【问题】
在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,何时不需要。
有待后续有机会弄清楚。