ANTLR 初学者 =>语法问题

发布于 2024-10-04 16:12:39 字数 1421 浏览 7 评论 0原文

我是 ANTLR 的初学者。我只是出于测试目的执行以下操作,并尝试了解其工作方式并产生错误:

INTEGER_NUMBER : ('0'..'9')+;
integer_number:INTEGER_NUMBER;
小数数字:(整数数字'.'整数数字)| ('.'integer_number);
regular_number:decimal_number|integer_number;

我对“regular_number”规则收到以下警告:决策可以匹配诸如“INTEGER_NUMBER '.' 之类的输入” INTEGER_NUMBER”使用多个替代项:1、2 因此,该输入的替代方案 2 被禁用。

它究竟意味着什么?


好的,我已编辑这篇文章以包含重现此错误的代码

program :(price)*;

INTEGER_NUMBER : ('0'..'9')+;< br> INFO_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';< br> 货币:'欧元'|'美元'|'英镑';

integer_number:INTEGER_NUMBER ;
小数数字:(整数数字?'.')整数数字;
分数数字:(整数数字(('')+))? FRACTION_NUMBER;
常规数字:小数数字|整数数字;
numeric_number :regular_number|fraction_number;
non_numerical_number : INFO_PRICE ((' ')*) ('+'|'-') ((' ')*)(numerical_number)((' ')*) CURRENCY;

价格 : numeric_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 |---> : 小数|整数;

I'm a beginner using ANTLR. I'm just doing the following for test purposes and try to understand the way it works and produce errors:

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

I have the following warning on the "regular_number" rule : Decision can match input such as "INTEGER_NUMBER '.' INTEGER_NUMBER" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input.

What exactly does it means ?


Ok I have edited this post to include the code that reproduce this error

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;};

and the error know is this one

error(201): /ANTLR - Tuto 1/src/Test.g:37:2: The following alternatives can never be matched: 2
|---> : decimal_number|integer_number ;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尸血腥色 2024-10-11 16:12:39

正如评论中已经提到的,您发布的语法没有任何问题。

您提到的错误发生在以下语法中:

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'+ 
  ;

当解析器尝试为输入字符串 "123" 匹配 regular_number 时,它不知道选择哪个替代方案。 decimal_numberinteger_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
123.456

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

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

这应该可以解决这个问题。

但还有更多问题:

numerical_number 
  :  fraction_number
  |  regular_number
  ;

当上面的规则尝试处理像 "2 1/8" 这样的输入时,其中的 2 可能是您的 fraction_number 的一部分 包括 1/8,但也可以将其处理为 regular_number 后跟 fraction_number

另外,您不应该在解析器规则中定义空格,您已将它们放在词法分析器中的隐藏通道上,因此解析器不会“看到”它们。

话虽如此,这将是一种可能的替代语法,可能可以满足您的需求:

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;}
  ;

编辑 II

<块引用>

此外,您不应该在解析器规则中定义空格,您已经
将它们放在词法分析器中的隐藏通道上,这样它们就不会被“看到”
由解析器处理。

问题在于,词法分析器将如何发挥作用
例如 1011 1/16 和 101 11/16 之间?

当遇到(子)字符串 1011 1/16 时,1011 被标记为 INTEGER_NUMBER,空格被放置在 HIDDEN 通道上(并且因此,在传递给解析器的令牌流中不存在),并且 1/16 被标记为 FRACTION_NUMBER

对于 101 11/16,同样适用:101INTEGER_NUMBER11/16FRACTION_NUMBER

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

华泰

As already mentioned in the comments, there's nothing wrong with the grammar you posted.

The error you mention occurs with the following grammar:

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'+ 
  ;

When the parser tries to match a regular_number for the input string "123", it does not know which alternative to choose. Both decimal_number and integer_number match "123". Hence the error message:

... using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input

EDIT

From within the regular_number rule, the string "123.456" could be parsed as:

integer_number decimal_number
123            .456

or as:

decimal_number
123.456

Why not define a DECIMAL_NUMBER in the lexer:

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

?

That should fix that problem.

There are more issues though:

numerical_number 
  :  fraction_number
  |  regular_number
  ;

when the rule above tries to handle input like "2 1/8", the 2 from it could be a part of your fraction_number including the 1/8, but it could also be handled as a regular_number followed by a fraction_number.

Also, you shouldn't define spaces inside your parser rules, you've put them on the HIDDEN channel in the lexer, so they won't be "seen" by the parser.

Having said all that, this would be a possible alternative grammar that probably does what you want:

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;}
  ;

EDIT II

Also, you shouldn't define spaces inside your parser rules, you've
put them on the HIDDEN channel in the lexer, so they won't be "seen"
by the parser.

the thing being, how will the lexer make the difference
beetween 1011 1/16 and 101 11/16 for example ?

When encountering the (sub) string 1011 1/16, 1011 is tokenized as an INTEGER_NUMBER, the space is put on the HIDDEN channel (and is therefor not present in the token-stream that is being passed to the parser), and 1/16 is tokenized as a FRACTION_NUMBER.

For 101 11/16 the same applies: 101 is a INTEGER_NUMBER and 11/16 a FRACTION_NUMBER.

To emphasize: when you put spaces and line breaks on a different channel (like the HIDDEN channel), they are not present in the token stream that the parser operates on. So it makes no sense to use these tokens in parser rules: they're never going to be matched.

HTH

随心而道 2024-10-11 16:12:39

您发布的错误意味着有两个规则与某些输入匹配,在您的情况下,输入 INTEGER_NUMBER '.' INTEGER_NUMBER。然而,正如巴特评论的那样,您发布的语法不存在这个问题。您确定错误来自您发布的确切内容吗?

The error you posted means there are two rules that match certain input, in your case the input INTEGER_NUMBER '.' INTEGER_NUMBER. However, as Bart commented, the grammar you posted does not have that problem. Are you sure the error comes from the exact thing you posted?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文