我是使用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;
答案 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
事实上,词法分析者将如何发挥作用 例如,在1011 1/16和101 11/16之间?此外,您不应该在解析器规则中定义空格 把它们放在词法分析器的HIDDEN通道上,这样它们就不会被“看到” 解析器。
当遇到(子)字符串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/16
是101
和INTEGER_NUMBER
a 11/16
。
要强调:当您在不同的通道(如HIDDEN通道)上放置空格和换行符时,它们不会出现在解析器操作的令牌流中。因此,在解析器规则中使用这些标记是没有意义的:它们永远不会匹配。
HTH
答案 1 :(得分:0)
您发布的错误表示有两个规则匹配某些输入,在您的情况下是输入INTEGER_NUMBER '.' INTEGER_NUMBER
。但是,正如Bart评论的那样,你发布的语法没有那个问题。你确定错误来自你发布的确切内容吗?