【问题】
在antlrworks中,antlr v3的语法,用如下代码:
grammar DDParserDemo; options { output = AST; ASTLabelType = CommonTree; // type of $stat.tree ref etc... } //NEWLINE : '\r'? '\n' ; //NEWLINE : '\r' '\n' ; fragment NEWLINE : '\r'? '\n' ; /* fragment FLOAT : ('0'..'9')+ '.' ('0'..'9')* EXPONENT? | '.' ('0'..'9')+ EXPONENT? | ('0'..'9')+ EXPONENT ; */ COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} | '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} ; //fragment WS : ( ' ' | '\t' | '\r' | '\n') {skip();}; //fragment WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; /* STRING : '"' ( ESC_SEQ | ~('\\'|'"') )* '"' ; */ CHAR: '\'' ( ESC_SEQ | ~('\''|'\\') ) '\'' ; fragment EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; ESC_SEQ : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') | UNICODE_ESC | OCTAL_ESC ; fragment OCTAL_ESC : '\\' ('0'..'3') ('0'..'7') ('0'..'7') | '\\' ('0'..'7') ('0'..'7') | '\\' ('0'..'7') ; fragment UNICODE_ESC : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT ; //fragment DIGIT : '0'..'9'; DECIMAL_VALUE : DIGIT+; HEX_DIGIT : ('a'..'f'|'A'..'F' | DIGIT) ; HEX_VALUE : '0x' HEX_DIGIT+; BLANKS : (' '|'\t')+; //BLANKS : (' '|'\t')+ {skip();}; //BLANKS : ' '+ {$channel=HIDDEN;}; //fragment ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; //ID_START : 'a'..'z'|'A'..'Z'|'_'; //WHOLE_ID : (ID_START) (ID_START | DIGIT)*; //ID_MIDDLE_END : ID_START | DIGIT; //ID_MIDDLE_END : HEX_DIGIT | '_'; //singleInclude : '#include' BLANKS '"' ID_START ID_MIDDLE_END* '.h' '"'; //singleInclude : '#include' BLANKS '"' ID_START (ID_START | DIGIT)* '.h' '"'; //singleInclude : '#include' BLANKS '"' ID_START (ID_START | DIGIT)+ '.h' '"'; //singleInclude : '#include' BLANKS '"' ID_START '.h' '"'; //singleInclude : '#include' BLANKS '"' WHOLE_ID '.h' '"'; singleInclude : '#include' BLANKS '"' ID '.h' '"'; //include : singleInclude WS* -> singleInclude; include : singleInclude WS*; //startParse : include* identification+; //startParse : include+ identification+; //startParse : identification+; //startParse : manufacture deviceType deviceRevison ddRevision; startParse : include+ manufacture deviceType deviceRevison ddRevision; //manufacture : 'MANUFACTURER'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; //manufacture : 'MANUFACTURER'^ (BLANK+! (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; //manufacture : 'MANUFACTURER'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) ','? WS*; manufacture : 'MANUFACTURER'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; deviceType : 'DEVICE_TYPE'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; deviceRevison : 'DEVICE_REVISION'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; //deviceRevison : 'DEVICE_REVISION'^ BLANKS (DIGIT+ | HEX_VALUE) (','?)! WS*; ddRevision : 'DD_REVISION'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*;
去解析:
/* ********************************************************************** ** Includes ********************************************************************** */ #include "std_defs.h" #include "com_tbls.h" #include "rev_defs.h" #include "fbk_hm.h" #include "fdiag_FBK2_Start.h" #include "blk_err.h" /* ********************************************************************** ********** DEVICE SECTION ******************************************** ********************************************************************** */ MANUFACTURER 0x1E6D11, DEVICE_TYPE 0x00FF, DEVICE_REVISION 5, DD_REVISION 1
出错:
其中错的是,用:
deviceRevison : 'DEVICE_REVISION'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*;
解析对应的
DEVICE_REVISION 5,
中的5,竟然无法匹配。
【解决过程】
1.后来试了试,改为:
deviceRevison : 'DEVICE_REVISION'^ BLANKS (DIGIT+ | HEX_VALUE) (','?)! WS*;
是可以工作的。
2.后来是,把对应的fragment加上:
fragment DIGIT : '0'..'9';
就可以了:
【总结】
此处,如果使用单独的定义:
DIGIT : '0'..'9'; DECIMAL_VALUE : DIGIT+; deviceRevison : 'DEVICE_REVISION'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*;
是无法正常匹配:
DEVICE_REVISION 5,
中的数字5的。
但是添加了fragment后,变为:
fragment DIGIT : '0'..'9'; DECIMAL_VALUE : DIGIT+; deviceRevison : 'DEVICE_REVISION'^ BLANKS (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*;
就可以了。
根本原因在于:
加了fragment后,就类似于DIGIT,就类似于inline了,就会自动被替换为:
deviceRevison : 'DEVICE_REVISION'^ BLANKS (DIGIT+ | HEX_VALUE) (','?)! WS*;
了,就可以解析了。
但是目前,不是十分清楚的是:
对于一个简单的token的定义,何时,才需要加上那个fragment,何时不需要。
有待后续有机会弄清楚。