我正在尝试使用 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")
唯一剩下的值(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.
即使在阅读了 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
将导致以下解析:和
(3 < d()).e
在:当然,您可能希望省略 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/