为什么 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 规则),您的解析器将正确解析它: