0

我正在编写一个 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 ''
           )*
      '\''
    ;

我有时会有一个奇怪的转义查询,谓词返回 true。例如:


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

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

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

4

2 回答 2

1

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

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

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

ADMIN 关键字仅适用于 < 8.0.14 的版本(只是一个示例,实际上并非如此),而 ONLY 关键字是任何版本的可能替代方案。

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

options {
    superClass = MySQLBaseRecognizer;
    tokenVocab = MySQLLexer;
}

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

您可以在MySQL Workbench Github 存储库中找到完整的代码 + 语法。

于 2020-12-30T07:52:34.743 回答
0

我想知道是否可以将参数传递给词法分析器,因此词法分析会有所不同取决于该参数?

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

于 2020-12-29T12:17:55.050 回答