【问题】
折腾:
【已解决】antlr调试解析出错:UnwantedTokenException(found=xxx)
的过程中,如果按照之前的逻辑:会自动匹配空格然后hidden掉
那么,之前自己手动添加的空格,都可以去掉了,比如针对
manufacture : 'MANUFACTURER'^ BLANKS_TABS (direct_value | define_value) (','?)! WS*;
可以改为:
//manufacture : 'MANUFACTURER'^ BLANKS_TABS (direct_value | define_value) (','?)! WS*; manufacture : 'MANUFACTURER'^ (direct_value | define_value) (','?)!;
看看效果,
结果就会出现:
NoViableAltException(0@[null])
【解决过程】
1.怀疑是,WS只能自动识别并忽略掉单个的空格,所以,对于多个的空格,需要手动自己去匹配并忽略掉。
所以,去把WS改为自动识别多个,并忽略:
//WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; WS : ( ' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
试试,结果,后来的,原先可用的:
BLANKS_TABS : (' '|'\t')+;
显示,和之前的WS冲突了,重复定义了,
所以,去掉BLANKS_TABS,以及多处出现的BLANKS_TABS。
2.然后,再去调试,发现,的确是可以了。
【总结】
1.此处的错误:
NoViableAltException
是由于,对于之前用WS,匹配并忽略掉了单个的空格,而后续的再去用BLANKS_TABS去匹配空格,实际上已经没了空格了,所以,无法继续匹配,才报错的。
解决办法就是,使用如下要解释的内容,使用WS,匹配并自动忽略掉所有的空格,会更加高效。
2.对于使用:
WS : ( ' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
可以达到的效果:
后续的,所有的token的定义中,凡是出现的,一个或多个的空格,Tab,回车,换行等内容,
都可以自动地,匹配到,并且由于加了hidden,就会自动忽略掉。
所以,后续的token中,就无需再写对应的WS,去匹配对应的空格了。
如此,就简化了整个语法,即无需每次单独去写对应的WS了。
目前,去掉了WS的,已经简化的语法如下:
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'); //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'; //FAKE_TOKEN : '1' '2' '3'; /* DECIMAL_VALUE : '1'..'9' DIGIT*; */ //DECIMAL_VALUE : DIGIT*; DECIMAL_VALUE : DIGIT+; //DECIMAL_VALUE : '1'..'9' DIGIT*; //HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; //HEX_DIGIT : (DIGIT|'a'..'f'|'A'..'F') ; HEX_DIGIT : ('a'..'f'|'A'..'F' | DIGIT) ; HEX_VALUE : '0x' HEX_DIGIT+; /* fragment HEADER_FILENAME : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_')*; */ //BLANK : (' '|'\t')+ {$channel=HIDDEN;}; //BLANK : (' '|'\t')+ {skip();}; //BLANKS_TABS : (' '|'\t')+; //fragment //BLANKS_TABS : (' '|'\t')+; //fragment ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; HEADER_FILENAME : ID '.h'; //singleInclude : '#include' BLANKS_TABS '"' ID '.h' '"'; //singleInclude : '#include' BLANKS_TABS '"' HEADER_FILENAME '"'; //singleInclude : '#include' WS '"' HEADER_FILENAME '"'; singleInclude : '#include' '"' HEADER_FILENAME '"'; //include : singleInclude WS*; include : singleInclude; define_value : ID; direct_value : (DECIMAL_VALUE | HEX_VALUE); //manufacture : 'MANUFACTURER'^ BLANKS_TABS (direct_value | define_value) (','?)! WS*; manufacture : 'MANUFACTURER'^ (direct_value | define_value) (','?)!; //deviceType : 'DEVICE_TYPE'^ (DECIMAL_VALUE | HEX_VALUE) (','?)!; deviceType : 'DEVICE_TYPE'^ (direct_value | define_value) (','?)!; //deviceRevison : 'DEVICE_REVISION'^ (DECIMAL_VALUE | HEX_VALUE) (','?)!; deviceRevison : 'DEVICE_REVISION'^ (direct_value | define_value) (','?)!; //ddRevision : 'DD_REVISION'^ (DECIMAL_VALUE | HEX_VALUE) (','?)!; ddRevision : 'DD_REVISION'^ (direct_value | define_value) (','?)!; label_value : '['? ID ']'; //label : WS* ('REDEFINE' WS+)? 'LABEL' WS+ label_value WS* ';' WS*; label : ('REDEFINE')? 'LABEL' label_value ';'; help_value : '['? ID ']'; //help : WS* ('REDEFINE' WS+)? 'HELP' WS+ help_value WS* ';' WS*; help : ('REDEFINE')? 'HELP' help_value ';'; //variable: 'REDEFINE' WS+ ID WS* '{' WS* label help class? type? constant?_unit? handling? '}'; //variable: 'REDEFINE' WS+ ID WS* '{' WS* label help '}'; variable: 'REDEFINE' ID '{' label help '}'; //everything : 'EVERYTHING' WS* ';'; everything : 'EVERYTHING' ';'; //redefinitions : 'REDEFINITIONS' WS* '{' WS* (variable | record)+ '}'; //redefinitions : 'REDEFINITIONS' WS* '{' WS* (variable)+ '}'; redefinitions : 'REDEFINITIONS' '{' (variable)+ '}'; //single_import : 'IMPORT' BLANKS_TABS manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ; //single_import : 'IMPORT' manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ; single_import : 'IMPORT' manufacture deviceType deviceRevison ddRevision '{' everything redefinitions '}' ; //single_import : 'IMPORT' (' ' | '\t')+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ; //single_import : 'IMPORT' WS+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ; startParse : include+ manufacture deviceType deviceRevison ddRevision single_import+;
是可以正常匹配如下测试内的:
/* =========================================================================== FILE_NAME fbk_hm.ddl FUNCTIONAL_MODULE_DESCRIPTION This file contains the device description of the FBK HART Master application. =========================================================================== */ /* ********************************************************************** ** 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 /* *********************************************************************** Import the Standard Descriptions for all Standard Parameters *********************************************************************** */ IMPORT MANUFACTURER __FF, DEVICE_TYPE __STD_PARM, DEVICE_REVISION SFT_STD_PARM_dev_rev, DD_REVISION SFT_STD_PARM_dd_rev { EVERYTHING ; REDEFINITIONS {
效果为:
效果真心不错。