From 5a7687e1b5685ee8edcee6768a967b43a7fd5570 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 3 Sep 2018 00:10:13 +0200 Subject: [PATCH] Simple grammar tests - read integer and real numbers - numbers must be followed by semi-column (instructions) - spaces and comments are consumed silently - test error message improvements (rang) --- src/language/PastisParser.cpp | 136 +++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 12 deletions(-) diff --git a/src/language/PastisParser.cpp b/src/language/PastisParser.cpp index 5752c11ae..703894b2d 100644 --- a/src/language/PastisParser.cpp +++ b/src/language/PastisParser.cpp @@ -1,46 +1,158 @@ #include <PastisParser.hpp> #include <iostream> +#include <rang.hpp> + #define TAO_PEGTL_NAMESPACE language #include <pegtl.hpp> +#include <pegtl/analyze.hpp> + namespace language { using namespace tao::language; // clang-format off -//struct prefix : string< 'H', 'e', 'l', 'l', 'o', ',', ' ' > {}; -struct prefix : TAO_PEGTL_STRING("Hello, ") {}; -struct name : plus< alpha > {}; + +struct comment + : sor< if_must< + string< '/', '/' >, + until< eolf > + >, + if_must< + string< '/', '*' >, + until< string< '*', '/' > > + > + > {}; + +struct ignored + : star< sor< space, comment> >{}; + +// struct ignored : star< space >{}; + +struct integer + : seq< opt< one< '+', '-' > >, plus< digit > >{}; +struct INTEGER : seq< integer, ignored >{}; + +struct real + : seq< opt< one< '+', + '-' > + >, + sor< seq< + plus< digit >, + one < '.' >, + star< digit > + >, + seq< + one < '.' >, + plus< digit > + > + >, + opt< + seq< + one< 'E', + 'e' >, + opt< one< '+', + '-' > + >, + plus<digit> + > + > + >{}; + +struct REAL : seq< real, ignored >{}; + +struct expression : sor< REAL, INTEGER > {}; + +struct semicol : one< ';' >{}; +struct SEMICOL : seq< semicol , ignored > {}; + +struct instruction + : sor<seq< expression , SEMICOL>, + SEMICOL> +{}; + struct grammar - : must< prefix, name, star< sor< space, digit, string < '+' >, string < '-' >, string < '/' >, string < '*' > > >, one< '!' >, eof > -{ -}; + : must<star<instruction>,eof>{}; // clang-format on template< typename Rule > -struct action - : nothing< Rule > +struct action : nothing< Rule > {}; + +template<> +struct action< integer > { + template< typename Input > + static void apply( const Input& in, std::string& v ) + { + if (v.size() > 0) { + v += std::string(", I:") + in.string(); + } else { + v = std::string("I:") + in.string(); + } + } }; template<> -struct action< name > +struct action< real > { template< typename Input > static void apply( const Input& in, std::string& v ) { - v = in.string(); + if (v.size() > 0) { + v += std::string(", R:") + in.string(); + } else { + v = std::string("R:") + in.string(); + } + } +}; + + +template< typename Rule > +struct errors + : public normal< Rule > +{ + static const std::string error_message; + + template< typename Input, typename... States > + static void raise( const Input& in, States&&... /*unused*/ ) + { + throw parse_error(error_message, std::vector{in.position()} ); } }; + +template <typename Rule> +const std::string errors<Rule>::error_message = "parse error..."; + +template <> +const std::string errors<eolf>::error_message = "parse error expecting expression"; + } void parser(const std::string& filename) { std::string name; + const size_t grammar_issues = language::analyze< language::grammar >(); + + std::cout << "grammar_issues=" << grammar_issues << '\n'; language::read_input in(filename); - language::parse< language::grammar, language::action >( in, name ); + try { + language::parse< language::grammar, language::action//, language::errors + >( in, name ); + } + catch(const language::parse_error& e) { + const auto p = e.positions.front(); + std::cerr << rang::style::bold + << p.source << ':' << p.line << ':' << p.byte_in_line<< ": " + << rang::style::reset + << rang::fgB::red << "error: " << rang::fg::reset + << rang::style::bold << e.what() << rang::style::reset << '\n' + << in.line_as_string( p ) << '\n' + << std::string( p.byte_in_line, ' ' ) + << rang::fgB::yellow << '^' << rang::fg::reset + << std::endl; + std::exit(1); + } - std::cout << name << " -> "; std::cout << "Good bye, " << name << "!" << std::endl; std::exit(0); } -- GitLab