微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 antrl4 不能将标记识别为语法规则的一部分?

如何解决为什么 antrl4 不能将标记识别为语法规则的一部分?

我正在使用 antlr4 来解析 .eds 文件。我写了一个语法,但我遇到了一个问题,解析器将部分正文中的每个标记解析为正文的一部分。似乎 antlr4 只是忽略了我的正文语法规则。

这是我的语法:

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 可视化解析树时,我看到标头被正确解析,但主体对于每个标记只有一个子代:

这是树输出,您可以看到它根本没有解析正文:

(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 真正解析正文?

解决方法

ANY : .; 放在语法的末尾,以便词法分析器不会产生任何错误/警告。这样,更容易看出哪里出了问题。添加 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 规则),您的解析器将正确解析它:

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。