我正在尝试扩展the grammar of the Tiny Language以将赋值视为表达式。因此,编写
是有效的a = b = 1; // -> a = (b = 1)
a = 2 * (b = 1); // contrived but valid
a = 1 = 2; // invalid
分配在两个方面与其他运营商不同。这是正确的联想(并不是一件大事),它的左侧必须是一个变量。所以我改变了这样的语法
statement: assignmentExpr | functionCall ...;
assignmentExpr: Identifier indexes? '=' expression;
expression: assignmentExpr | condExpr;
它不起作用,因为它包含非LL(*)决定。我也试过这个变种:
assignmentExpr: Identifier indexes? '=' (expression | condExpr);
但我得到了同样的错误。我对
感兴趣答案 0 :(得分:2)
我认为你可以改变你的语法来达到同样的目的,而不使用句法谓词:
statement: Expr ';' | functionCall ';'...;
Expr: Identifier indexes? '=' Expr | condExpr ;
condExpr: .... and so on;
我考虑到这个想法改变了Bart的例子:
grammar TL;
options {
output=AST;
}
tokens {
ROOT;
}
parse
: stat+ EOF -> ^(ROOT stat+)
;
stat
: expr ';'
;
expr
: Id Assign expr -> ^(Assign Id expr)
| add
;
add
: mult (('+' | '-')^ mult)*
;
mult
: atom (('*' | '/')^ atom)*
;
atom
: Id
| Num
| '('! expr ')' !
;
Assign : '=' ;
Comment : '//' ~('\r' | '\n')* {skip();};
Id : 'a'..'z'+;
Num : '0'..'9'+;
Space : (' ' | '\t' | '\r' | '\n')+ {skip();};
输入:
a=b=4;
a = 2 * (b = 1);
你得到以下解析树:
答案 1 :(得分:1)
这里的关键是你需要“确保”解析器在表达式中,前面有一些东西满足表达式。这可以使用句法谓词(( ... )=>
和add
规则中的mult
部分)来完成。
快速演示:
grammar TL;
options {
output=AST;
}
tokens {
ROOT;
ASSIGN;
}
parse
: stat* EOF -> ^(ROOT stat+)
;
stat
: expr ';' -> expr
;
expr
: add
;
add
: mult ((('+' | '-') mult)=> ('+' | '-')^ mult)*
;
mult
: atom ((('*' | '/') atom)=> ('*' | '/')^ atom)*
;
atom
: (Id -> Id) ('=' expr -> ^(ASSIGN Id expr))?
| Num
| '(' expr ')' -> expr
;
Comment : '//' ~('\r' | '\n')* {skip();};
Id : 'a'..'z'+;
Num : '0'..'9'+;
Space : (' ' | '\t' | '\r' | '\n')+ {skip();};
将解析输入:
a = b = 1; // -> a = (b = 1)
a = 2 * (b = 1); // contrived but valid
进入以下AST: