Я пытаюсь реализовать синтаксический анализатор TSql с использованием ANTLR4 с целью C ++. Я схватил файлы грамматики Вот. Jar был использован для создания соответствующих исходных файлов (и изменил все NULL
в null
в TSqlParser.cpp из-за конфликта). Я следую за пример документа (и любой другой пример в сети), который показывает, как реализовать единственное правило и слушатель, который работает нормально. Проблема возникает при реализации нескольких правил.
main.cpp:
#include <iostream>
#include <antlr4-runtime/antlr4-runtime.h>
#include "TSqlParser.h"#include "TSqlLexer.h"
#include "listener.h"
int main(int argc, const char* argv[])
{
std::ifstream stream;
stream.open(argv[1]);
antlr4::ANTLRInputStream input(stream);
TSqlLexer lexer(&input);
antlr4::CommonTokenStream tokens(&lexer);
TSqlParser parser(&tokens);
TreeShapeListener listener;
//antlr4::tree::ParseTree *select_tree = parser.select_statement();
antlr4::tree::ParseTree *update_tree = parser.update_statement();
//antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, select_tree);
antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, update_tree);
return 0;
}
listener.h:
#include <antlr4-runtime/antlr4-runtime.h>
#include "TSqlParserBaseListener.h"
class TreeShapeListener : public TSqlParserBaseListener
{
public:
void enterSelect_statement(TSqlParser::Select_statementContext*) override;
void enterUpdate_statement(TSqlParser::Update_statementContext*) override;
};
listener.cpp:
#include "listener.h"
void TreeShapeListener::enterSelect_statement(TSqlParser::Select_statementContext *ctx)
{
std::cout << "Hello Select\n";
}
void TreeShapeListener::enterUpdate_statement(TSqlParser::Update_statementContext *ctx)
{
std::cout << "Hello Update\n";
}
И вот небольшой тестовый файл sql:
SELECT TOP 1 NAME
FROM MYTABLE
WHERE SEQ = 6
UPDATE MYTABLE
SET NAME = 'Bob'
WHERE SEQ = 5
выход:
line 1:0 mismatched input 'SELECT' expecting {'UPDATE', 'WITH'}
Hello Update
Если я переключу операторы SQL, я получу только Hello Update
так что я думаю, что это просто поглощает весь ввод. Просто кажется, что мне нужно жестко закодировать все, чтобы получить то, что я хочу. У меня вопрос, как мне заставить правильных слушателей называть себя, когда я анализирую файл? Я чувствую, что мне здесь не хватает чего-то очень важного для АНТЛР. Мне действительно не нужен полный ответ, мне просто нужен кто-то, чтобы указать мне правильное направление. Это может быть страница API … Прошло много времени с тех пор, как я написал какую-либо Java, но она достаточно хорошо переводится, чтобы я мог понять это оттуда.
Если вы строите свое дерево
antlr4::tree::ParseTree *update_tree = parser.update_statement();
вы используете только часть вашей грамматики, потому что ваша точка входа tsql_file
,
update_statement
это правило для ключевого слова SQL UPDATE
так что он не знает, что делать с SELECT
,
Вместо этого вы должны построить свое дерево
antlr4::tree::ParseTree *tsql_file_tree = parser.tsql_file();
Других решений пока нет …