如何消除左递归?

发布于 2024-10-18 17:44:33 字数 747 浏览 2 评论 0原文

我正在尝试为一种保留了递归的简单语言编写语法,但我不太明白如何实现。

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

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')*;

还有更多内容,但这是我试图删除的左递归的重要部分。

我一直在维基百科上查找有关它的信息,这就是我最终得到的结果:

expr: function
| add
| ID
| INTEGER
| STRING

function : ( ('@'TYPE)? '.' ID '(' (expr',')* ')'  function)?;
add : (('+' expr) add)?;

但是antlr仍然说它是左递归的,我无法让它识别我想要的语言。谁能帮我解释一下如何删除左递归?

I'm trying to write a grammar for a simple language that has left recursion, but I don't really understand how.

Basically my grammar looks like this:

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')*;

There is more to it but that's the important part with the left recursion I'm trying to remove.

I've been looking on the Wikipedia about it, and this is what I ended up with:

expr: function
| add
| ID
| INTEGER
| STRING

function : ( ('@'TYPE)? '.' ID '(' (expr',')* ')'  function)?;
add : (('+' expr) add)?;

However antlr still says it's left recursive and I can't get it to recognize the language I want it to. Could anyone help me out and explain to me how to remove the left recursion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

峩卟喜欢 2024-10-25 17:44:33

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

Both function and add match ε (empty string). Remove the ? at the end of the rules and you're fine:

function 
  :  ('@'TYPE)? '.' ID '(' (expr',')* ')'  function
  ;

add 
  :  '+' expr add
  ;

Note that (expr',')* dictates that a "list" of expressions must always end with a comma. Perhaps the following is more appropriate:

(expr (',' expr)*)?

which matches ε or one or more expr separated by a comma.

Note that the left recursive grammar:

expr ::= expr '+' expr
      |  expr '-' expr
      |  expr '*' expr
      |  expr '/' expr
      |  '-' expr
      |  function
      |  INTEGER
      |  STRING
      |  IDENTIFIER
      |  '(' expr ')'

could be translated into:

expr
  :  addExpr
  ;

addExpr
  :  multExpr (('+' | '-') multExpr)*
  ;

multExpr
  :  unaryExpr (('*' | '/') unaryExpr)*
  ;

unaryExpr
  :  '-' atom
  |  atom
  ;

atom
  :  function
  |  INTEGER
  |  STRING
  |  IDENTIFIER
  |  '(' expr ')'
  ;

where ANTLR has no problems with (ie. no left recursion anymore).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文