Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fluent-syntax/src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function getErrorMessage(code, args) {
case "E0016":
return "Message references cannot be used as selectors";
case "E0017":
return "Variants cannot be used as selectors";
return "Terms cannot be used as selectors";
case "E0018":
return "Attributes of messages cannot be used as selectors";
case "E0019":
Expand Down
67 changes: 36 additions & 31 deletions fluent-syntax/src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -655,12 +655,18 @@ export default class FluentParser {
throw new ParseError("E0016");
}

if (selector.type === "AttributeExpression" &&
selector.ref.type === "MessageReference") {
if (selector.type === "AttributeExpression"
&& selector.ref.type === "MessageReference") {
throw new ParseError("E0018");
}

if (selector.type === "VariantExpression") {
if (selector.type === "TermReference"
|| selector.type === "VariantExpression") {
throw new ParseError("E0017");
}

if (selector.type === "CallExpression"
&& selector.callee.type === "TermReference") {
throw new ParseError("E0017");
}

Expand All @@ -672,8 +678,8 @@ export default class FluentParser {

const variants = this.getVariants(ps, {allowVariantList: false});
return new AST.SelectExpression(selector, variants);
} else if (selector.type === "AttributeExpression" &&
selector.ref.type === "TermReference") {
} else if (selector.type === "AttributeExpression"
&& selector.ref.type === "TermReference") {
throw new ParseError("E0019");
}

Expand All @@ -685,60 +691,59 @@ export default class FluentParser {
return this.getPlaceable(ps);
}

const literal = this.getLiteral(ps);

if (literal.type !== "MessageReference"
&& literal.type !== "TermReference") {
return literal;
const selector = this.getLiteral(ps);
switch (selector.type) {
case "StringLiteral":
case "NumberLiteral":
case "VariableReference":
return selector;
}

const ch = ps.currentChar;

if (ch === ".") {
if (ps.currentChar === ".") {
ps.next();

const attr = this.getIdentifier(ps);
return new AST.AttributeExpression(literal, attr);
return new AST.AttributeExpression(selector, attr);
}

if (ch === "[") {
if (ps.currentChar === "[") {
ps.next();

if (literal.type === "MessageReference") {
if (selector.type === "MessageReference") {
throw new ParseError("E0024");
}

const key = this.getVariantKey(ps);

ps.expectChar("]");

return new AST.VariantExpression(literal, key);
return new AST.VariantExpression(selector, key);
}

if (ch === "(") {
if (ps.currentChar === "(") {
ps.next();

if (!/^[A-Z][A-Z_?-]*$/.test(literal.id.name)) {
throw new ParseError("E0008");
if (selector.type === "MessageReference") {
if (/^[A-Z][A-Z_?-]*$/.test(selector.id.name)) {
// The callee is a Function.
var func = new AST.FunctionReference(selector.id);
if (this.withSpans) {
func.addSpan(selector.span.start, selector.span.end);
}
} else {
// Messages can't be callees.
throw new ParseError("E0008");
}
}

const args = this.getCallArgs(ps);

ps.expectChar(")");

const func = new AST.FunctionReference(literal.id);
if (this.withSpans) {
func.addSpan(literal.span.start, literal.span.end);
}

return new AST.CallExpression(
func,
func || selector,
args.positional,
args.named,
);
}

return literal;
return selector;
}

getCallArg(ps) {
Expand Down
6 changes: 3 additions & 3 deletions fluent-syntax/src/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,13 @@ function serializeVariantExpression(expr) {


function serializeCallExpression(expr) {
const fun = serializeExpression(expr.callee);
const callee = serializeExpression(expr.callee);
const positional = expr.positional.map(serializeExpression).join(", ");
const named = expr.named.map(serializeNamedArgument).join(", ");
if (expr.positional.length > 0 && expr.named.length > 0) {
return `${fun}(${positional}, ${named})`;
return `${callee}(${positional}, ${named})`;
}
return `${fun}(${positional || named})`;
return `${callee}(${positional || named})`;
}


Expand Down
13 changes: 6 additions & 7 deletions fluent-syntax/test/fixtures_behavior/term.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,21 @@ key2 =

key3 = Test { -brand-short-name[accusative] }

key4 = { -brand() }

# ~ERROR E0004, pos 306, args "0-9"
err1 =
{ $foo ->
[one] Foo
*[-other] Foo 2
}
# ~ERROR E0004, pos 285, args "0-9"

# ~ERROR E0004, pos 336, args "a-zA-Z"
err2 = { $-foo }
# ~ERROR E0004, pos 315, args "a-zA-Z"

err4 = { -brand() }
# ~ERROR E0008, pos 339

-err5 =
# ~ERROR E0006, pos 351, args "err5"
-err5 =

# ~ERROR E0006, pos 360, args "err6"
-err6 =
.attr = Attribute
# ~ERROR E0006, pos 360, args "err6"
3 changes: 1 addition & 2 deletions fluent-syntax/test/fixtures_reference/call_expressions.ftl
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
## Callees

function-callee = {FUNCTION()}
term-callee = {-term()}

# ERROR Equivalent to a MessageReference callee.
mixed-case-callee = {Function()}

# ERROR MessageReference is not a valid callee.
message-callee = {message()}
# ERROR TermReference is not a valid callee.
term-callee = {-term()}
# ERROR VariableReference is not a valid callee.
variable-callee = {$variable()}

Expand Down
38 changes: 29 additions & 9 deletions fluent-syntax/test/fixtures_reference/call_expressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,35 @@
"attributes": [],
"comment": null
},
{
"type": "Message",
"id": {
"type": "Identifier",
"name": "term-callee"
},
"value": {
"type": "Pattern",
"elements": [
{
"type": "Placeable",
"expression": {
"type": "CallExpression",
"callee": {
"type": "TermReference",
"id": {
"type": "Identifier",
"name": "term"
}
},
"positional": [],
"named": []
}
}
]
},
"attributes": [],
"comment": null
},
{
"type": "Comment",
"content": "ERROR Equivalent to a MessageReference callee."
Expand All @@ -52,15 +81,6 @@
"annotations": [],
"content": "message-callee = {message()}\n"
},
{
"type": "Comment",
"content": "ERROR TermReference is not a valid callee."
},
{
"type": "Junk",
"annotations": [],
"content": "term-callee = {-term()}\n"
},
{
"type": "Comment",
"content": "ERROR VariableReference is not a valid callee."
Expand Down
16 changes: 14 additions & 2 deletions fluent-syntax/test/fixtures_reference/select_expressions.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,29 @@ new-messages =
*[other] {""}Other
}

valid-selector =
valid-selector-term-attribute =
{ -term.case ->
*[key] value
}

# ERROR
invalid-selector =
invalid-selector-term-value =
{ -term ->
*[key] value
}

# ERROR
invalid-selector-term-variant =
{ -term[case] ->
*[key] value
}

# ERROR
invalid-selector-term-call =
{ -term(case: "nominative") ->
*[key] value
}

empty-variant =
{ 1 ->
*[one] {""}
Expand Down
22 changes: 20 additions & 2 deletions fluent-syntax/test/fixtures_reference/select_expressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"type": "Message",
"id": {
"type": "Identifier",
"name": "valid-selector"
"name": "valid-selector-term-attribute"
},
"value": {
"type": "Pattern",
Expand Down Expand Up @@ -137,7 +137,25 @@
{
"type": "Junk",
"annotations": [],
"content": "invalid-selector =\n { -term[case] ->\n *[key] value\n }\n"
"content": "invalid-selector-term-value =\n { -term ->\n *[key] value\n }\n"
},
{
"type": "Comment",
"content": "ERROR"
},
{
"type": "Junk",
"annotations": [],
"content": "invalid-selector-term-variant =\n { -term[case] ->\n *[key] value\n }\n"
},
{
"type": "Comment",
"content": "ERROR"
},
{
"type": "Junk",
"annotations": [],
"content": "invalid-selector-term-call =\n { -term(case: \"nominative\") ->\n *[key] value\n }\n"
},
{
"type": "Message",
Expand Down
8 changes: 8 additions & 0 deletions fluent-syntax/test/fixtures_reference/term_parameters.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-term = { $arg ->
*[key] Value
}

key01 = { -term }
key02 = { -term() }
key03 = { -term(arg: 1) }
key04 = { -term("positional", narg1: 1, narg2: 2) }
Loading