【问题】
在antlrworks 1.5rc2中,用antlr v3的语法,相关代码如下:
//fragment BLANKS_TABS : (' '|'\t')+; manufacture : 'MANUFACTURER'^ BLANKS_TABS (direct_value | define_value) (','?)! WS*; single_import : 'IMPORT' BLANKS_TABS manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
去解析内容:
IMPORT MANUFACTURER __FF, DEVICE_REVISION SFT_STD_PARM_dev_rev, DD_REVISION SFT_STD_PARM_dd_rev |
结果出错:
UnwantedTokenException(found=xxx)
【解决过程】
1.字面上看起来,像是,本来写代码,用BLANKS_TABS去匹配空格的,结果实际匹配到的内容却是MANUFACTURER,
但是,很奇怪的是,本来要测试的内容,在IMPORT和MANUFACTURER,就的确,存在一个空格的:
IMPORT MANUFACTURER __FF, |
所以,没道理啊。
2.后来通过:
single_import : 'IMPORT' (' ' | '\t')+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
就的确是可以匹配到的:
3。但是后来,无意间,把空格匹配的部分去掉,变成:
single_import : 'IMPORT' manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ; //single_import : 'IMPORT' (' ' | '\t')+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
结果,竟然是可以匹配到的,而且是无错的:
所以,看起来,很是诡异啊。
即,本身要解析的内容,IMPORT和MANUFACTURER之前的确存在一个空格,
但是用语法解析时,没有写代码去匹配空格,结果竟然也是可以匹配正常的。
难道,antlr中,自动会忽略掉两个ID之间的空格?
4.去试试,把其他一些,看起来,暂时用不到的token,都注释掉,比如CHAR,NEWLINE,等等,结果效果依旧。
5.后来,觉得,估计是原先的这句:
WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
所导致,自动匹配到白空格之类的,然后就自动hidden了,所以,应该就是上面的效果了。
所以,现在试试,把hidden属性去掉,变成:
//WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; WS : ( ' ' | '\t' | '\r' | '\n');
试试,结果竟然,从最开始的内容,都无法匹配了:
还是很奇怪的,为何把WS的hidden去掉,竟然连comment里面的内容,都无法匹配了。
6.结果,只能把在WS的hidden加上,然后反正是可以正常解析了。
7.此处,看起来,像是:
此处,加了对应的空格去匹配本身就存在的空格,却导致了异常,出现UnwantedTokenException的错误,原因在于:
本身,之前已经写了规则:
WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
去自动匹配单个空格,并且自动忽略掉,所以,后来再加上自己写的:
BLANKS_TABS : (' '|'\t')+; single_import : 'IMPORT' BLANKS_TABS manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
去匹配:
IMPORT MANUFACTURER
中间的那个空格时,才会出错。
但是为何,手动写成:
single_import : 'IMPORT' (' ' | '\t')+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
中,却又是可以匹配到其中的空格呢?
所以,还是没有完全搞懂其中的规则,没有搞懂,此处的WS,何时会去自动匹配,何时会被当前的规则重写。
8.所以,再去试着手动写成WS,变成:
single_import : 'IMPORT' WS+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
看看效果,结果竟然是出现了org.antlr.runtime.EearlyExitException:
9.期间出现
NoViableAltException(0@[null]) |
折腾过程见:
【已解决】antlr调试解析出错:NoViableAltException(0@[null])
【总结】
此处的UnwantedTokenException的错误的原因是,对于之前使用:
WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
会自动识别匹配,单个的白空格,且由于加了hidden,所以会自动忽略掉。
所以,对于要匹配的内容:
IMPORT MANUFACTURER
中的空格,本身就只有一个,所以,已经被之前的WS匹配并忽略掉了。
所以,再次使用:
single_import : 'IMPORT' WS+ manufacture deviceType deviceRevison ddRevision WS* '{' WS* everything WS* redefinitions WS* '}' ;
去匹配的时候,注意此处用的WS+,已经找不到对应的,其他的空格了,所以会报UnwantedTokenException的错。
解决办法是,直接把WS改为:
WS : ( ' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
则可以自动识别并忽略掉所有的白空格,且对后续的所有内容中白空格都有效。
更多解释参见:
【已解决】antlr调试解析出错:NoViableAltException(0@[null])
转载请注明:在路上 » 【已解决】antlr调试解析出错:UnwantedTokenException(found=xxx)