首页 > 解决方案 > 有没有人成功使用 Antlr v4 为 Hive 生成​​ javascript

问题描述

我的目标是用 javascript 解析 SQL(特别是 Hive)语句,最好是 Nodejs。我从看起来很有希望的 node-sql-parser 开始。但是,我发现很多情况下,解析器无法识别有效的 SQL,例如 select 子句中列上的多个嵌套函数,以及 SQL 中具有大量连接、联合等的多个 AND 子句。(我已记录为问题但需要一些时间)。

我决定看看 Antlr v4。我按照 Hive SQL 语法的入门步骤进行操作。(https://github.com/apache/hive/blob/master/hplsql/src/main/antlr4/org/apache/hive/hplsql/Hplsql.g4);我使用 Antlr 为 JavaSCript 生成的解析器词法分析器和侦听器 - 到目前为止一切都很好。然后我尝试了一个简单的测试,如下所示:

const HplsqlLexer = require('./HplsqlLexer');
const HplsqlParser = require('./HplsqlParser');
const input = "select * from table_a"
var chars = new antlr4.InputStream(input);
var lexer = new HplsqlLexer.HplsqlLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new HplsqlParser.HplsqlParser(tokens);
parser.buildParseTrees = true;
const tree = parser.program();

我相信“program()”是解析器的入口点,但我可能是错的。这在 parser.program() 行给了我“ReferenceError:_input 未定义”。我质疑 Hplsql.g4 是否可能缺少某些东西,但排除了这一点。然后我查看了 HplsqlParser.js 中生成的代码 - 我在顶部添加了 var _input = "" 并重新运行;然后它抱怨说没有定义LT。感觉像兔子洞。

接下来的步骤包括运行 Antlr 解析器的 Java 版本,然后是 Calcite。(hplsql.org 不是我要找的)。
节点--版本:v15.2.1。任何建议或指示都会有所帮助。

标签: sqlnode.jsparsinghiveantlr4

解决方案


正如 kaby76 在评论中提到的:语法包含目标特定(Java)代码。您需要用 TypeScipt 代码替换所有 Java{代码}?

例如,这个 Java 代码:

{!_input.LT(2).getText().equalsIgnoreCase("TRANSACTION")}?

可以改写成这样:

{this._input.LT(2).text.toUpperCase() !== 'TRANSACTION'}?

(未经测试!)

编辑

我迅速进行了全局搜索并_input\.LT\((\d+)\).getText\(\)\.equalsIgnoreCase\("(\w+)"\)用替换字符串替换了模式(this._input.LT(\1).text.toUpperCase() === '\2'),这导致了以下语法:https ://gist.github.com/bkiers/bb68b25ed03cf6c8ffae2709606d27a5

编辑 2

我很惊讶 Antlr 甚至有一个用于解析器生成的 -Dlanguage=JavaScript 标志。如果它本质上仍然是 Java,那又有什么意义呢?

确保在-Dlanguage=JavaScriptJavaScript 中生成词法分析器和解析器类。它不做的是重写语义谓词,它们只是“按原样”复制。请注意,始终建议不要使用语义谓词,而是将此类目标特定代码移动到访问者或侦听器类中。


推荐阅读