【问题】
用的是antlrworks 1.5rc2,去使用如下antlr v3的语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | 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; imported_value : '[' ID ']'; /* normal ID with [] */ define_imported_value : define_value | imported_value; direct_value : (DECIMAL_VALUE | HEX_VALUE); string_value : (STRING | define_imported_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 : define_value | imported_value; label : 'REDEFINE'? 'LABEL' define_imported_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 : 'CLASS' class_value ';' ; /* TYPE ENUMERATED (4) { {0x1E6D11, "|en|Softing", [mfr_id_help]} } TYPE UNSIGNED_INTEGER (4) ; TYPE ENUMERATED (1) { _UNINITIALIZED_VALUE, { 0x01, [restart_run], [restart_run_help] }, { 0x02, [restart_resource], [restart_resource_help] }, { 0x03, [restart_defaults], [restart_defaults_help] }, { 0x04, [restart_processor], [restart_processor_help] }, { 0x05, RESTART_FACTORY_DEFAULT, RESTART_FACTORY_DEFAULT_HELP } } TYPE BIT_ENUMERATED (2) { FEATURES_RES2 } */ single_type_value : ('DOUBLE'| 'FLOAT'| 'INTEGER'| 'UNSIGNED_INTEGER'| 'DATE'| 'DATE_AND_TIME'| 'DURATION'| 'TIME'| 'TIME_VALUE'| 'BIT_ENUMERATED'| 'ENUMERATED'| 'INDEX'| 'OBJECT_REFERENCE'| 'ASCII'| 'BITSTRING'| 'EUC'| 'OCTET'| 'PACKED_ASCII'| 'PASSWORD'| 'VISIBLE'); triplet_interger: direct_value;/* TODO: support diffrent values(dicimal and others) */ triplet_description : string_value; triplet_help : string_value; triplet : '{' triplet_interger ',' triplet_description ',' triplet_help '}' ; enumerate_line : (define_value | triplet) ','; type_struct : '{' enumerate_line+ '}'; type : single_type_value '(' DECIMAL_VALUE ')' type_struct? ';' ; /* CONSTANT_UNIT "|en|1/32 millisec" ; CONSTANT_UNIT [blank] ; */ constant_unit_value : (imported_value | STRING); constant_unit : constant_unit_value ';' ; /* 7.27.2.5 HANDLING */ single_handling_value : ('READ' | 'READ_WRITE' | 'WRITE'); handling_value : single_handling_value ('&' single_handling_value)*; handling : handling_value ';' ; /* 7.27 VARIABLE Table 138 – VARIABLE attributes */ single_variable_field_m : class | label | type; variable_fields_o: help | constant_unit | handling; variable : 'REDEFINE'? 'VARIABLE' ID '{' (single_variable_field_m+ | variable_fields_o?) '}'; everything : 'EVERYTHING' ';'; //redefinitions : 'REDEFINITIONS' WS* '{' WS* (variable | record)+ '}'; 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+; |
去解析一个ddl文件。
已经是可以正常编译通过的(虽然有warning)。
但是去用antlrworks去debug时出错:
[14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1870: error: <identifier> expected [14:44:43] ^ [14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1870: error: illegal start of type [14:44:43] public final DDParserDemoParser.class_return class() throws RecognitionException { [14:44:43] ^ [14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1870: error: <identifier> expected [14:44:43] public final DDParserDemoParser.class_return class() throws RecognitionException { [14:44:43] ^ [14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1870: error: ‘;’ expected [14:44:43] public final DDParserDemoParser.class_return class() throws RecognitionException { [14:44:43] ^ [14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1870: error: <identifier> expected [14:44:43] public final DDParserDemoParser.class_return class() throws RecognitionException { [14:44:43] ^ [14:44:43] D:\DevRoot\IndustrialMobileAutomation\HandheldDataSetter\ANTLR\projects\v1.5\DDParserDemo\output\DDParserDemoParser.java:1872: error: <identifier> expected [14:44:43] retval.start = input.LT(1); [14:44:43] ^ 。。。 。。。 。。。 |
【解决过程】
1.所以就去看了看,生成的DDParserDemoParser.java的1870行的内容:
1 2 3 4 5 | // $ANTLR start "class" // D:\\DevRoot\\IndustrialMobileAutomation\\HandheldDataSetter\\ANTLR\\projects\\v1.5\\DDParserDemo\\DDParserDemo.g:142:1: class : 'CLASS' class_value ';' ; public final DDParserDemoParser.class_return class() throws RecognitionException { DDParserDemoParser.class_return retval = new DDParserDemoParser.class_return(); retval.start = input.LT(1); |
即,对应的是:
public final DDParserDemoParser.class_return class() throws RecognitionException { |
结果就是,根本看不出来,搞不懂为何出错。
2.后来发现,原来之前自己就遇到过类似的问题,在:
【已解决】ANTLRWorks 1.5编译代码出错:Compiler failed with result code 1
中,就有:
error: <identifier> expected |
3.参考:
[antlr-interest] Antlr 3.0: run time and java compiling errors
去看到解释:
This seems to be an actual problem of the grammar. It probably has a rule called "class", which is illegal in Java as "class" is a keyword. Simply rename the rule in the .g file. |
看懂了,意思就是,此处,java中本身就有个关键字是class,但是由于antlr中有个token(变量)也被定义成class,所以冲突了。
解决办法就是去把antlr中对应class这个变量改个名字。
然后就去看看原先的语法,果然有这个class:
1 | class : 'CLASS' class_value ';' ; |
所以就随便改个别的:
1 2 3 4 | class_line : 'CLASS' class_value ';' ; single_variable_field_m : class_line | label | type; |
然后再去编译和调试antlr。
然后就可以正常编译和调试了。
【总结】
现象:
antlr调试中出现“error: <identifier> expected”的错误
原因:(很可能就是由于)
antrl中的语法代码中,定义了某个token,即变量,名字叫做class
导致生成的Parser(和Lexer)的java文件中,对应的函数名或类名,叫做class
这与Java语言本身的class这个关键字冲突了。
解决办法:
把antlr语法中的,那个class的token,改个别的名字。
比如我此处就是把class改为class_line,即把:
1 | class : 'CLASS' class_value ';' ; |
改为:
1 | class_line : 'CLASS' class_value ';' ; |
就可以解决问题了。
转载请注明:在路上 » 【已解决】antlrworks中调试出错:xxxParser.java:1870: error: <identifier> expected