diff --git a/apps/interpreter/source/main.cpp b/apps/interpreter/source/main.cpp index a761c65..11286da 100644 --- a/apps/interpreter/source/main.cpp +++ b/apps/interpreter/source/main.cpp @@ -1,11 +1,12 @@ #include +#include #include #include #include #include -int main(int argc, char ** argv) +int main(int argc, char ** argv) try { if (argc == 1) { @@ -43,3 +44,7 @@ int main(int argc, char ** argv) interpreter::dump(std::cout, context); } } +catch (pslang::parser::parse_error const & error) +{ + std::cerr << "Parse error at " << error.location() << ":\n " << error.what() << std::endl; +} diff --git a/libs/parser/CMakeLists.txt b/libs/parser/CMakeLists.txt index c331a2c..e8ed47b 100644 --- a/libs/parser/CMakeLists.txt +++ b/libs/parser/CMakeLists.txt @@ -10,6 +10,8 @@ set(PSLANG_LEXER_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/generated/gen_lexer.cp set(PSLANG_PARSER_HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/generated/gen_parser.hpp") set(PSLANG_PARSER_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/generated/gen_parser.cpp") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated/pslang/parser") + flex_target( generate-pslang-lexer ${PSLANG_LEXER_RULES_FILE} diff --git a/libs/parser/include/pslang/parser/error.hpp b/libs/parser/include/pslang/parser/error.hpp new file mode 100644 index 0000000..98238eb --- /dev/null +++ b/libs/parser/include/pslang/parser/error.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include + +namespace pslang::parser +{ + + struct parse_error + : std::exception + { + parse_error(std::string message, bison::location location) + : message_(std::move(message)) + , filename_(*location.begin.filename) + , location_(location) + { + location_.begin.filename = &filename_; + location_.end.filename = &filename_; + } + + char const * what() const noexcept + { + return message_.c_str(); + } + + bison::location location() const noexcept + { + return location_; + } + + private: + std::string message_; + std::string filename_; + bison::location location_; + }; + +} diff --git a/libs/parser/rules/pslang.l b/libs/parser/rules/pslang.l index 22a2541..c579cf4 100644 --- a/libs/parser/rules/pslang.l +++ b/libs/parser/rules/pslang.l @@ -4,6 +4,7 @@ #include "gen_parser.hpp" #include +#include using bp = ::pslang::parser::bison::parser; @@ -80,4 +81,4 @@ f64 { return bp::make_f64(ctx.location); } <> { return bp::make_end(ctx.location); } -. { throw std::runtime_error(std::string("Unexpected character: ") + yytext); } +. { throw ::pslang::parser::parse_error("unexpected character \"" + std::string(yytext) + "\"", ctx.location); } diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index daeb50f..0e0a0dc 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -4,7 +4,8 @@ %language "C++" %define api.namespace {pslang::parser::bison} -%define api.location.file none +%define api.location.file "pslang/parser/location.hpp" +%define api.location.include "" %define api.token.raw %define api.token.constructor @@ -45,6 +46,7 @@ struct context; %code { #include +#include #include #include @@ -279,7 +281,5 @@ literal void pslang::parser::bison::parser::error(location_type const& location, std::string const& message) { - std::ostringstream os; - os << "Error parsing at " << location << ": " << message << "\n"; - throw std::runtime_error(os.str()); + throw ::pslang::parser::parse_error(message, location); }