Skip to content

Commit 28ca56a

Browse files
committed
Add Parameterized Terms
1 parent 378ab1f commit 28ca56a

10 files changed

+286
-17
lines changed

spec/fluent.ebnf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ MessageReference ::= Identifier
6565
TermReference ::= "-" Identifier
6666
VariableReference ::= "$" Identifier
6767
FunctionReference ::= Identifier
68-
CallExpression ::= FunctionReference blank? "(" blank? argument_list blank? ")"
68+
CallExpression ::= Callee blank? "(" blank? argument_list blank? ")"
69+
Callee ::= FunctionReference
70+
| TermReference
6971
argument_list ::= (Argument blank? "," blank?)* Argument?
7072
Argument ::= NamedArgument
7173
| InlineExpression

spec/valid.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,6 @@ Invalid Select Expressions:
5454

5555
SelectExpression.selector > MessageReference
5656
SelectExpression.selector > TermReference
57+
SelectExpression.selector > CallExpression.callee > TermReference
5758
SelectExpression.selector > VariantExpression
5859
SelectExpression.selector > AttributeExpression.ref > MessageReference

syntax/abstract.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ export function list_into(Type) {
6868
let invalid_selector_found =
6969
selector instanceof FTL.MessageReference
7070
|| selector instanceof FTL.TermReference
71+
|| (selector instanceof FTL.CallExpression
72+
&& selector.callee instanceof FTL.TermReference)
7173
|| selector instanceof FTL.VariantExpression
7274
|| (selector instanceof FTL.AttributeExpression
7375
&& selector.ref instanceof FTL.MessageReference);

syntax/grammar.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ let FunctionReference = defer(() =>
243243

244244
let CallExpression = defer(() =>
245245
sequence(
246-
FunctionReference.abstract,
246+
Callee.abstract,
247247
maybe(blank),
248248
string("("),
249249
maybe(blank),
@@ -253,6 +253,11 @@ let CallExpression = defer(() =>
253253
.map(keep_abstract)
254254
.chain(list_into(FTL.CallExpression)));
255255

256+
let Callee =
257+
either(
258+
FunctionReference,
259+
TermReference);
260+
256261
let argument_list = defer(() =>
257262
sequence(
258263
repeat(

test/fixtures/call_expressions.ftl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
## Callees
22

33
function-callee = {FUNCTION()}
4+
term-callee = {-term()}
45
56
# ERROR Equivalent to a MessageReference callee.
67
mixed-case-callee = {Function()}
78
89
# ERROR MessageReference is not a valid callee.
910
message-callee = {message()}
10-
# ERROR TermReference is not a valid callee.
11-
term-callee = {-term()}
1211
# ERROR VariableReference is not a valid callee.
1312
variable-callee = {$variable()}
1413

test/fixtures/call_expressions.json

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,35 @@
3434
"attributes": [],
3535
"comment": null
3636
},
37+
{
38+
"type": "Message",
39+
"id": {
40+
"type": "Identifier",
41+
"name": "term-callee"
42+
},
43+
"value": {
44+
"type": "Pattern",
45+
"elements": [
46+
{
47+
"type": "Placeable",
48+
"expression": {
49+
"type": "CallExpression",
50+
"callee": {
51+
"type": "TermReference",
52+
"id": {
53+
"type": "Identifier",
54+
"name": "term"
55+
}
56+
},
57+
"positional": [],
58+
"named": []
59+
}
60+
}
61+
]
62+
},
63+
"attributes": [],
64+
"comment": null
65+
},
3766
{
3867
"type": "Comment",
3968
"content": "ERROR Equivalent to a MessageReference callee."
@@ -52,15 +81,6 @@
5281
"annotations": [],
5382
"content": "message-callee = {message()}\n"
5483
},
55-
{
56-
"type": "Comment",
57-
"content": "ERROR TermReference is not a valid callee."
58-
},
59-
{
60-
"type": "Junk",
61-
"annotations": [],
62-
"content": "term-callee = {-term()}\n"
63-
},
6484
{
6585
"type": "Comment",
6686
"content": "ERROR VariableReference is not a valid callee."

test/fixtures/select_expressions.ftl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,29 @@ new-messages =
44
*[other] {""}Other
55
}
66
7-
valid-selector =
7+
valid-selector-term-attribute =
88
{ -term.case ->
99
*[key] value
1010
}
1111
1212
# ERROR
13-
invalid-selector =
13+
invalid-selector-term-value =
14+
{ -term ->
15+
*[key] value
16+
}
17+
18+
# ERROR
19+
invalid-selector-term-variant =
1420
{ -term[case] ->
1521
*[key] value
1622
}
1723
24+
# ERROR
25+
invalid-selector-term-call =
26+
{ -term(case: "nominative") ->
27+
*[key] value
28+
}
29+
1830
empty-variant =
1931
{ 1 ->
2032
*[one] {""}

test/fixtures/select_expressions.json

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"type": "Message",
8181
"id": {
8282
"type": "Identifier",
83-
"name": "valid-selector"
83+
"name": "valid-selector-term-attribute"
8484
},
8585
"value": {
8686
"type": "Pattern",
@@ -136,7 +136,25 @@
136136
{
137137
"type": "Junk",
138138
"annotations": [],
139-
"content": "invalid-selector =\n { -term[case] ->\n *[key] value\n }\n"
139+
"content": "invalid-selector-term-value =\n { -term ->\n *[key] value\n }\n"
140+
},
141+
{
142+
"type": "Comment",
143+
"content": "ERROR"
144+
},
145+
{
146+
"type": "Junk",
147+
"annotations": [],
148+
"content": "invalid-selector-term-variant =\n { -term[case] ->\n *[key] value\n }\n"
149+
},
150+
{
151+
"type": "Comment",
152+
"content": "ERROR"
153+
},
154+
{
155+
"type": "Junk",
156+
"annotations": [],
157+
"content": "invalid-selector-term-call =\n { -term(case: \"nominative\") ->\n *[key] value\n }\n"
140158
},
141159
{
142160
"type": "Message",

test/fixtures/term_parameters.ftl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-term = { $arg ->
2+
*[key] Value
3+
}
4+
5+
key01 = { -term }
6+
key02 = { -term() }
7+
key03 = { -term(arg: 1) }
8+
key04 = { -term("positional", narg1: 1, narg2: 2) }

test/fixtures/term_parameters.json

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
{
2+
"type": "Resource",
3+
"body": [
4+
{
5+
"type": "Term",
6+
"id": {
7+
"type": "Identifier",
8+
"name": "term"
9+
},
10+
"value": {
11+
"type": "Pattern",
12+
"elements": [
13+
{
14+
"type": "Placeable",
15+
"expression": {
16+
"type": "SelectExpression",
17+
"selector": {
18+
"type": "VariableReference",
19+
"id": {
20+
"type": "Identifier",
21+
"name": "arg"
22+
}
23+
},
24+
"variants": [
25+
{
26+
"type": "Variant",
27+
"key": {
28+
"type": "Identifier",
29+
"name": "key"
30+
},
31+
"value": {
32+
"type": "Pattern",
33+
"elements": [
34+
{
35+
"type": "TextElement",
36+
"value": "Value"
37+
}
38+
]
39+
},
40+
"default": true
41+
}
42+
]
43+
}
44+
}
45+
]
46+
},
47+
"attributes": [],
48+
"comment": null
49+
},
50+
{
51+
"type": "Message",
52+
"id": {
53+
"type": "Identifier",
54+
"name": "key01"
55+
},
56+
"value": {
57+
"type": "Pattern",
58+
"elements": [
59+
{
60+
"type": "Placeable",
61+
"expression": {
62+
"type": "TermReference",
63+
"id": {
64+
"type": "Identifier",
65+
"name": "term"
66+
}
67+
}
68+
}
69+
]
70+
},
71+
"attributes": [],
72+
"comment": null
73+
},
74+
{
75+
"type": "Message",
76+
"id": {
77+
"type": "Identifier",
78+
"name": "key02"
79+
},
80+
"value": {
81+
"type": "Pattern",
82+
"elements": [
83+
{
84+
"type": "Placeable",
85+
"expression": {
86+
"type": "CallExpression",
87+
"callee": {
88+
"type": "TermReference",
89+
"id": {
90+
"type": "Identifier",
91+
"name": "term"
92+
}
93+
},
94+
"positional": [],
95+
"named": []
96+
}
97+
}
98+
]
99+
},
100+
"attributes": [],
101+
"comment": null
102+
},
103+
{
104+
"type": "Message",
105+
"id": {
106+
"type": "Identifier",
107+
"name": "key03"
108+
},
109+
"value": {
110+
"type": "Pattern",
111+
"elements": [
112+
{
113+
"type": "Placeable",
114+
"expression": {
115+
"type": "CallExpression",
116+
"callee": {
117+
"type": "TermReference",
118+
"id": {
119+
"type": "Identifier",
120+
"name": "term"
121+
}
122+
},
123+
"positional": [],
124+
"named": [
125+
{
126+
"type": "NamedArgument",
127+
"name": {
128+
"type": "Identifier",
129+
"name": "arg"
130+
},
131+
"value": {
132+
"type": "NumberLiteral",
133+
"value": "1"
134+
}
135+
}
136+
]
137+
}
138+
}
139+
]
140+
},
141+
"attributes": [],
142+
"comment": null
143+
},
144+
{
145+
"type": "Message",
146+
"id": {
147+
"type": "Identifier",
148+
"name": "key04"
149+
},
150+
"value": {
151+
"type": "Pattern",
152+
"elements": [
153+
{
154+
"type": "Placeable",
155+
"expression": {
156+
"type": "CallExpression",
157+
"callee": {
158+
"type": "TermReference",
159+
"id": {
160+
"type": "Identifier",
161+
"name": "term"
162+
}
163+
},
164+
"positional": [
165+
{
166+
"type": "StringLiteral",
167+
"value": "positional"
168+
}
169+
],
170+
"named": [
171+
{
172+
"type": "NamedArgument",
173+
"name": {
174+
"type": "Identifier",
175+
"name": "narg1"
176+
},
177+
"value": {
178+
"type": "NumberLiteral",
179+
"value": "1"
180+
}
181+
},
182+
{
183+
"type": "NamedArgument",
184+
"name": {
185+
"type": "Identifier",
186+
"name": "narg2"
187+
},
188+
"value": {
189+
"type": "NumberLiteral",
190+
"value": "2"
191+
}
192+
}
193+
]
194+
}
195+
}
196+
]
197+
},
198+
"attributes": [],
199+
"comment": null
200+
}
201+
]
202+
}

0 commit comments

Comments
 (0)