ANTLR4中奇怪的语义谓词行为可能是一个Bug

时间:2016-11-26 12:47:44

标签: antlr4

这是我的C语法分析语法的一个有效子集。它只能解析下面显示的输入,但足以说明我的完整语法遇到的问题。请注意,它遵循传统方法来定义运算符优先级:

grammar CPPProcessor;
translation_unit:    expression;
primary_expression:
  '1'
  //|  {false}? '(' expression ')'
  | 'a'
  | 'b'

;
postfix_expression:
      primary_expression
    | postfix_expression '(' expression ')'

;

unary_expression:
      postfix_expression
    | '-' cast_expression
;
cast_expression:
      unary_expression
    | '(' 'a' ')' cast_expression
;
additive_expression:
      cast_expression
    | additive_expression '-' cast_expression
;
expression :  additive_expression;
WS: [ \t\f]+    -> channel(1);
CRLF: '\r'? '\n' -> channel(1);

调用规则为translation_unit,输入为包含以下内容的单行:

(a)-b

请注意primary_expression中的语义谓词已被注释掉。 (解释语法的方法是,当启用primary_expression的第二个规则时,输入被解析为减法。当子规则不存在时,它变为-b的C风格类型转换输入a)。

问题:真正的问题是,我认为{false}?等同于什么都没有,因此删除评论应该没有区别。但是,当我删除注释时,解析失败,即

primary_expression:
  '1'
  |  {false}? '(' expression ')'
  | 'a'
  | 'b'

;

并收到此错误:

line 1:0 no viable alternative at input '('

为什么拥有{false}?语义谓词会导致解析失败?这可能是ANLTR4中的一个错误吗?看起来postfix_expression中的第二个子规则导致了左递归的问题。删除左递归后,问题就会消失

1 个答案:

答案 0 :(得分:0)

我弄明白了这个问题。

语义谓词不能导致上层规则回溯并尝试其他子规则。因此,当<div class='nickname'><span>Ali</span></div> <div class='username'><span>@AliUser</span></div> <div class='go-premium'></div> 的第二个子规则未被注释时,它会公开另一个'('匹配规则,并允许为输入选择primary_expression的第一个子规则。但是一旦做出这个选择,它就会即使进一步的子规则中的某些语义谓词返回false,也无法撤消。语义谓词只能导致cast_expression的其他一些子规则被选中。但由于primary_expression中没有任何其他子规则可以匹配'('。解析失败。