1

我正在为 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 必须在它的右手表达式中选择再次是一个赋值(即后缀和赋值运算符跟随),如果它被链接起来。

知道我的理解有什么问题吗?

4

1 回答 1

1

如果我向解释器提供任何输入,...

不要使用 ANTLRWorks 的解释器:它有问题,并且无视任何类型的谓词。使用它的调试器:它完美无缺。

如果输入可以被读取为 postfixExpression,它将检查 postfixExpression 之后的下一个标记是否是赋值运算符之一,如果是,它会将规则解析为 assignmentExpression。

你是对的。

编辑 [已解决] 现在,我可以意识到这个解决方案还有另一个问题:assignmentExpression 必须在它的右手表达式中选择再次是一个赋值(即后缀和赋值运算符跟随),如果它被链接起来。

那有什么问题?

于 2012-01-01T18:42:40.237 回答