diff --git a/CMakeLists.txt b/CMakeLists.txt index 1652863..ee1ee34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,11 @@ configure_file( add_library(diagon_base STATIC src/translator/Translator.cpp src/translator/Translator.h + src/translator/antlr_error_listener.cpp + src/translator/antlr_error_listener.h +) +target_link_libraries(diagon_base + PRIVATE antlr4_static ) target_set_common(diagon_base) diff --git a/src/translator/antlr_error_listener.cpp b/src/translator/antlr_error_listener.cpp new file mode 100644 index 0000000..904bca8 --- /dev/null +++ b/src/translator/antlr_error_listener.cpp @@ -0,0 +1,13 @@ +#include "translator/antlr_error_listener.h" +#include + +void AntlrErrorListener::syntaxError(antlr4::Recognizer* recognizer, + antlr4::Token* offendingSymbol, + size_t line, + size_t charPositionInLine, + const std::string& msg, + std::exception_ptr e) { + std::stringstream s; + s << "Line(" << line << ":" << charPositionInLine << ") Error(" << msg << ")"; + throw std::invalid_argument(s.str()); +} diff --git a/src/translator/antlr_error_listener.h b/src/translator/antlr_error_listener.h new file mode 100644 index 0000000..5652b25 --- /dev/null +++ b/src/translator/antlr_error_listener.h @@ -0,0 +1,15 @@ +#ifndef TRANSLATOR_ANTLR_ERROR_LISTENER_HPP +#define TRANSLATOR_ANTLR_ERROR_LISTENER_HPP + +#include + +class AntlrErrorListener : public antlr4::BaseErrorListener { + void syntaxError(antlr4::Recognizer* recognizer, + antlr4::Token* offendingSymbol, + size_t line, + size_t charPositionInLine, + const std::string& msg, + std::exception_ptr e) final; +}; + +#endif // TRANSLATOR_ANTLR_ERROR_LISTENER_HPP diff --git a/src/translator/flowchart/Flowchart.cpp b/src/translator/flowchart/Flowchart.cpp index 02e4b60..3313eb8 100644 --- a/src/translator/flowchart/Flowchart.cpp +++ b/src/translator/flowchart/Flowchart.cpp @@ -7,8 +7,8 @@ #include #include #include "screen/Screen.h" - #include "translator/Translator.h" +#include "translator/antlr_error_listener.h" #include "translator/flowchart/FlowchartLexer.h" #include "translator/flowchart/FlowchartParser.h" #include "util.hpp" @@ -636,8 +636,20 @@ std::string Flowchart::Translate(const std::string& input, antlr4::CommonTokenStream tokens(&lexer); tokens.fill(); + // Parser: FlowchartParser parser(&tokens); - return Parse(parser.program(), true).screen.ToString(); + + AntlrErrorListener error_listener; + parser.addErrorListener(&error_listener); + + FlowchartParser::ProgramContext* context = nullptr; + try { + context = parser.program(); + } catch (...) { + return ""; + } + + return Parse(context, true).screen.ToString(); } } // namespace diff --git a/src/translator/graph_planar/GraphPlanar.cpp b/src/translator/graph_planar/GraphPlanar.cpp index 06b73f6..7f8973d 100644 --- a/src/translator/graph_planar/GraphPlanar.cpp +++ b/src/translator/graph_planar/GraphPlanar.cpp @@ -10,6 +10,7 @@ #include #include "screen/Screen.h" #include "translator/Translator.h" +#include "translator/antlr_error_listener.h" #include "translator/graph_planar/GraphPlanarLexer.h" #include "translator/graph_planar/GraphPlanarParser.h" @@ -201,8 +202,18 @@ void GraphPlanar::Read(const std::string& input) { antlr4::CommonTokenStream tokens(&lexer); tokens.fill(); + // Parser: + AntlrErrorListener error_listener; GraphPlanarParser parser(&tokens); - ReadGraph(parser.graph()); + parser.addErrorListener(&error_listener); + GraphPlanarParser::GraphContext* context = nullptr; + try { + context = parser.graph(); + } catch (...) { + return; + } + + ReadGraph(context); } void GraphPlanar::ReadGraph(GraphPlanarParser::GraphContext* graph) { diff --git a/src/translator/math/Math.cpp b/src/translator/math/Math.cpp index 7a270a3..11d99eb 100644 --- a/src/translator/math/Math.cpp +++ b/src/translator/math/Math.cpp @@ -8,6 +8,7 @@ #include "translator/Translator.h" #include "translator/math/MathLexer.h" #include "translator/math/MathParser.h" +#include "translator/antlr_error_listener.h" class Screen; @@ -1291,7 +1292,6 @@ class Math : public Translator { }; } - // antlr4::ANTLRInputStream input_stream(input); // Lexer. @@ -1300,8 +1300,16 @@ class Math : public Translator { tokens.fill(); // Parser. + AntlrErrorListener error_listener; MathParser parser(&tokens); - auto* content = parser.multilineEquation(); + parser.addErrorListener(&error_listener); + + MathParser::MultilineEquationContext* content = nullptr; + try { + content = parser.multilineEquation(); + } catch (...) { + return ""; + } if (options["style"] == "Latex") return to_string(ParseLatex(content, &style)) + '\n'; diff --git a/src/translator/sequence/Sequence.cpp b/src/translator/sequence/Sequence.cpp index b7b6fab..7629ea7 100644 --- a/src/translator/sequence/Sequence.cpp +++ b/src/translator/sequence/Sequence.cpp @@ -11,6 +11,7 @@ #include #include #include "screen/Screen.h" +#include "translator/antlr_error_listener.h" #include "translator/sequence/Graph.hpp" void Actor::Draw(Screen& screen, int height) { @@ -269,10 +270,16 @@ void Sequence::ComputeInternalRepresentation(const std::string& input) { tokens.fill(); // Parser. + AntlrErrorListener error_listener; SequenceParser parser(&tokens); + parser.addErrorListener(&error_listener); - // Print the tree. - auto program = parser.program(); + SequenceParser::ProgramContext* program = nullptr; + try { + program = parser.program(); + } catch (...) { + return; + } for (SequenceParser::CommandContext* command : program->command()) { AddCommand(command);