我正在为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工作正常)。如果下一个标记不属于它们,它会尝试将其解析为conditionalExpression。
修改 [已解决]现在,我已经意识到这个解决方案存在另一个问题:assignExpression必须选择它的右手表达式再次赋值(即后缀和赋值运算符如下),如果它被链接起来。
知道我的理解有什么问题吗?
答案 0 :(得分:1)
如果我向解释器提供任何输入,......
不要使用ANTLRWorks的解释器:它是错误的,并且忽略任何类型的谓词。使用它的调试器:它完美无缺。
如果输入可以作为postfixExpression读取,它将检查postfixExpression之后的下一个标记是否为赋值运算符之一,如果是,则将该规则解析为assignmentExpression。
你是对的。
编辑[已解决]现在,我可以意识到这个解决方案存在另一个问题:assignExpression必须选择它的右手表达式再次赋值(即后缀和赋值运算符如下),如果它是链接的起来。
这有什么问题?