ANTLR初学者=>;语法问题
我是一个使用ANTLR的初学者。我只是出于测试目的做了以下工作,并试图了解它的工作方式和产生错误的方式:ANTLR初学者=>;语法问题,antlr,grammar,Antlr,Grammar,我是一个使用ANTLR的初学者。我只是出于测试目的做了以下工作,并试图了解它的工作方式和产生错误的方式: INTEGER_数:('0'..'9')+ integer\u编号:integer\u编号 decimal_number:“整数_number.”“整数_number”)(“整数_number”) 正则数:十进制数|整数|数 关于“常规编号”规则,我有以下警告:决策可以匹配输入,例如“整数编号”。“整数编号”使用多个选项:1、2 因此,该输入的备选方案2被禁用 这到底意味着什么 好的,我已
INTEGER_数:('0'..'9')+代码>
integer\u编号:integer\u编号代码>
decimal_number:“整数_number.”“整数_number”)(“整数_number”)代码>
正则数:十进制数|整数|数代码>
关于“常规编号”规则,我有以下警告:决策可以匹配输入,例如“整数编号”。“整数编号”使用多个选项:1、2
因此,该输入的备选方案2被禁用
这到底意味着什么
好的,我已经编辑了这篇文章,包括重现这个错误的代码
程序:(价格)*代码>
INTEGER_数:('0'..'9')+代码>
INFO_PRICE:“旧价格”代码>
分数编号:'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\u编号:integer\u编号代码>
十进制数:(整数?')整数代码>
分数:(整数(“)+)?分数_数代码>
正则数:十进制数|整数|数代码>
数值_数:正则_数|分数_数代码>
non_numeric_number:INFO_PRICE((“”)*)(“+”|“-”)((“”)*)(numeric_number)((“”)*)货币代码>
价格:数字|非数字|代码>
WS:(''|'\t'|'\f')+{$channel=HIDDEN;}代码>
NL:('\r'\n'|'\r'|'\n'){$channel=HIDDEN;}代码>
我们知道的错误是这个
错误(201):/ANTLR-Tuto 1/src/Test.g:37:2:以下选项永远无法匹配:2
|--->:十进制数|整数|数 您发布的错误意味着有两条规则与某些输入匹配,在您的案例中,输入整数。\n整数
。然而,正如巴特评论的那样,你发布的语法没有这个问题。您确定错误来自您发布的内容吗?如评论中所述,您发布的语法没有问题
您提到的错误发生在以下语法中:
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'+
;
编辑
在常规\u编号
规则中,字符串“123.456”
可以解析为:
integer_number decimal_number
123 .456
或作为:
decimal_number
123.456
为什么不在lexer中定义一个十进制数:
DECIMAL_NUMBER
: INTEGER_NUMBER '.' INTEGER_NUMBER
| '.' INTEGER_NUMBER
;
?
这应该可以解决这个问题
不过,还有更多问题:
numerical_number
: fraction_number
| regular_number
;
当上面的规则试图处理像“2 1/8”
这样的输入时,其中的2
可能是分数
的一部分,包括1/8
,但也可以作为常规
后接分数
处理
另外,您不应该在解析器规则中定义空格,您已经将它们放在lexer中的隐藏通道上,因此解析器不会“看到”它们
话虽如此,这将是一种可能的替代语法,可能满足您的需求:
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;}
;
编辑二
另外,您不应该在解析器规则中定义空格,您已经
把它们放在lexer的隐藏通道上,这样它们就不会被“看到”
由解析器执行
问题是,lexer将如何发挥作用
例如,甜菜蛋白1011 1/16和101 11/16
当遇到(子)字符串1011 1/16
时,1011
被标记为整数
,空间被放在隐藏通道上(因此在传递给解析器的令牌流中不存在),1/16
被标记为分数
对于101 11/16
同样适用:101
是整数
和11/16
是分数
要强调的是:当您在不同的通道(如隐藏通道)上放置空格和换行符时,它们不会出现在解析器操作的令牌流中。所以在解析器规则中使用这些标记是没有意义的:它们永远不会被匹配
HTH你发布的语法没有问题。在命令行上生成lexer和解析器,并使用ANTLRWorks(1.4),不会产生您发布的错误。之后还有其他规则吗?我怀疑有。您正在测试令牌的开始和结束吗?除了这个问题,您还可以更改十进制数:(整数。'integer_number')('integer_number')代码>到<代码>十进制数:(整数?。“整数”)代码>:同样的东西,但它更短。谢谢你的回答,你没事,我从我的示例中提取了这段代码,因为警告发布在这一行上。事实上,这个警告似乎是因为另一条规则而出现的。。。我将尝试查看哪一个并发布代码。感谢您的回答,您也很好,我从示例中提取了这段代码,因为警告发布在这一行上。事实上,这个警告似乎是因为另一条规则而出现的。。。我会试着看看是哪一个,然后把代码发出去。@BlackLabrador,不客气。我想你现在知道什么时候会发生这样的错误了吧?如果你仍然不确定你的语法错误在哪里,请编辑你的原始问题并发布整个语法。谢谢巴特,我已经编辑了这篇文章,并试图把产生错误的版本放进去。非常感谢你的精彩报道!你的评论非常精确和宝贵!!!!此外,您不应该在解析器规则中定义空格,您已经将它们放在lexer中的隐藏通道上,因此解析器不会“看到”它们。=>问题是,lexer将如何在10111/16和10111/16之间产生差异?嗨,Jorn,显然是warni
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;}
;