我正在为 D 实现一个带有 ANTLR 的解析器。这种语言基于 C,因此声明和表达式存在一些歧义。考虑一下:
a* b = c; // This is a declaration of the variable d with a pointer-to-a type.
c = a * b; // as an expression is a multiplication.
由于第二个示例只能出现在赋值表达式的右侧,因此我尝试使用以下代码段解决此问题:
expression
: left = assignOrConditional
(',' right = assignOrConditional)*
;
assignOrConditional
: ( postfixExpression ('=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '~=' | '<<=' | '>>=' | '>>>=' | '^^=') )=> assignExpression
| conditionalExpression
;
assignExpression
: left = postfixExpression
( op = ('=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '~=' | '<<=' | '>>=' | '>>>=' | '^^=')
right = assignOrExpression
)?
;
conditionalExpression
: left = logicalOrExpression
('?' e1 = conditionalExpression ':' e2 = conditionalExpression)?
;
据我了解,这应该可以避免歧义,但测试失败了。如果我向解释器提供任何输入,从规则 assignOrConditional 开始,它将因 NoViableAltException 而失败。输入是
a = b
b-=c
d
也许我误解了谓词是如何工作的,因此如果有人可以更正我对代码的解释,那就太好了:如果输入可以被读取为 postfixExpression,它将检查 postfixExpression 之后的下一个标记是否是赋值运算符之一如果是,它会将规则解析为 assignmentExpression。(注意, assignmentExpression 和 conditionalExpression 效果很好)。如果下一个标记不属于它们,它会尝试将其解析为条件表达式。
编辑 [已解决] 现在,我可以意识到这个解决方案还有另一个问题:assignmentExpression 必须在它的右手表达式中选择再次是一个赋值(即后缀和赋值运算符跟随),如果它被链接起来。
知道我的理解有什么问题吗?