Antlr 如何解析带括号的层次结构根?
我正在尝试用ANTLR解析值。以下是我语法的相关部分:Antlr 如何解析带括号的层次结构根?,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
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")
但是,由于非LL(*)ism,这违反了值
规则:
即使在阅读了大多数权威的ANTLR参考之后,我仍然不理解这些错误。然而,我所理解的是,在看到一个圆括号打开时,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 : IDENTIFIER | SELF | literal | constructor | call | indexer | '(' value ')';
...
value : comparison;
现在(a.b).c
将导致以下解析:
和(3
中:
当然,您可能希望从AST中省略括号:
root : IDENTIFIER | SELF | literal | constructor | call | indexer | '('! value ')'!;
此外,您不需要在解析器规则中使用+=
在列表中追加标记。以下是:
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)
可以通过值的备选方案1和2进行解析
规则:
root : ... | '(' value ')';
value
: comparison // alternative 1
| '(' value ')' // alternative 2
;
运行解析器规则:比较
(备选方案1)可以匹配(a)
,因为它匹配根
规则,而根
规则又匹配”(“值”)
。但这也是备选方案2所匹配的!这就是:解析器“看到”一个输入,两个不同的输入
解析并报告此歧义。您能发布完整的解析文件吗?(例如,什么是构造函数
,调用
,索引器
)我不是ANTLR专家,但我过去也做过类似的事情(确切地说,编译器-使用Lex/Yacc作为解析器部分-我可能能够帮助你。我真的相信这些与问题无关,但我会把它们添加到问题中。只是一个想法(这可能看起来很愚蠢,但如果我是你,我会尝试):创建另一个元素superroot:PAREN\u OPEN root PAREN\u CLOSE
,看看会发生什么。(我希望我没有弄乱语法,但你明白我的意思了……)或者基本上:super:PAREN_OPEN root PAREN_CLOSE | root
我本可以添加|'(“root”)
而不是|'(“value”)
,但这只允许将其他根元素括起来,而不是像(3
。非常感谢。你能给我一些关于如何理解和分析这些错误的解释吗?我的大脑仍然无法掌握出了什么问题,因此它显然无法修复它。(附言:我的语法还没有针对美进行优化,但谢谢你的隐含列表提示)@LazloBonin,请看我的编辑。谢谢。然而,我坚持认为,这在规则具有非LL(*)决策中是不明确的,因为从alts 1,2可以访问递归规则调用。我看不出你的解释有什么反复。@LazloBonin:对。我只注册了“alts错误”,但这只是问题的一部分。递归的事实是,值
也是括号内的值
。如果在value
-和root
规则中删除文本括号内的value
,您将看到只有一个“alts错误”,没有提到递归。
call
: IDENTIFIER PAREN_OPEN (value (SEPARATOR value)*)? PAREN_CLOSE
-> ^(CALL IDENTIFIER ^(ARGUMENTS value*)?)
;
value
: comparison // alternative 1
| '(' value ')' // alternative 2
;