【问题】
用的是antlrworks 1.5rc2,去使用如下antlr v3的语法:
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行的内容:
// $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:
class : 'CLASS' class_value ';' ;
所以就随便改个别的:
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,即把:
class : 'CLASS' class_value ';' ;
改为:
class_line : 'CLASS' class_value ';' ;
就可以解决问题了。
转载请注明:在路上 » 【已解决】antlrworks中调试出错:xxxParser.java:1870: error: <identifier> expected