Кто-нибудь добился успеха с Antlr v4, генерирующим javascript для Hive

#sql #node.js #parsing #hive #antlr4

#sql #node.js #синтаксический анализ #улей #antlr4

Вопрос:

Моя цель — проанализировать операторы SQL (в частности, Hive) с помощью javascript, предпочтительно Nodejs. Я начал с node-sql-parser, который выглядел многообещающим. Однако я обнаружил немало случаев, когда анализатор не распознал действительный SQL, например, несколько вложенных функций в столбце в предложении select и несколько предложений AND в SQL, В которых было много объединений, объединений и т. Д. (Я зарегистрировался как проблема, но это займет некоторое время).

Я решил посмотреть на Antlr v4. Я выполнил шаги по началу работы с грамматикой Hive SQL. (https://github.com/apache/hive/blob/master/hplsql/src/main/antlr4/org/apache/hive/hplsql/Hplsql.g4 ); Я сгенерировал синтаксические анализаторы lexers и listeners, используя генерацию 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 ()» является точкой входа в анализатор, но я могу ошибаться. Это дало мне «ReferenceError: _input не определен» в строке parser.program(). Я задался вопросом, может ли в Hplsql.g4 чего-то не хватать, но исключил это. Затем я просмотрел сгенерированный код в HplsqlParser.js — Я добавил var _input = «» вверху и повторил; затем он пожаловался, что ablut LT не определен. Похоже на кроличью нору.

Следующие шаги включают запуск Java-версии анализатора Antlr, затем Calcite. (hplsql.org это не то, что я ищу).
узел —версия: v15.2.1. Любые предложения или указания были бы полезны.

Комментарии:

1. Эта грамматика содержит зависящий от цели код. Я бы предположил, что это Java. Вам нужно будет изменить синтаксис файла .g4 на JavaScript. Удалите добавленный вами def для _input и измените «_input» на «this._input», а затем посмотрите, к чему это приведет. Для получения дополнительных изменений посмотрите на типы по адресу github.com/antlr/antlr4/tree/master/runtime/JavaScript/src /.

2. Я думал, что файл грамматики не зависит от языка. И Antlr сгенерирует код на целевом языке. Я попробовал несколько вариантов _input. Когда кажется, что он принят, появляется ошибка LT (я понятия не имею, как ее устранить). Спасибо за ссылку на исходный код Antlr для генерации javascript. Я, конечно, не думал, что мне придется копаться в источнике, чтобы заставить это работать.

3. Отрицательно. Это одно из больших недостатков Antlr: код, специфичный для конкретной цели, может быть встроен в CFG, и, кроме того, в файле .g4 нет ничего, что явно указывало бы, что эта грамматика должна быть сгенерирована для конкретной цели. Для дальнейших изменений, «getText ()» => «текст». Вам нужно будет что-то сделать для «equalsIgnoreCase», например, преобразовать его в нижний регистр, а затем сравнить.

Ответ №1:

Как упоминалось в комментариях kaby76: грамматика содержит целевой код (Java). Вам нужно заменить весь код Java между { и }? на код TypeScipt.

Например, этот 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=JavaScript Обязательно генерирует классы lexer и parser в JavaScript. Чего он не делает, так это переписывает семантические предикаты, которые просто копируются «как есть». Обратите внимание, что из-за этого всегда рекомендуется не использовать семантические предикаты, а перемещать такой целевой код в классы посетителей или слушателей.

Комментарии:

1. Спасибо, Барт (и kaby76), теперь я понимаю, что вы оба говорите. Я удивлен, что у Antlr даже есть флаг для -Dlanguage=JavaScript для генерации синтаксического анализатора. Какой смысл, если это все еще по сути Java?

2. @MikeLapenna добро пожаловать. Также проверьте мое РЕДАКТИРОВАНИЕ 2