为什么 antrl4 不将标记识别为语法规则的一部分?
Why is antrl4 not recognizing tokens as part of rules in grammar?
我正在使用 antlr4 来解析 .eds 文件。我写了一个语法,但我遇到了一个问题,即解析器将一个部分的 body 中的每个标记解析为 body 的一部分。似乎 antlr4 只是忽略了我对 body.
的语法规则
这是我的语法:
grammar test;
eds : section+;
section : header body;
header : '[' header_name ']';
body : field+;
field : name '=' value STMTEND;
header_name : ~(']')+;
name : Identifier;
raw_value : string
| integer
| hex
| version
| date
| time;
value : raw_value
| list;
list : raw_value list_value+;
list_value : ',' raw_value
| ',';
string : String_standard
| string_list;
string_list : String_standard string_list
| String_standard String_standard;
integer : Integer;
version : Version;
date : Date;
time : Time;
hex : Hex;
String_standard : '"' ( Escape | ~('\'' | '\' | '\n' | '\r') | '.' | '+' + '/' | ' ') + '"';
Escape : '\' ( '\'' | '\' );
Integer : NUMBER+;
Hex : '0' 'x' HEX_DIGIT+;
Version : NUMBER+ '.' NUMBER+
| NUMBER+ '.' NUMBER+ '.' NUMBER+
| NUMBER+ '.' NUMBER+ '.' NUMBER+ '.' NUMBER+;
Date : NUMBER NUMBER '-' NUMBER NUMBER '-' NUMBER NUMBER NUMBER NUMBER;
Time : NUMBER NUMBER ':' NUMBER NUMBER ':' NUMBER NUMBER;
Identifier : Identifier_Char+;
HeaderID : Header_Char+;
fragment
Identifier_Char : LETTER
| NUMBER
| '_';
fragment
Header_Char : LETTER
| NUMBER
| '_'
| ' ';
fragment LETTER : [a-zA-Z];
fragment HEX_DIGIT : [a-fA-F0-9];
fragment NUMBER : [0-9];
STMTEND : SEMICOLON;
fragment SEMICOLON : ';';
fragment NEWLINE : '\r' '\n' | '\n' | '\r';
WS: [ \t\r\n\u000C]+ -> channel(HIDDEN);
LINE_COMMENT: '$' ~[\r\n]* -> channel(HIDDEN);
这是我的输入:
[File]
DescText = "EtherNet/IP EDS for ANT lite+ PLC";
CreateDate = 02-16-2018;
CreateTime = 14:13:46;
ModDate = 10-11-2019;
ModTime = 11:05:09;
Revision = 1.2;
HomeURL = "www.bluebotics.com";
1_IOC_Details_License = 0x7B457ED4;
当我用 antlr4 gui 可视化解析树时,我看到 header 被正确解析但是 body 每个标记只有一个 child:
这是树输出,您可以看到它根本没有解析 body:
(eds (section (header [ (header_name File) ]) (body DescText = "EtherNet/IP EDS for ANT lite+ PLC" ; CreateDate = 02 16 2018 ; CreateTime = 14 13 46 ; ModDate = 10 11 2019 ; ModTime = 11 05 09 ; Revision = 1 2 ; HomeURL = "www.bluebotics.com" ; 1_IOC_Details_License = 0x7B457ED4 ;)))
如何更改我的语法以便 antlr 真正解析 body?
将 ANY : .;
放在语法的末尾,这样词法分析器就不会产生任何 errors/warnings。这样,就更容易看出哪里出了问题。添加 ANY
规则后,您将看到您的输入被标记为如下所示:
null `[`
Identifier `File`
null `]`
WS `\n `
HeaderID `DescText `
null `=`
HeaderID ` `
String_standard `"EtherNet/IP EDS for ANT lite+ PLC"`
STMTEND `;`
WS `\n `
HeaderID `CreateDate `
null `=`
HeaderID ` 02`
ANY `-`
Integer `16`
ANY `-`
Integer `2018`
STMTEND `;`
WS `\n `
HeaderID `CreateTime `
null `=`
HeaderID ` 14`
ANY `:`
Integer `13`
ANY `:`
Integer `46`
STMTEND `;`
WS `\n `
HeaderID `ModDate `
null `=`
HeaderID ` 10`
ANY `-`
Integer `11`
ANY `-`
Integer `2019`
STMTEND `;`
WS `\n `
HeaderID `ModTime `
null `=`
HeaderID ` 11`
ANY `:`
Integer `05`
ANY `:`
Integer `09`
STMTEND `;`
WS `\n `
HeaderID `Revision `
null `=`
HeaderID ` 1`
ANY `.`
Integer `2`
STMTEND `;`
WS `\n `
HeaderID `HomeURL `
null `=`
HeaderID ` `
String_standard `"www.bluebotics.com"`
STMTEND `;`
WS `\n `
HeaderID `1_IOC_Details_License `
null `=`
HeaderID ` 0x7B457ED4`
STMTEND `;`
EOF `<EOF>`
如您所见,您的 HeaderID
搞砸了:它真的不应该包含空格。删除此 HeaderID
规则(以及 ANY
规则),您的解析器将正确解析它:
我正在使用 antlr4 来解析 .eds 文件。我写了一个语法,但我遇到了一个问题,即解析器将一个部分的 body 中的每个标记解析为 body 的一部分。似乎 antlr4 只是忽略了我对 body.
的语法规则这是我的语法:
grammar test;
eds : section+;
section : header body;
header : '[' header_name ']';
body : field+;
field : name '=' value STMTEND;
header_name : ~(']')+;
name : Identifier;
raw_value : string
| integer
| hex
| version
| date
| time;
value : raw_value
| list;
list : raw_value list_value+;
list_value : ',' raw_value
| ',';
string : String_standard
| string_list;
string_list : String_standard string_list
| String_standard String_standard;
integer : Integer;
version : Version;
date : Date;
time : Time;
hex : Hex;
String_standard : '"' ( Escape | ~('\'' | '\' | '\n' | '\r') | '.' | '+' + '/' | ' ') + '"';
Escape : '\' ( '\'' | '\' );
Integer : NUMBER+;
Hex : '0' 'x' HEX_DIGIT+;
Version : NUMBER+ '.' NUMBER+
| NUMBER+ '.' NUMBER+ '.' NUMBER+
| NUMBER+ '.' NUMBER+ '.' NUMBER+ '.' NUMBER+;
Date : NUMBER NUMBER '-' NUMBER NUMBER '-' NUMBER NUMBER NUMBER NUMBER;
Time : NUMBER NUMBER ':' NUMBER NUMBER ':' NUMBER NUMBER;
Identifier : Identifier_Char+;
HeaderID : Header_Char+;
fragment
Identifier_Char : LETTER
| NUMBER
| '_';
fragment
Header_Char : LETTER
| NUMBER
| '_'
| ' ';
fragment LETTER : [a-zA-Z];
fragment HEX_DIGIT : [a-fA-F0-9];
fragment NUMBER : [0-9];
STMTEND : SEMICOLON;
fragment SEMICOLON : ';';
fragment NEWLINE : '\r' '\n' | '\n' | '\r';
WS: [ \t\r\n\u000C]+ -> channel(HIDDEN);
LINE_COMMENT: '$' ~[\r\n]* -> channel(HIDDEN);
这是我的输入:
[File]
DescText = "EtherNet/IP EDS for ANT lite+ PLC";
CreateDate = 02-16-2018;
CreateTime = 14:13:46;
ModDate = 10-11-2019;
ModTime = 11:05:09;
Revision = 1.2;
HomeURL = "www.bluebotics.com";
1_IOC_Details_License = 0x7B457ED4;
当我用 antlr4 gui 可视化解析树时,我看到 header 被正确解析但是 body 每个标记只有一个 child:
这是树输出,您可以看到它根本没有解析 body:
(eds (section (header [ (header_name File) ]) (body DescText = "EtherNet/IP EDS for ANT lite+ PLC" ; CreateDate = 02 16 2018 ; CreateTime = 14 13 46 ; ModDate = 10 11 2019 ; ModTime = 11 05 09 ; Revision = 1 2 ; HomeURL = "www.bluebotics.com" ; 1_IOC_Details_License = 0x7B457ED4 ;)))
如何更改我的语法以便 antlr 真正解析 body?
将 ANY : .;
放在语法的末尾,这样词法分析器就不会产生任何 errors/warnings。这样,就更容易看出哪里出了问题。添加 ANY
规则后,您将看到您的输入被标记为如下所示:
null `[`
Identifier `File`
null `]`
WS `\n `
HeaderID `DescText `
null `=`
HeaderID ` `
String_standard `"EtherNet/IP EDS for ANT lite+ PLC"`
STMTEND `;`
WS `\n `
HeaderID `CreateDate `
null `=`
HeaderID ` 02`
ANY `-`
Integer `16`
ANY `-`
Integer `2018`
STMTEND `;`
WS `\n `
HeaderID `CreateTime `
null `=`
HeaderID ` 14`
ANY `:`
Integer `13`
ANY `:`
Integer `46`
STMTEND `;`
WS `\n `
HeaderID `ModDate `
null `=`
HeaderID ` 10`
ANY `-`
Integer `11`
ANY `-`
Integer `2019`
STMTEND `;`
WS `\n `
HeaderID `ModTime `
null `=`
HeaderID ` 11`
ANY `:`
Integer `05`
ANY `:`
Integer `09`
STMTEND `;`
WS `\n `
HeaderID `Revision `
null `=`
HeaderID ` 1`
ANY `.`
Integer `2`
STMTEND `;`
WS `\n `
HeaderID `HomeURL `
null `=`
HeaderID ` `
String_standard `"www.bluebotics.com"`
STMTEND `;`
WS `\n `
HeaderID `1_IOC_Details_License `
null `=`
HeaderID ` 0x7B457ED4`
STMTEND `;`
EOF `<EOF>`
如您所见,您的 HeaderID
搞砸了:它真的不应该包含空格。删除此 HeaderID
规则(以及 ANY
规则),您的解析器将正确解析它: