我的目标是用javascript解析sql(特别是hive)语句,最好是nodejs。我从node-sql解析器开始,它看起来很有前途。但是,我发现有很多情况下解析器无法识别有效的sql,比如select子句中一列上的几个嵌套函数,以及sql中有许多连接、联合等的多个and子句(我记录为issue,但这需要一些时间)。
我决定看看antlrv4。我遵循了hivesql语法的入门步骤(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:\u input is not defined”。我怀疑hplsql.g4是否遗漏了什么,但排除了这种可能性。然后我查看了hplsqlparser.js中生成的代码-我在顶部添加了var\u input=“”并重新运行;但它没有定义。感觉像个兔子洞。
接下来的步骤包括运行antlr解析器的java版本,然后运行calcite(我要找的不是hplsql.org)。
节点——版本:v15.2.1。任何建议或建议都会有帮助。
1条答案
按热度按时间ldfqzlk81#
正如kaby76在注解中提到的:语法包含特定于目标(java)的代码。您需要替换
{
以及}?
使用typescipt代码。例如,以下java代码:
可以改写为:
(未测试!)
编辑
我很快做了一个全球搜索和更换的模式
_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=JavaScript
确保在javascript中生成lexer和parser类。它没有做的是重写语义 predicate ,而语义 predicate 只是“按原样”复制。请注意,通常建议不要使用语义 predicate ,而是将此类特定于目标的代码移到visitor或listener类中。