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

在ANTLR4中使用令牌令牌

如何解决在ANTLR4中使用令牌令牌

我遇到了ANTLR的问题,我想知道在ANTLR中这种情况是否可以接受。我在下面准备了一个非常简化的示例。

grammar test;

test
    : statement*
    ;

statement
    : s1
    | s2
    ;

s1
    : 'OK' INT
    ;

s2
    : 'ABC' US_INT
    ;

INT
    : S_INT
    | US_INT
    ;

S_INT
   : [+-] [0-9]+
   ;

US_INT
    : [0-9]+
    ;

对于OK 5,一切正常,但是对于ABC 5,我收到以下错误消息:

line 1:4 mismatched input '5' expecting US_INT

我在运行grun时使用了-tokens选项,我在这里INT而不是US_INT

[@1,4:4='5',<INT>,1:4]

这让我想知道ANTLR中的这种情况是否完全可能。以前,我尝试过对令牌重新排序,将US_INT,{fragment和其他内容移出INT,但效果不佳。唯一的变化是OK 5停止工作,ABC 5开始工作。我希望这两种情况都能正常运行。

解决方法

您面临的问题非常简单:5可以同时匹配:US_INT(因为它包含US_INT)和S_INT本身。但是,只要声明INT高于US_INT,词法分析器就会将5解析为INT

要解决此问题,建议您将INT从词法分析器标记移至解析器规则,如下所示:

grammar test;

test
    : statement*
    ;

statement
    : s1
    | s2
    ;

s1
    : 'OK' int_stmt
    ;

s2
    : 'ABC' US_INT
    ;
    
int_stmt
    : S_INT | US_INT
    ;

S_INT
   : [+-] [0-9]+
   ;

US_INT
    : [0-9]+
    ;
,

在这种情况下,如果您想逃避词法处理的优先级,则可以在Tunnel Grammar Studio中使用此ABNF解析器语法,而该语法完全没有此问题:

test         = *statement
statement    = s-ok / s-abc
s-ok         = "OK" 1*ws int
s-abc        = "ABC" 1*ws unsigned-int
int          = signed-int / unsigned-int
signed-int   = ('+' / '-') unsigned-int 
unsigned-int = 1*('0'-'9')
ws           = %x20 / %x9 / %xA / %xD

这是区分大小写的匹配的情况,如ABNF(RFC 5234)中所定义。您还可以将每个字符串的区分大小写或不区分大小写的匹配分别定义为%s"ABC"%i"ABC"(RFC 7405)。当您开始有更多的语句时,一些字符串将开始重叠,那么您可以在lexer语法中成为关键字:

keyword      = %s"OK" / %s"OK2"

,并在解析器语法中执行:

s-ok         = {keyword,%s"OK"} 1*ws int 
s-ok-2       = {keyword,%s"OK2"} 1*ws int 1*ws int 
s-ok-any     = {keyword} 1*ws int *(ws 0*1 int)

请注意,最后一条规则将允许您在整数之间使用空格,并且任何关键字都将匹配。

*我开发了Tunnel Grammar Studio。语法非常简单,因此该演示对您来说足够了。

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