如何使用C ++捕获antlr4中的解析异常?

时间:2019-05-19 08:15:47

标签: c++ antlr4

我正在使用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缺少';'之类的异常消息。在“”,然后使用我自己的异常类型将其重新抛出。

2 个答案:

答案 0 :(得分:0)

ParseCancellationException不包含有关遇到的语法错误的任何信息,因此它们不适合错误报告。 BailErrorStrategy实际上仅适用于您不想报告错误的情况。

相反,您应该坚持默认的错误处理策略,并注册自己的错误侦听器(在用removeErrorListeners删除默认侦听器之后,除非您希望执行任何操作后仍将错误消息打印到stderr报告和/或处理错误)。将使用正确报告错误所需的所有信息来调用错误侦听器。然后,您可以直接使用该信息引发异常,也可以将错误信息存储在向量中,然后在解析器完成后引发包含有关 all 语法错误信息的异常。

答案 1 :(得分:0)

没有可以捕获的解析异常。 ParseCancellationException非常特殊,因为它用于实施提早退出策略(通常与两阶段方法结合使用,以SLL模式开始解析(对于语法正确的输入来说更快)并继续执行。 LL模式(如果第一阶段失败)会产生异常,以便绕过通常在解析错误时出现的所有catch子句。

捕获解析错误的正确方法是(如已经提到的sepp2k),方法是添加自己的错误侦听器,并使用所有必要的信息(位置,违规令牌等)调用该侦听器,以便为用户创建自己的错误

我已经在MySQL Workbench中实现了该方法。检查代码for the parse steplexer以及那里的parser error处理。