我正在尝试为一个已经离开递归的简单语言编写语法,但我真的不明白如何。
基本上我的语法看起来像这样:
expr: expr('@'TYPE)? '.' ID '(' (expr ',')∗ ')'
| expr '+' expr
| ID
| INTEGER
| STRING
INTEGER : ('0'..'9')+;
STRING : '"' ('a'..'z' | 'A'..'Z' | '0'..'9')* '"';
TYPE : ('String' | 'Bool' | 'Int')
ID : ('a'..'z' | 'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'9')*;
还有更多内容,但这是我试图删除的左递归的重要部分。
我一直关注Wikipedia关于它,这就是我最终的结果:
expr: function
| add
| ID
| INTEGER
| STRING
function : ( ('@'TYPE)? '.' ID '(' (expr',')* ')' function)?;
add : (('+' expr) add)?;
然而,antlr仍然说它是递归的,我无法让它识别我想要的语言。任何人都可以帮我解释一下如何删除左递归吗?
答案 0 :(得分:4)
function
和add
都匹配ε(空字符串)。删除规则末尾的?
,你没问题:
function
: ('@'TYPE)? '.' ID '(' (expr',')* ')' function
;
add
: '+' expr add
;
请注意(expr',')*
表示表达式的“列表”必须始终以逗号结尾。也许以下更合适:
(expr (',' expr)*)?
匹配ε或由逗号分隔的一个或多个expr
。
请注意左递归语法:
expr ::= expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| '-' expr
| function
| INTEGER
| STRING
| IDENTIFIER
| '(' expr ')'
可以翻译成:
expr
: addExpr
;
addExpr
: multExpr (('+' | '-') multExpr)*
;
multExpr
: unaryExpr (('*' | '/') unaryExpr)*
;
unaryExpr
: '-' atom
| atom
;
atom
: function
| INTEGER
| STRING
| IDENTIFIER
| '(' expr ')'
;
其中ANTLR没有问题(即不再有左递归)。