Skip to content

Commit 9333554

Browse files
committed
Restrict variant keys to Identifiers and NumberLiterals
1 parent b9f3b77 commit 9333554

11 files changed

+212
-54
lines changed

spec/fluent.ebnf

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,14 @@ SelectExpression ::= InlineExpression inline_space? "->" variant_list
6262
variant_list ::= inline_space? Variant* DefaultVariant Variant* break_indent
6363
Variant ::= break_indent VariantKey inline_space? Value
6464
DefaultVariant ::= break_indent "*" VariantKey inline_space? Value
65-
VariantKey ::= "[" inline_space? (NumberLiteral | VariantName) inline_space? "]"
66-
VariantName ::= word (inline_space word)*
65+
VariantKey ::= "[" inline_space? (NumberLiteral | Identifier) inline_space? "]"
6766

6867
/* Identifiers */
6968
Identifier ::= identifier
7069
TermIdentifier ::= "-" identifier
7170
VariableIdentifier ::= "$" identifier
7271
Function ::= [A-Z] [A-Z_?-]*
73-
74-
/* Tokens */
7572
identifier ::= [a-zA-Z] [a-zA-Z0-9_-]*
76-
word ::= (regular_char - backslash - "}" - "{" - "]" - "[")+
7773

7874
/* Characters */
7975
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 & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -337,22 +337,11 @@ let VariantKey = defer(() =>
337337
maybe(inline_space),
338338
either(
339339
NumberLiteral,
340-
VariantName),
340+
Identifier),
341341
maybe(inline_space),
342342
string("]"))
343343
.map(element_at(2)));
344344

345-
let VariantName = defer(() =>
346-
sequence(
347-
word,
348-
repeat(
349-
sequence(
350-
inline_space,
351-
word)))
352-
.map(flatten(2))
353-
.map(join)
354-
.chain(into(FTL.VariantName)));
355-
356345
/* ----------- */
357346
/* Identifiers */
358347

@@ -382,8 +371,6 @@ let Function =
382371
.map(join)
383372
.chain(into(FTL.Function));
384373

385-
/* ------ */
386-
/* Tokens */
387374
let identifier =
388375
sequence(
389376
charset("a-zA-Z"),
@@ -392,17 +379,6 @@ let identifier =
392379
.map(flatten(1))
393380
.map(join);
394381

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

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)