antlr - 如何解析带括号的层次结构根?

标签 antlr

我正在尝试使用 ANTLR 解析值。这是我的语法的相关部分:

root : IDENTIFIER | SELF | literal | constructor | call | indexer;

hierarchy : root (SUB^ (IDENTIFIER | call | indexer))*;

factor  : hierarchy ((MULT^ | DIV^ | MODULO^) hierarchy)*;

sum : factor ((PLUS^ | MINUS^) factor)*;

comparison  : sum (comparison_operator^ sum)*;

value   : comparison | '(' value ')';

我不会描述每个标记或规则,因为它们的名称已经很好地解释了它们的作用。这个语法运行良好并且可以编译,允许我使用 value 进行解析,例如:
a.b[c(5).d[3] * e()] < e("f")

Interpretation

唯一剩下的值(value)识别就是能够有括号的层次结构根。例如:
(a.b).c
(3 < d()).e
...

天真地,没有太多期望,我尝试将以下替代方案添加到我的 root 中。规则:
root : ... | '(' value ')';

然而,这打破了 value由于非 LL(*)ism 的规则:
rule value has non-LL(*) decision due to recursive rule invocations reachable
from alts 1,2.  Resolve by left-factoring or using syntactic predicates or using 
backtrack=true option.

Break

即使在阅读了 The Definitive ANTLR Reference 的大部分内容之后,我仍然不明白这些错误。但是,我所理解的是,在看到括号开头时,ANTLR 无法知道它是在查看括号中的值的开头,还是在括号中的根的开头。

如何明确定义带括号的层次结构根的行为?

编辑 :根据要求,附加规则:
parameter : type IDENTIFIER -> ^(PARAMETER ^(type IDENTIFIER));

constructor : NEW type PAREN_OPEN (arguments+=value (SEPARATOR arguments+=value)*)? PAREN_CLOSE -> ^(CONSTRUCTOR type ^(ARGUMENTS $arguments*)?);

call : IDENTIFIER PAREN_OPEN (values+=value (SEPARATOR values+=value)*)? PAREN_CLOSE -> ^(CALL IDENTIFIER ^(ARGUMENTS $values*)?);

indexer : IDENTIFIER INDEX_START (values+=value (SEPARATOR values+=value)*)? INDEX_END -> ^(INDEXER IDENTIFIER ^(ARGUMENTS $values*));

最佳答案

删除 '(' value ')'来自 value并将其放入 root :

root : IDENTIFIER | SELF | literal | constructor | call | indexer | '(' value ')';

...

value : comparison;

现在 (a.b).c将导致以下解析:

enter image description here

(3 < d()).e在:

enter image description here

当然,您可能希望省略 AST 中的括号:
root : IDENTIFIER | SELF | literal | constructor | call | indexer | '('! value ')'!;

此外,您不需要在 List 中附加 token 。使用 +=在您的解析器规则中。下列:
call 
 : IDENTIFIER PAREN_OPEN (values+=value (SEPARATOR values+=value)*)? PAREN_CLOSE 
   -> ^(CALL IDENTIFIER ^(ARGUMENTS $values*)?)
 ;

可以改写为:
call 
 : IDENTIFIER PAREN_OPEN (value (SEPARATOR value)*)? PAREN_CLOSE 
   -> ^(CALL IDENTIFIER ^(ARGUMENTS value*)?)
 ;

编辑

您的主要问题是可以以两种(或更多!)方式解析某些输入。例如,输入 (a)可以通过您的 value 的替代 1 和 2 进行解析规则:
value 
 : comparison    // alternative 1
 | '(' value ')' // alternative 2
 ;

运行你的解析器规则:a comparison (备选方案1)可以匹配(a)因为它匹配 root规则,它依次匹配 '(' value ')' .但这也是替代2匹配的内容!你有它:解析器“看到”一个输入,两个不同的
解析并报告这种歧义。

关于antlr - 如何解析带括号的层次结构根?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10405668/

相关文章:

java - 在 Antlr 中使用访问者编辑 AST

antlr - 为什么 ANTLR 要求标记所有替代品或不标注替代品?

gradle - 如何使用Gradle通过导入构建ANTLR 3语法?

antlr - antlr4语法中 "~"运算符的意义

antlr - 如何在条件规则重写中使用 ANTLR 词法分析器标记值

ANTLR:输入不匹配

parsing - 帮助解析日志文件 (ANTLR3)

c#-4.0 - ANTLR4中根据行号和列号获取最可能的token类型

java - 递归表达式的 ANTLR 语法

antlr - 在 Nemerle 中使用 cs2n 工具