Правильный способ пройтись по ParseTree ANTLR4 - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь реализовать синтаксический анализатор TSql с использованием ANTLR4 с целью C ++.Я взял файлы грамматики здесь .Jar-файл использовался для создания соответствующих исходных файлов (и из-за конфликта изменил все NULL на null в TSqlParser.cpp).Я следую примеру doc (и каждому другому примеру в сети), который показывает, как реализовать одно правило и прослушиватель, который работает нормально.Проблема возникает при реализации нескольких правил.

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";
}

А вот немногоtest sql file:

SELECT TOP 1 NAME
FROM MYTABLE
WHERE SEQ = 6

UPDATE MYTABLE
SET NAME = 'Bob'
WHERE SEQ = 5

output:

line 1:0 mismatched input 'SELECT' expecting {'UPDATE', 'WITH'}
Hello Update

Если я переключу операторы SQL, я получу только Hello Update, так что я думаю, что это просто сожрало весь ввод,Кажется, что мне нужно все жестко написать, чтобы получить то, что я хочу.У меня вопрос, как мне заставить правильных слушателей называть себя, когда я анализирую файл?Я чувствую, что мне здесь не хватает чего-то очень важного для АНТЛР.Мне действительно не нужен полный ответ, мне просто нужен кто-то, чтобы указать мне правильное направление.Это может быть страница API ... Прошло много времени с тех пор, как я написал какую-либо Java, но она достаточно хорошо переводится, чтобы я мог понять это оттуда.

1 Ответ

0 голосов
/ 08 октября 2018

Если вы строите свое дерево по

antlr4::tree::ParseTree *update_tree = parser.update_statement();

, вы используете только подмножество вашей грамматики, потому что ваша точка входа - tsql_file.update_statement является правилом для ключевого слова SQL UPDATE, поэтому он не знает, что делать с SELECT.

Вместо этого вы должны построить свое дерево по

antlr4::tree::ParseTree *tsql_file_tree = parser.tsql_file();
...