我正在使用antlr4 c ++目标。我不知道如何捕获解析异常,也找不到有关它的文档。
我尝试使用parser.setErrorHandler(std::make_shared<antlr4::BailErrorStrategy>());
,但是它抛出了一个异常,其“ e.what()”为空。
try {
ANTLRInputStream instream(sql);
MyLexer lexer(&instream);
CommonTokenStream tokens(&lexer);
MyParser parser(&tokens);
// parser.setErrorHandler(std::make_shared<antlr4::BailErrorStrategy>());
auto ctx = parser.singleStatement();
...
} catch(ParseCancellationException& e) {
std::cout << string(e.what()) << std::endl;
throw MyParseException(e.what());
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
我希望捕捉到诸如“行1:19缺少';'之类的异常消息。在“”,然后使用我自己的异常类型将其重新抛出。
答案 0 :(得分:0)
ParseCancellationException
不包含有关遇到的语法错误的任何信息,因此它们不适合错误报告。 BailErrorStrategy
实际上仅适用于您不想报告错误的情况。
相反,您应该坚持默认的错误处理策略,并注册自己的错误侦听器(在用removeErrorListeners
删除默认侦听器之后,除非您希望执行任何操作后仍将错误消息打印到stderr报告和/或处理错误)。将使用正确报告错误所需的所有信息来调用错误侦听器。然后,您可以直接使用该信息引发异常,也可以将错误信息存储在向量中,然后在解析器完成后引发包含有关 all 语法错误信息的异常。
答案 1 :(得分:0)
没有可以捕获的解析异常。 ParseCancellationException
非常特殊,因为它用于实施提早退出策略(通常与两阶段方法结合使用,以SLL模式开始解析(对于语法正确的输入来说更快)并继续执行。 LL模式(如果第一阶段失败)会产生异常,以便绕过通常在解析错误时出现的所有catch子句。
捕获解析错误的正确方法是(如已经提到的sepp2k),方法是添加自己的错误侦听器,并使用所有必要的信息(位置,违规令牌等)调用该侦听器,以便为用户创建自己的错误
我已经在MySQL Workbench中实现了该方法。检查代码for the parse step和lexer以及那里的parser error处理。