【问题】
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])