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

Antlr:如何在访客实现中打开令牌类型

如何解决Antlr:如何在访客实现中打开令牌类型

我正在和Antlr玩耍,设计一种玩具语言,我认为这是大多数人开始的地方! -我有一个问题,关于如何最好地考虑开启令牌类型。

考虑一种语言中的“函数调用”,在该语言中函数可以使用字符串,数字或变量-例如下面的示例(project()函数调用

project("ABC") vs project(123) vs project($SOME_VARIABLE)

我的语法中有一个运算符,所以语法可以解析正确的内容,但是在访问者代码中,最好分辨出上述三个版本之间的区别。


   @Override
    public ASTRoot visitCreateproj(projectmgmtParser.CreateprojContext ctx) {


        try {
             s1 = ctx.STRING_LIteraL().getText();
        }catch(Exception e){}
        try{
             s2 = ctx.NUM().getText();
        }catch(Exception e){}
        System.out.println("Created Project via => "  + ctx.getChild(1).toString());
    }

上面的代码有效,具体取决于s1s2是否为空,我可以推断出我如何被调用(使用文字或数字,我没有在上面显示变量的大小写) ,但我对是否有更好或更优雅的方式感兴趣-例如,在访问者代码中启用令牌类型以实际处理该语言。

我上面的语法是

createproj: 'project('WS?(STRING_LIteraL|NUM)')';

当我使用intellij antlr插件时,似乎知道project()函数的参数的令牌类型-但我似乎无法从我的代码获取它。

解决方法

您可以执行以下操作:

createproj
 : 'project' '(' WS? param ')'
 ;

param
 : STRING_LITERAL 
 | NUM
 ;

以及您的访客代码:

@Override
public ASTRoot visitCreateproj(projectmgmtParser.CreateprojContext ctx) {
  switch(ctx.param().start.getType()) {
    case YourLexerName.STRING_LITERAL:
      ...
    case YourLexerName.NUM:
      ...
    ...
  }
}

因此,通过在我原来的语法中插入标记,我失去了在访问者代码中检查标记的机会了?

不是,您也可以这样:

createproj
 : 'project' '(' WS? param_token=(STRING_LITERAL | NUM) ')'
 ;

然后可以执行以下操作:

@Override
public ASTRoot visitCreateproj(projectmgmtParser.CreateprojContext ctx) {
  switch(ctx.param_token.getType()) {
    case YourLexerName.STRING_LITERAL:
      ...
    case YourLexerName.NUM:
      ...
    ...
  }
}

只需确保在集合param_token=( ... )中不要混合使用词法分析器规则(令牌)和解析器规则。当它是解析器规则时,ctx.param_token.getType()将失败(然后必须为ctx.param_token.start.getType())。这就是为什么我建议添加一个额外的解析器规则的原因,因为这样仍然可以:

param
 : STRING_LITERAL 
 | NUM
 | some_parser_rule
 ;

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