Skip to content

Commit 0f8809f

Browse files
committed
Restrict variant keys to Identifiers and NumberLiterals
1 parent 3c7cd30 commit 0f8809f

11 files changed

+212
-55
lines changed

spec/fluent.ebnf

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,14 @@ SelectExpression ::= InlineExpression blank? "->" blank_inline? variant_list
7777
variant_list ::= Variant* DefaultVariant Variant* line_end
7878
Variant ::= line_end blank? VariantKey blank_inline? Value
7979
DefaultVariant ::= line_end blank? "*" VariantKey blank_inline? Value
80-
VariantKey ::= "[" blank? (NumberLiteral | VariantName) blank? "]"
81-
VariantName ::= word (blank word)*
80+
VariantKey ::= "[" blank? (NumberLiteral | Identifier) blank? "]"
8281

8382
/* Identifiers */
8483
Identifier ::= identifier
8584
TermIdentifier ::= "-" identifier
8685
VariableIdentifier ::= "$" identifier
8786
Function ::= [A-Z] [A-Z_?-]*
88-
89-
/* Tokens */
9087
identifier ::= [a-zA-Z] [a-zA-Z0-9_-]*
91-
word ::= (regular_char - backslash - "}" - "{" - "]" - "[" - "=")+
9288

9389
/* Characters */
9490
backslash ::= "\\"

syntax/ast.mjs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,6 @@ export class Identifier extends SyntaxNode {
194194
}
195195
}
196196

197-
export class VariantName extends Identifier {
198-
constructor(name) {
199-
super(name);
200-
this.type = "VariantName";
201-
}
202-
}
203-
204197
export class BaseComment extends Entry {
205198
constructor(content) {
206199
super();

syntax/grammar.mjs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -335,22 +335,11 @@ let VariantKey = defer(() =>
335335
maybe(blank),
336336
either(
337337
NumberLiteral,
338-
VariantName),
338+
Identifier),
339339
maybe(blank),
340340
string("]"))
341341
.map(element_at(2)));
342342

343-
let VariantName = defer(() =>
344-
sequence(
345-
word,
346-
repeat(
347-
sequence(
348-
blank,
349-
word)))
350-
.map(flatten(2))
351-
.map(join)
352-
.chain(into(FTL.VariantName)));
353-
354343
/* ----------- */
355344
/* Identifiers */
356345

@@ -380,8 +369,6 @@ let Function =
380369
.map(join)
381370
.chain(into(FTL.Function));
382371

383-
/* ------ */
384-
/* Tokens */
385372
let identifier =
386373
sequence(
387374
charset("a-zA-Z"),
@@ -390,18 +377,6 @@ let identifier =
390377
.map(flatten(1))
391378
.map(join);
392379

393-
let word = defer(() =>
394-
repeat1(
395-
and(
396-
not(string("=")),
397-
not(string("[")),
398-
not(string("]")),
399-
not(string("{")),
400-
not(string("}")),
401-
not(backslash),
402-
regular_char))
403-
.map(join));
404-
405380
/* ---------- */
406381
/* Characters */
407382

test/fixtures/leading_dots.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@
350350
{
351351
"type": "Variant",
352352
"key": {
353-
"type": "VariantName",
353+
"type": "Identifier",
354354
"name": "one"
355355
},
356356
"value": {
@@ -367,7 +367,7 @@
367367
{
368368
"type": "Variant",
369369
"key": {
370-
"type": "VariantName",
370+
"type": "Identifier",
371371
"name": "other"
372372
},
373373
"value": {

test/fixtures/member_expressions.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
},
2424
"key": {
25-
"type": "VariantName",
25+
"type": "Identifier",
2626
"name": "case"
2727
}
2828
}

test/fixtures/select_expressions.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ new-messages =
66
77
valid-selector =
88
{ -term.case ->
9-
*[ many words ] value
9+
*[key] value
1010
}
1111
1212
# ERROR

test/fixtures/select_expressions.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
{
4545
"type": "Variant",
4646
"key": {
47-
"type": "VariantName",
47+
"type": "Identifier",
4848
"name": "other"
4949
},
5050
"value": {
@@ -104,8 +104,8 @@
104104
{
105105
"type": "Variant",
106106
"key": {
107-
"type": "VariantName",
108-
"name": "many words"
107+
"type": "Identifier",
108+
"name": "key"
109109
},
110110
"value": {
111111
"type": "Pattern",
@@ -156,7 +156,7 @@
156156
{
157157
"type": "Variant",
158158
"key": {
159-
"type": "VariantName",
159+
"type": "Identifier",
160160
"name": "one"
161161
},
162162
"value": {
@@ -202,7 +202,7 @@
202202
{
203203
"type": "Variant",
204204
"key": {
205-
"type": "VariantName",
205+
"type": "Identifier",
206206
"name": "one"
207207
},
208208
"value": {
@@ -220,7 +220,7 @@
220220
{
221221
"type": "Variant",
222222
"key": {
223-
"type": "VariantName",
223+
"type": "Identifier",
224224
"name": "two"
225225
},
226226
"value": {

test/fixtures/sparse_entries.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
{
121121
"type": "Variant",
122122
"key": {
123-
"type": "VariantName",
123+
"type": "Identifier",
124124
"name": "one"
125125
},
126126
"value": {
@@ -137,7 +137,7 @@
137137
{
138138
"type": "Variant",
139139
"key": {
140-
"type": "VariantName",
140+
"type": "Identifier",
141141
"name": "two"
142142
},
143143
"value": {

test/fixtures/variant_keys.ftl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-simple-identifier =
2+
{
3+
*[key] value
4+
}
5+
6+
-identifier-surrounded-by-whitespace =
7+
{
8+
*[ key ] value
9+
}
10+
11+
-int-number =
12+
{
13+
*[1] value
14+
}
15+
16+
-float-number =
17+
{
18+
*[3.14] value
19+
}
20+
21+
# ERROR
22+
-invalid-identifier =
23+
{
24+
*[two words] value
25+
}
26+
27+
# ERROR
28+
-invalid-int =
29+
{
30+
*[1 apple] value
31+
}
32+
33+
# ERROR
34+
-invalid-int =
35+
{
36+
*[3.14 apples] value
37+
}

test/fixtures/variant_keys.json

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
{
2+
"type": "Resource",
3+
"body": [
4+
{
5+
"type": "Term",
6+
"id": {
7+
"type": "Identifier",
8+
"name": "-simple-identifier"
9+
},
10+
"value": {
11+
"type": "VariantList",
12+
"variants": [
13+
{
14+
"type": "Variant",
15+
"key": {
16+
"type": "Identifier",
17+
"name": "key"
18+
},
19+
"value": {
20+
"type": "Pattern",
21+
"elements": [
22+
{
23+
"type": "TextElement",
24+
"value": "value"
25+
}
26+
]
27+
},
28+
"default": true
29+
}
30+
]
31+
},
32+
"attributes": [],
33+
"comment": null
34+
},
35+
{
36+
"type": "Term",
37+
"id": {
38+
"type": "Identifier",
39+
"name": "-identifier-surrounded-by-whitespace"
40+
},
41+
"value": {
42+
"type": "VariantList",
43+
"variants": [
44+
{
45+
"type": "Variant",
46+
"key": {
47+
"type": "Identifier",
48+
"name": "key"
49+
},
50+
"value": {
51+
"type": "Pattern",
52+
"elements": [
53+
{
54+
"type": "TextElement",
55+
"value": "value"
56+
}
57+
]
58+
},
59+
"default": true
60+
}
61+
]
62+
},
63+
"attributes": [],
64+
"comment": null
65+
},
66+
{
67+
"type": "Term",
68+
"id": {
69+
"type": "Identifier",
70+
"name": "-int-number"
71+
},
72+
"value": {
73+
"type": "VariantList",
74+
"variants": [
75+
{
76+
"type": "Variant",
77+
"key": {
78+
"type": "NumberLiteral",
79+
"value": "1"
80+
},
81+
"value": {
82+
"type": "Pattern",
83+
"elements": [
84+
{
85+
"type": "TextElement",
86+
"value": "value"
87+
}
88+
]
89+
},
90+
"default": true
91+
}
92+
]
93+
},
94+
"attributes": [],
95+
"comment": null
96+
},
97+
{
98+
"type": "Term",
99+
"id": {
100+
"type": "Identifier",
101+
"name": "-float-number"
102+
},
103+
"value": {
104+
"type": "VariantList",
105+
"variants": [
106+
{
107+
"type": "Variant",
108+
"key": {
109+
"type": "NumberLiteral",
110+
"value": "3.14"
111+
},
112+
"value": {
113+
"type": "Pattern",
114+
"elements": [
115+
{
116+
"type": "TextElement",
117+
"value": "value"
118+
}
119+
]
120+
},
121+
"default": true
122+
}
123+
]
124+
},
125+
"attributes": [],
126+
"comment": null
127+
},
128+
{
129+
"type": "Comment",
130+
"content": "ERROR"
131+
},
132+
{
133+
"type": "Junk",
134+
"annotations": [],
135+
"content": "-invalid-identifier =\n {\n *[two words] value\n }\n"
136+
},
137+
{
138+
"type": "Comment",
139+
"content": "ERROR"
140+
},
141+
{
142+
"type": "Junk",
143+
"annotations": [],
144+
"content": "-invalid-int =\n {\n *[1 apple] value\n }\n"
145+
},
146+
{
147+
"type": "Comment",
148+
"content": "ERROR"
149+
},
150+
{
151+
"type": "Junk",
152+
"annotations": [],
153+
"content": "-invalid-int =\n {\n *[3.14 apples] value\n }\n"
154+
}
155+
]
156+
}

0 commit comments

Comments
 (0)