最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】antlr调试解析出错:NoViableAltException(0@[null])

ANTLR crifan 4790浏览 0评论

【问题】

折腾:

【已解决】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])

remove blanks error 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
      {

效果为:

parsed tree without every WS

效果真心不错。

转载请注明:在路上 » 【已解决】antlr调试解析出错:NoViableAltException(0@[null])

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.163 seconds, using 22.13MB memory