Antlr解析数字问题
我在解析整数和十六进制数时遇到问题。我想用下面的规则解析C++枚举:Antlr解析数字问题,antlr,grammar,Antlr,Grammar,我在解析整数和十六进制数时遇到问题。我想用下面的规则解析C++枚举: grammar enum; rule_enum : 'enum' ID '{' enum_values+ '}'';'; enum_values : enum_value (COMMA enum_value)+; enum_value : ID ('=' number)?; number : hex_number | integer_number; hex_number : '0' 'x' HE
grammar enum;
rule_enum
: 'enum' ID '{' enum_values+ '}'';';
enum_values
: enum_value (COMMA enum_value)+;
enum_value
: ID ('=' number)?;
number : hex_number | integer_number;
hex_number
: '0' 'x' HEX_DIGIT+;
integer_number
: DIGIT+;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
DIGIT : ('0'..'9');
COMMA : ',';
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
我遇到的问题如下-在解析类似以下代码时:
enum Enum
{
Option1 = 0,
Option2 = 1
};
它不将0识别为整数,但尝试将其解析为十六进制数。我如何解决这个问题
多谢各位。
Tobias以下ANTLR仅适用于枚举的数字位。 (编辑内容包括以下Bart的建议)
首先,片段规则只能被lexer规则“看到”,而不能被解析器规则“看到”。因此,以下内容无效:
integer_number
: DIGIT+; // can't use DIGIT here!
fragment
DIGIT : ('0'..'9');
为了解决这些数字的模糊性,我认为最好将这些整数
-和十六进制
数字设置为lexer规则,而不是解析器规则
例如:
grammar enum;
rule_enum
: 'enum' ID '{' enum_values+ '}'';';
enum_values
: enum_value (COMMA enum_value)+;
enum_value
: ID ('=' number)?;
number
: HEX_NUMBER
| INTEGER_NUMBER
;
HEX_NUMBER
: '0' 'x' HEX_DIGIT+;
INTEGER_NUMBER
: DIGIT+;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
DIGIT : ('0'..'9');
COMMA : ',';
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
SPACE : (' ' | '\t' | '\r' | '\n') {skip();};
这将生成示例代码段的以下解析树:
十六进制介绍(数字|十六进制数字)
将只匹配单个十六进制数字(它无法匹配0xFF
)。此外,数字
部分可以省略,因为十六进制数字
已经包含这些数字。但是,我非常不愿意把这些东西放在语法分析器规则中:我很确定C++分析器本身也处理了一个词汇级上的整数、十六进制和八进制数的标记。上面的语法在我的ANTLR(1.4.2)副本上匹配0xFF(当活动规则是数字:)。您的建议是在Lexer级别上完全匹配十六进制数字吗?啊,是的,对不起,我错过了十六进制数字之后的+
。我必须说这有点误导:调用某个东西十六进制数字
,并使其匹配多个数字!:)Jimmy,您的最新建议现在导致lexer可能生成一个只包含'0x'
的令牌。最好将HEX\u INTRO
作为一个片段,或者在HEX\u NUMBER
中插入'0x'(在这种情况下,您只是复制了我的答案:)HEX\u DIGIT
也一样:如果要解析的源代码中只有F
一个,它就会被标记为HEX\u DIGIT
:这不是我们的本意。最好把它也变成一个片段。谢谢你-我不知道lexer和parser规则之间的细微差别。据我所知,这种语法不处理负数
grammar enum;
rule_enum
: 'enum' ID '{' enum_values+ '}'';';
enum_values
: enum_value (COMMA enum_value)+;
enum_value
: ID ('=' number)?;
number
: HEX_NUMBER
| INTEGER_NUMBER
;
HEX_NUMBER
: '0' 'x' HEX_DIGIT+;
INTEGER_NUMBER
: DIGIT+;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
DIGIT : ('0'..'9');
COMMA : ',';
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
SPACE : (' ' | '\t' | '\r' | '\n') {skip();};