【问题】
antlr v3,在antlrworks中,用如下语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | grammar DDParserDemo; options { output = AST; ASTLabelType = CommonTree; // type of $stat.tree ref etc... } //NEWLINE : '\r'? '\n' ; //NEWLINE : '\r' '\n' ; fragment NEWLINE : '\r'? '\n' ; fragment ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; 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();} ; 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*; HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; HEX_VALUE : '0x' HEX_DIGIT+; /* BLANKSPACE_TAB // : (' ' | '\t'){skip();}; : (' ' | '\t') {$channel=HIDDEN;}; */ //fragment BLANK : (' '|'\t')+ {skip();}; //BLANK : (' '|'\t') {skip();}; BLANK : (' '|'\t') {skip();}; fragment HEADER_FILENAME : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_')*; /* //singleInclude : '#include' ' '+ '"' ID '.h"' ; //singleInclude : '#include' ' '+ '"' ID+ '.h"' ; //singleInclude : '#include' ' '+ '"' HEADER_FILENAME '.h"'; //singleInclude : '#include' ' ' '"' HEADER_FILENAME '.h"'; //singleInclude : '#include "' HEADER_FILENAME '.h"'; //fragment singleInclude : '#include' (' ')+ '"' ID '.h"'; //singleInclude : '#include' (' '|'\t')+ '""' ID '.h"'; //singleInclude : '#include' (' '|'\t')+ '"std_defs.h"'; singleInclude : '#include' (' '|'\t')+ ID '.h'; include : singleInclude WS* -> singleInclude; */ //startParse : include* identification+; //startParse : include+ identification+; //startParse : identification+; startParse : manufacture deviceType deviceRevison ddRevision; manufacture : 'MANUFACTURER'^ BLANK+ (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; deviceType : 'DEVICE_TYPE'^ BLANK+ (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; deviceRevison : 'DEVICE_REVISION'^ BLANK+ (DECIMAL_VALUE | HEX_VALUE)(','?)! WS*; ddRevision : 'DD_REVISION'^ BLANK+ (DECIMAL_VALUE | HEX_VALUE)(','?)! WS*; //identification : definiton WS* (','?)! WS* -> definiton; //definiton : (ID)^ ('\t'!|' '!)+ (DECIMAL_VALUE | HEX_VALUE) //definiton : (ID)^ BLANKSPACE_TAB+ (DECIMAL_VALUE | HEX_VALUE) //definiton : ID ('\t'!|' '!)+ (DECIMAL_VALUE | HEX_VALUE); |
去调试解析:
1 2 3 4 | MANUFACTURER 0x1E6D11, DEVICE_TYPE 0x00FF, DEVICE_REVISION 5, DD_REVISION 1 |
结果出错:
【解决过程】
1.参考:
How to resolve this parsing ambiguitiy in Antlr3
看了其解释,只是明白了一点,那就是,
在语法中,的确存在,解析器,希望匹配的东西,但是实际上所匹配的内容中,缺少了后面的部分,所以导致解析器报错,说是EarlyExitException,即过早退出,(希望还有更多后续匹配的内容)
2.所以,就去自己的语法中,看看是否有,类似于上面这样的歧义的东西。
试试去,把skip去掉,即变为:
1 2 | //BLANK : (' '|'\t') {skip();}; BLANK : (' '|'\t'); |
看看效果。结果果然可以正常解析对应的值了:
接下来,还是需要,好好搞懂,为何加上那个skip,而出现EarlyExitException。
3.改为加上感叹号,表示不捕获:
1 2 | //manufacture : 'MANUFACTURER'^ BLANK+ (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; manufacture : 'MANUFACTURER'^ (BLANK+)! (DECIMAL_VALUE | HEX_VALUE) (','?)! WS*; |
结果还是和上面一样,还是可以捕获对应的那6个空格。
4.参考:
http://www.antlr3.org/api/Java/index-all.html
中的:
All tokens go to the parser (unless skip() is called in that rule) on a particular "channel". |
以及,进一步的,参考:
得知,加上skip()后,对应的,antlr就不为此内容,创建对应的token了。
所以,倒是可以去试试,把对应的内容,去改为hidden,而不是skip:
1 2 3 | //BLANK : (' '|'\t') {skip();}; //BLANK : (' '|'\t'); BLANK : (' '|'\t') {$channel=HIDDEN;}; |
结果却又是变成EarlyExitException了:
觉得还是不能理解。
5.期间,又出现别的问题,详见:
【基本解决】antlr v3,用包含{$channel=HIDDEN;}语法,结果解析出错:MissingTokenException
【总结】
虽然,对于org.antlr.runtime.EarlyExitException和之后的MissingTokenException,都可以避免了。
但是还是无法实现所要的,可以skip或hidden空格的效果。
更多总结详见上面的:
【基本解决】antlr v3,用包含{$channel=HIDDEN;}语法,结果解析出错:MissingTokenException
转载请注明:在路上 » 【基本解决】antlr v3中包含{skip();}的语法,调试解析时出错:org.antlr.runtime.EarlyExitException