【已解决】antlr代码执行出错:xxx.ddl line 16:13 no viable alternative at input ‘1’,Recognition exception NoViableAltException(0@[null])

【问题】

antlr v3的代码:

grammar HartEddlParser;

options {
	output = AST;
	ASTLabelType = CommonTree; // type of $stat.tree ref etc...
}

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WS  :   ( ' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};

//fragment
ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;



//ID_NON_FRAGMENT	:	ID;

fragment
DIGIT
	:	'0'..'9';


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
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

//fragment
STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;



fragment
IMPORTED_VALUE	:	'[' ID ']'; /* normal ID with [] */

//fragment
DEFINE_IMPORTED_VALUE
		:	ID | IMPORTED_VALUE;


fragment	
DATA_ITEM_SPECIAL_MASKS
	: ID '<' HEX_VALUE '>' ','?;
fragment
DATA_ITEM_SPECIAL_QUALIFIER
	: ID '(' 'INFOR'|'INDEX'|'INFOR,INDEX' ')' ','?;
DATA_ITEM_SPECIAL
	:	DATA_ITEM_SPECIAL_MASKS | DATA_ITEM_SPECIAL_QUALIFIER;



UNSIGNED_CHAR_NUMBER
	:UNSIGNED_CHAR_CONDITION_ONE|UNSIGNED_CHAR_CONDITION_TWO|UNSIGNED_CHAR_CONDITION_THREE|UNSIGNED_CHAR_CONDITION_FOUR;
fragment   
UNSIGNED_CHAR_CONDITION_ONE
	:'0';
fragment	
UNSIGNED_CHAR_CONDITION_TWO
	:'1' (DIGIT | (DIGIT DIGIT))?;		
fragment
UNSIGNED_CHAR_CONDITION_THREE
	:'2' (('0'..'4' DIGIT?) | ('5' '0'..'5'?) | ('6'..'9'))?;				
fragment
UNSIGNED_CHAR_CONDITION_FOUR
	:'3'..'9' DIGIT?;


//fragment
//HEX_VALUE
//	:	'0x' HEX_DIGIT+;
HEX_VALUE
	:	TMP_HEX_VALUE;
fragment
TMP_HEX_VALUE
	:		'0x' HEX_DIGIT+;

//fragment
//DECIMAL_VALUE	:	DIGIT+;
DECIMAL_VALUE	: 	TMP_DECIMAL_VALUE;
fragment
TMP_DECIMAL_VALUE	:	DIGIT+;

fragment
HEX_DIGIT : ('a'..'f'|'A'..'F' | DIGIT) ;

string_value	:	(DEFINE_IMPORTED_VALUE | STRING);

startParse	:	(singleInclude | id_info | variable)+;

singleInclude	:	'#include' STRING;

//id_info		:	(manufacture | deviceType | deviceRevison | ddRevision)+;
id_info		:	(manufacture | deviceType | deviceRevison | ddRevision);
manufacture	:	'MANUFACTURER' 		(direct_value | DEFINE_IMPORTED_VALUE) (','?)!;
deviceType	:	'DEVICE_TYPE' 		(direct_value | DEFINE_IMPORTED_VALUE)  (','?)!;
deviceRevison	:	'DEVICE_REVISION' 	(direct_value | DEFINE_IMPORTED_VALUE)  (','?)!;
ddRevision	:	'DD_REVISION' 		(direct_value | DEFINE_IMPORTED_VALUE)  (','?)!;

//fragment
//DIRECT_VALUE	:	(HEX_VALUE | DECIMAL_VALUE);
//direct_value 	:	(HEX_VALUE | DECIMAL_VALUE);
direct_value 	:	(DECIMAL_VALUE | HEX_VALUE);

/*
7.27 VARIABLE
Table 138 – VARIABLE attributes
*/

//label_value	:	define_value | IMPORTED_VALUE;
//label		:	'REDEFINE'? 'LABEL' DEFINE_IMPORTED_VALUE ';';
label		:	'REDEFINE'? 'LABEL' string_value ';';

//help_value	:	define_value | IMPORTED_VALUE;
help		:	'REDEFINE'? 'HELP' DEFINE_IMPORTED_VALUE ';';

single_class_value
		: 	('ALARM'| 'ANALOG_INPUT'| 'ANALOG_OUTPUT'| 'COMPUTATION'| 'CONTAINED'| 'CORRECTION'| 'DEVICE'| 'DIAGNOSTIC'| 'DIGITAL_INPUT'| 'DIGITAL_OUTPUT'| 'DISCRETE_INPUT'| 'DISCRETE_OUTPUT'| 'DYNAMIC'| 'FREQUENCY_INPUT'| 'FREQUENCY_OUTPUT'| 'HART'| 'INPUT'| 'LOCAL'| 'LOCAL_DISPLAY'| 'OPERATE'| 'OUTPUT'| 'SERVICE'| 'TUNE');
class_value	:	single_class_value ('&' single_class_value)*;
class_line	:	'CLASS' class_value ';' ;


expression_or_direct_value
	:	direct_value; //todo: add expression support

expression_or_string
	:	STRING;//todo:add string expression support
values_display_format
	:	'DISPLAY_FORMAT' expression_or_string ';';
values_default_value
	:	'DEFAULT_VALUE' expression_or_direct_value ';';
values_attribute
	:	values_default_value | values_display_format;//todo: add more EDIT_FORMAT, ...
float_type_value
	:	'TYPE' 'FLOAT' '{' values_attribute+ '}';
integer_type_value
	:	'TYPE' 'INTEGER' '{' values_attribute+ '}';
type		:	integer_type_value | float_type_value; //todo: add more


constant_unit	:	'CONSTANT_UNIT' string_value ';' ;

/*
7.27.2.5 HANDLING
*/
single_handling_value
		:	('READ' | 'READ_WRITE' | 'WRITE');
handling_value	:	single_handling_value ('&' single_handling_value)*;
handling	:	'HANDLING' handling_value ';' ;


variable_field	:	class_line | label | type | help | constant_unit | handling;
variable	:	'REDEFINE'? 'VARIABLE' ID '{' variable_field+ '}';


/*
*HART_COMMAND
*to do :the length of CMD_NAME and the redefine of the CMD_NAME
*/
hart_command
	:	(hart_cmd_simple)|(hart_cmd_header '{' hart_cmd_number ';' hart_cmd_operation ';' hart_cmd_transaction* hart_cmd_response*);

hart_cmd_simple
	:	string_cmd cmd_name ';';
hart_cmd_header
	:string_cmd cmd_name;	
string_cmd
	:	'COMMAND';
cmd_name
	:	ID;
	
hart_cmd_number
	:	cmd_number cmd_number_param;	
cmd_number
	:	'NUMBER';	

cmd_number_param
	:	UNSIGNED_CHAR_NUMBER;

				
hart_cmd_operation
	:	cmd_operation cmd_operation_param;	
cmd_operation
	:	'OPERATION'^;
cmd_operation_param
	:	'READ'|'WRITE'|'COMMAND';
	
hart_cmd_transaction
	:cmd_transaction cmd_transaction_integer? '{' cmd_transaction_param '}';	
cmd_transaction
	:	'TRANSACTION'^;	
cmd_transaction_integer
	:	UNSIGNED_CHAR_NUMBER;
cmd_transaction_param
	: cmd_transaction_request '{' (cmd_transaction_request_data_item ','?)*  '}' cmd_transaction_reply '{' (cmd_transaction_reply_data_item ','?)+  '}' (cmd_transaction_response '{' cmd_response_code* '}')? ;	
cmd_transaction_request
	:	'REQUEST';
//The DATA_ITEM_SPECIAL should be specified  clearly and test in future	
cmd_transaction_request_data_item
	: ID | UNSIGNED_CHAR_NUMBER | DATA_ITEM_SPECIAL;
cmd_transaction_reply
	:'REPLY';	
cmd_transaction_reply_data_item
	:ID | DATA_ITEM_SPECIAL;
cmd_transaction_response
	:'RESPONSE';
cmd_response_code
	: (cmd_name ','?) | (cmd_response_code_item ';');	

hart_cmd_response
	:	cmd_response '{' (cmd_response_code_item ';')+  '}';			
cmd_response
	:	'RESPONSE_CODES'^;	
//cmd_response_param
//	: cmd_response_code_item ;	
	
cmd_response_code_item
	: cmd_response_code_item_value ',' cmd_response_code_item_type ',' cmd_response_code_item_description ','? cmd_response_code_item_help?;
	
cmd_response_code_item_value
	:UNSIGNED_CHAR_NUMBER;//DECIMAL_VALUE;	
cmd_response_code_item_type
	:'SUCCESS'|'DATA_ENTRY_WARNING'|'MTIC_WARNING'|'DATA_ENTRY_ERROR'|'MODE_ERROR'|'PROCESS_ERROR'|'MISC_ERROR';
cmd_response_code_item_description
	:string_for_description_help;
cmd_response_code_item_help
	:string_for_description_help;	
string_for_description_help
	:	('"' ID '"') |'[' ID ']';

用antlrworks 1.5rc2调试,去匹配内容:

/* *
 *      .........
 * */

/*----------------------- D E C L A R A T I O N S ----------------------*/

//MANUFACTURER PMV, DEVICE_TYPE _D3, DEVICE_REVISION 1, DD_REVISION 2
MANUFACTURER 1, DEVICE_TYPE 1, DEVICE_REVISION 1, DD_REVISION 2

结果出错:

output输出为:

D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\HartEddlParser\pos_identification_varialbe_command.ddl line 16:13 no viable alternative at input ‘1’

 

Events中是:

49 Recognition exception NoViableAltException(0@[null])

对应错误截图为:

no viable alternative at input NoViableAltException

【解决过程】

1.此处,感觉还是不懂,为何对于简单的代码:

fragment
DIGIT
	:	'0'..'9';

HEX_VALUE
	:	TMP_HEX_VALUE;
fragment
TMP_HEX_VALUE
	:		'0x' HEX_DIGIT+;

//fragment
//DECIMAL_VALUE	:	DIGIT+;
DECIMAL_VALUE	: 	TMP_DECIMAL_VALUE;
fragment
TMP_DECIMAL_VALUE	:	DIGIT+;

fragment
HEX_DIGIT : ('a'..'f'|'A'..'F' | DIGIT) ;

manufacture	:	'MANUFACTURER' 		(direct_value | DEFINE_IMPORTED_VALUE) (','?)!;

direct_value 	:	(DECIMAL_VALUE | HEX_VALUE);

去匹配

MANUFACTURER 1

竟然MANUFACTURER后面的1,会被丢掉,而无法匹配,出现NoViableAltException的错误。

2.猜测,或许是因为,由于把,HEX_DIGIT,放在了,其调用者,TMP_HEX_VALUE,的后面,

所以导致带fragment的HEX_DIGIT,无法获得对应的数字了。

所以去改为:

fragment
HEX_DIGIT : ('a'..'f'|'A'..'F' | DIGIT) ;

//fragment
//HEX_VALUE
//	:	'0x' HEX_DIGIT+;
HEX_VALUE
	:	TMP_HEX_VALUE;
fragment
TMP_HEX_VALUE
	:		'0x' HEX_DIGIT+;

//fragment
//DECIMAL_VALUE	:	DIGIT+;
DECIMAL_VALUE	: 	TMP_DECIMAL_VALUE;
fragment
TMP_DECIMAL_VALUE	:	DIGIT+;

试试效果。

结果问题依旧。

3.再改为:

fragment
TMP_DECIMAL_VALUE	:	DIGIT+;
//fragment
//DECIMAL_VALUE	:	DIGIT+;
DECIMAL_VALUE	: 	TMP_DECIMAL_VALUE;

结果是,问题依旧。

 

【总结】

后来终于搞懂了,实际上是:

对于十进制的立即数,目前有两个部分;

一个是,用于表示0-255的部分:

UNSIGNED_CHAR_NUMBER
	:UNSIGNED_CHAR_CONDITION_ONE|UNSIGNED_CHAR_CONDITION_TWO|UNSIGNED_CHAR_CONDITION_THREE|UNSIGNED_CHAR_CONDITION_FOUR;
fragment   
UNSIGNED_CHAR_CONDITION_ONE
	:'0';
fragment	
UNSIGNED_CHAR_CONDITION_TWO
	:'1' (DIGIT | (DIGIT DIGIT))?;		
fragment
UNSIGNED_CHAR_CONDITION_THREE
	:'2' (('0'..'4' DIGIT?) | ('5' '0'..'5'?) | ('6'..'9'))?;				
fragment
UNSIGNED_CHAR_CONDITION_FOUR
	:'3'..'9' DIGIT?;

另一个是,表示,所有的,普通的十进制的立即数的部分,即:

direct_value 	:	(DECIMAL_VALUE | HEX_VALUE);

中的DECIMAL_VALUE部分:

fragment
TMP_DECIMAL_VALUE	:	DIGIT+;
//fragment
//DECIMAL_VALUE	:	DIGIT+;
DECIMAL_VALUE	: 	TMP_DECIMAL_VALUE;

导致的结果是,

对于输入的数字:

1

其结果,被放在DECIMAL_VALUE前面的UNSIGNED_CHAR_NUMBER 部分匹配到了。

导致后来的:

manufacture	:	'MANUFACTURER' 		(direct_value | DEFINE_IMPORTED_VALUE) (','?)!;
direct_value 	:	(DECIMAL_VALUE | HEX_VALUE);

中的DECIMAL_VALUE再去匹配对应的数字1,就没了,所以就出现了:

no viable alternative at input ‘1’

的错误。

 

解决办法是:

方案1:

要么把UNSIGNED_CHAR_NUMBER部分删除掉,这样,对于任何输入的十进制的立即数,都去用DECIMAL_VALUE匹配,就不会有歧义和误判了。

方案2:

要么是把现有的DECIMAL_VALUE,拆分成:

0-255的UNSIGNED_CHAR_NUMBER

加上余下的,255到无穷大的部分

即:

  • 删除掉原有的
  • 保留UNSIGNED_CHAR_NUMBER,但是最好改名为:DECIMAL_0_255
  • 再写一个DECIMAL_255_MAX
  • 把原有的DECIMAL_VALUE的表示方法去掉,换成(DECIMAL_0_255 | DECIMAL_255_MAX)

如此,就可以解决了:

去匹配任何的十进制的立即数,使用:DECIMAL_VALUE

去匹配0-255的十进制的立即数,使用:DECIMAL_0_255

就不会产生冲突了。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量