控制参数 slurping

Controlling Parameter Slurping

我正在尝试编写一个不使用括号支持函数调用的语法:

f x, y

与 Haskell 一样,我希望函数调用能够尽可能少地吸收它们的参数。也就是我要

g 5 + 3

意思是

(g 5) + 3

而不是

g (5 + 3)

不幸的是,我正在使用此语法进行第二次解析:

grammar Parameters;

expr
  : '(' expr ')'
  | expr MULTIPLICATIVE_OPERATOR expr
  | expr ADDITIVE_OPERATOR expr
  | ID (expr (',' expr)*?)??
  | INT
  ;

MULTIPLICATIVE_OPERATOR: [*/%];
ADDITIVE_OPERATOR: '+';

ID: [a..z]+;
INT: '-'? [0-9]+;
WHITESPACE: [ \t\n\r]+ -> skip;

我得到的解析树是这样的:

我原以为首先列出的子规则会被首先尝试。在这种情况下,expr ADDITIVE_OPERATOR expr 出现在 ID 子规则之前,那么为什么 ID 子规则具有更高的优先级?

在这种情况下,ANTLR 没有进行正确的规则转换(以消除左递归和处理优先级):

expr
    : expr_1[0]
    ;

expr_1[int p]
    : ('(' expr_1[0] ')' | INT | ID (expr_1[0] (',' expr_1[0])*?)??)
      ( {4 >= $p}? MULTIPLICATIVE_OPERATOR expr_1[5]
      | {3 >= $p}? ADDITIVE_OPERATOR expr_1[4]
      )*
    ;

导致 (expr (expr_1 a (expr_1 5 + (expr_1 3))))

正确的是:

expr
    : expr_1[0]
    ;

expr_1[int p]
  : ('(' expr_1[0] ')' | INT | ID (expr_1[5] (',' expr_1[5])*?)??)
  ( {4 >= $p}? MULTIPLICATIVE_OPERATOR expr_1[5]
  | {3 >= $p}? ADDITIVE_OPERATOR expr_1[4]
  )*
  ;

导致(expr (expr_1 a (expr_1 5) + (expr_1 3)))

我不确定这是 ANTLR4 中的错误还是转换算法的权衡。也许应该给 ANTLR4 jira 写一个问题。

要解决您的问题,您只需将正确转换的语法放入您的代码中,它应该可以工作。规则转换的解释可以在第 249ff 页的 "The Definitive ANTLR4 Reference" 中找到(也许在网络上的某个地方)。