如何获取 ANTLR 词法分析器对象的参数?

How to get a parameter to the ANTLR lexer object?

我正在编写 JAVA 软件来解析 SQL 查询。为此,我将 ANTLR 与 presto.g4 一起使用。 我目前使用的代码非常标准:

PrestoLexer lexer = new PrestoLexer(
              new CaseChangingCharStream(CharStreams.fromString(query), true));

      lexer.removeErrorListeners();
      lexer.addErrorListener(errorListener);

      CommonTokenStream tokens = new CommonTokenStream(lexer);
      PrestoParser parser = new PrestoParser(tokens);

我想知道是否可以将一个参数传递给词法分析器,这样词法分析就会因该参数而异?

更新: 我在下面使用了@Mike 的建议,我的词法分析器现在继承自内置词法分析器并添加了谓词函数。我现在的问题是纯粹的语法问题。

这是我的字符串定义:


STRING
    : '\'' ( '\' .
           | '\\'  .  {HelperUtils.isNeedSpecialEscaping(this)}?       // match \ followed by any char
           | ~[\']       // match anything other than \ and '
           | '\'\''       // match ''
           )*
      '\''
    ;

我有时有一个奇怪的转义查询,谓词 returns 为真。例如:


select 
table1(replace(replace(some_col,'\'',''),'\"' ,'')) as features 
from table1

当我尝试解析它时,我得到: '\'',''),'

作为单个字符串。 我该如何处理?

I wonder whether it's possible to pass a parameter to the lexer so the lexing will be different depends on that parameter?

不,词法分析器独立于解析器工作。解析时不能引导词法分析器。

我不知道你需要参数做什么,但你提到了 SQL,所以让我介绍一个我多年来使用的解决方案:谓词。

在 MySQL(这是我使用的方言)中,语法因 MySQL 版本号而异。所以在我的语法中,我使用语义谓词来关闭和打开属于特定版本的语言部分。方法很简单:

test:
    {serverVersion < 80014}? ADMIN_SYMBOL
    | ONLY_SYMBOL
;

ADMIN 关键字仅适用于 < 8.0.14 的版本(仅作为示例,实际情况并非如此),而 ONLY 关键字在任何版本中都是可能的选择。

变量 serverVersion 是我派生解析器的基础 class 的成员。可以通过以下方式指定:

options {
    superClass = MySQLBaseRecognizer;
    tokenVocab = MySQLLexer;
}

词法分析器也派生自 class,因此版本号在词法分析器和解析器中都可用(除了其他重要设置,如 SQL 模式)。使用这种方法,您还可以为谓词实现更复杂的功能,这需要额外的处理。

您可以在 MySQL Workbench Github repository.

找到完整的代码和语法