【问题】
用的是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