【问题】
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]) |
对应错误截图为:
【解决过程】
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
就不会产生冲突了。
转载请注明:在路上 » 【已解决】antlr代码执行出错:xxx.ddl line 16:13 no viable alternative at input ‘1’,Recognition exception NoViableAltException(0@[null])