ANTLR初学者=>语法问题

时间:2010-11-24 09:09:33

标签: antlr grammar

我是使用ANTLR的初学者。我只是为了测试目的而做以下操作,并尝试理解它的工作方式并产生错误:

INTEGER_NUMBER : ('0'..'9')+;
integer_number: INTEGER_NUMBER;
decimal_number: (integer_number '.' integer_number) | ('.' integer_number);
regular_number: decimal_number|integer_number;

我对“regular_number”规则发出以下警告:决策可以匹配输入,例如“INTEGER_NUMBER”。 INTEGER_NUMBER“使用多种替代方案:1,2 结果,替代(s)2被禁用该输入。

这究竟意味着什么?


好的我已编辑此帖子以包含重现此错误的代码

program :(price)*;

INTEGER_NUMBER : ('0'..'9')+;
INFO_PRICE : 'OLD PRICE';
FRACTION_NUMBER : '1/16'|'1/8'|'3/16'|'1/4'|'5/16'|'3/8'|'7/16'|'1/2'|'9/16'|'5/8'|'11/16'|'3/4'|'13/16'|'7/8'|'15/16';
CURRENCY : 'EUR'|'USD'|'GBP';

integer_number : INTEGER_NUMBER ;
decimal_number : (integer_number? '.') integer_number ;
fraction_number : (integer_number ((' ')+))? FRACTION_NUMBER;
regular_number : decimal_number|integer_number ;
numerical_number :regular_number|fraction_number;
non_numerical_number : INFO_PRICE ((' ')*) ('+'|'-') ((' ')*)(numerical_number)((' ')*) CURRENCY;

price : numerical_number |non_numerical_number;

WS : (' ' | '\t' | '\f')+ {$channel=HIDDEN;};
NL :('\r' '\n' | '\r' | '\n') {$channel=HIDDEN;};

,错误就知道了这个

错误(201):/ ANTLR - Tuto 1 / src / Test.g:37:2:永远不能匹配以下替代方案:2  | ---> :decimal_number | integer_number;

2 个答案:

答案 0 :(得分:3)

正如评论中已经提到的,你发布的语法没有错。

您提到的错误会出现以下语法:

grammar Test;

regular_number
  :  decimal_number
  |  integer_number
  ;

integer_number
  :  INTEGER_NUMBER
  ;

decimal_number
  :  integer_number '.' integer_number
  |  '.' integer_number
  |  integer_number                      // <- I added this one
  ;

INTEGER_NUMBER 
  :  '0'..'9'+ 
  ;

当解析器尝试匹配输入字符串regular_number的{​​{1}}时,它不知道选择哪个替代项。 "123"decimal_number都匹配integer_number。因此错误消息:

"123"


修改

... using multiple alternatives: 1, 2 As a result, alternative(s) 2 were disabled for that input 规则中,字符串regular_number可以解析为:

"123.456"

或作为:

integer_number decimal_number
123            .456

为什么不在词法分析器中定义DECIMAL_NUMBER:

decimal_number
123.456

那应该解决这个问题。

但还有更多问题:

DECIMAL_NUMBER
  :  INTEGER_NUMBER '.' INTEGER_NUMBER
  |  '.' INTEGER_NUMBER
  ;

当上述规则尝试处理numerical_number : fraction_number | regular_number ; 之类的输入时,来自它的"2 1/8"可能是2的一部分,包括fraction_number,但它也可能是处理为1/8后跟regular_number

此外,您不应在解析器规则中定义空格,而是将它们放在词法分析器的HIDDEN通道中,这样它们就不会被解析器“看到”。

说了这么多,这可能是一种可能做你想做的替代语法:

fraction_number

编辑II

  
    

此外,您不应该在解析器规则中定义空格     把它们放在词法分析器的HIDDEN通道上,这样它们就不会被“看到”     解析器。

  
     事实上,词法分析者将如何发挥作用   例如,在1011 1/16和101 11/16之间?

当遇到(子)字符串program : price* EOF ; price : numerical_number | non_numerical_number ; numerical_number : FRACTION_NUMBER | DECIMAL_NUMBER | INTEGER_NUMBER ; non_numerical_number : INFO_PRICE ('+' | '-') (INTEGER_NUMBER FRACTION_NUMBER | numerical_number) CURRENCY ; DECIMAL_NUMBER : INTEGER_NUMBER '.' INTEGER_NUMBER | '.' INTEGER_NUMBER ; FRACTION_NUMBER : '1/16' | '1/8' | '3/16' | '1/4' | '5/16' | '3/8' | '7/16' | '1/2' | '9/16' | '5/8' | '11/16' | '3/4' | '13/16' | '7/8' | '15/16' ; INTEGER_NUMBER : '0'..'9'+ ; INFO_PRICE : 'OLD PRICE' ; CURRENCY : 'EUR' | 'USD' | 'GBP' ; WS : (' ' | '\t' | '\f' | '\r' | '\n')+ {$channel=HIDDEN;} ; 时,1011 1/16被标记为1011,空间被放置在HIDDEN频道上(因此不存在于令牌流中)正在传递给解析器),INTEGER_NUMBER被标记为1/16

FRACTION_NUMBER同样适用:101 11/16101INTEGER_NUMBER a 11/16

要强调:当您在不同的通道(如HIDDEN通道)上放置空格和换行符时,它们不会出现在解析器操作的令牌流中。因此,在解析器规则中使用这些标记是没有意义的:它们永远不会匹配。

HTH

答案 1 :(得分:0)

您发布的错误表示有两个规则匹配某些输入,在您的情况下是输入INTEGER_NUMBER '.' INTEGER_NUMBER。但是,正如Bart评论的那样,你发布的语法没有那个问题。你确定错误来自你发布的确切内容吗?