走 ParseTree ANTLR4 的正确方法
Correct way to walk a ParseTree ANTLR4
我正在尝试使用带有 C++ 目标的 ANTLR4 来实现 TSql 解析器。我抓取了语法文件 here. The jar was used to make the corresponding source files (and changed all NULL
to null
in TSqlParser.cpp because of conflict). I am following the doc example(以及网络上的所有其他示例),它展示了如何实现一个工作正常的规则和侦听器。实施多个规则时会出现问题。
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
所以我认为它只是吞噬了整个输入。似乎我需要对所有内容进行硬编码才能获得我想要的东西。我的问题是,如何在解析文件时让正确的侦听器调用自己?我觉得我在这里缺少 ANTLR 的一些非常关键的东西。我真的不需要一个完整的答案,我只需要有人给我指出正确的方向。它可能是一个 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();
我正在尝试使用带有 C++ 目标的 ANTLR4 来实现 TSql 解析器。我抓取了语法文件 here. The jar was used to make the corresponding source files (and changed all NULL
to null
in TSqlParser.cpp because of conflict). I am following the doc example(以及网络上的所有其他示例),它展示了如何实现一个工作正常的规则和侦听器。实施多个规则时会出现问题。
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
所以我认为它只是吞噬了整个输入。似乎我需要对所有内容进行硬编码才能获得我想要的东西。我的问题是,如何在解析文件时让正确的侦听器调用自己?我觉得我在这里缺少 ANTLR 的一些非常关键的东西。我真的不需要一个完整的答案,我只需要有人给我指出正确的方向。它可能是一个 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();