你如何删除左递归?

时间:2011-02-22 16:09:59

标签: antlr antlr3

我正在尝试为一个已经离开递归的简单语言编写语法,但我真的不明白如何。

基本上我的语法看起来像这样:

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仍然说它是递归的,我无法让它识别我想要的语言。任何人都可以帮我解释一下如何删除左递归吗?

1 个答案:

答案 0 :(得分:4)

functionadd都匹配ε(空字符串)。删除规则末尾的?,你没问题:

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没有问题(即不再有左递归)。