【问题标题】:How can I set an ANTLR token value from an input parameter?如何从输入参数设置 ANTLR 令牌值?
【发布时间】:2015-03-16 17:08:11
【问题描述】:

假设我在 ANTLR 4 中定义了一个非常简单的语法:

input : String Separator String ;
String : 'a'..'z' ;
Separator : ',' ;

对于这个语法,分隔符是固定的;它永远是一个逗号。有没有办法使分隔符变量?也就是说,我想使用输入参数定义分隔符,该参数由调用词法分析器的代码设置。我可以像这样定义一个 getter 和 setter:

@lexer::members
{
    String sep = ",";

    public void setSep(String sep)
    {
        this.sep = sep;
    }

    private String getSep()
    {
        return sep;
    }
}

但是如何更改词法分析器规则中分隔符的值?这很接近,但错误:

Separator : ',' { setText(getSep()); } ;

【问题讨论】:

    标签: antlr4 parser-generator


    【解决方案1】:

    在查看了其他一些问题后,我决定尝试使用语义谓词来解决这个问题。这是我的完整解决方案:

    grammar InputCombinedGrammar;
    
    @parser::members
    {
        String sep = ",";
    
        public void setSep(String sep)
        {
            this.sep = sep;
        }
    
        private String getSep()
        {
            return sep;
        }
    }
    
    input : String { getSep().equals(_input.LT(1).getText()) }? Separator String EOF ;
    String : 'a'..'z' ;
    Separator : . ;
    

    需要注意的两点:

    1. 分隔符将匹配任何字符,而不仅仅是逗号。
    2. 语义谓词使用前瞻将下一个标记与分隔符进行比较。如果匹配,则规则继续。如果不是,则会抛出错误。

    此解决方案信任语义谓词仅使用正确的分隔符。我对这个解决方案很满意,但我想看看其他解决方案。

    【讨论】:

      【解决方案2】:

      我会在词法分析器中处理它:

      @lexer::members {
        ...
      }
      
      input : String Separator String EOF ;
      
      Separator : { sep.equals(_input.LA(1).getText()) }? . ;
      String : 'a'..'z' ;
      

      如果您在解析器中执行此操作,则所有在Separator : . ; 之后定义的规则 永远不能是单个字符,因为它会被Separator 规则捕获。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-17
        相关资源
        最近更新 更多