From d8948dd9361d197f60f02ad59ccf00ce6ba8182f Mon Sep 17 00:00:00 2001 From: Charles Baker Date: Sun, 21 May 2023 20:09:41 +1200 Subject: [PATCH] Report missing action handlers from Parser::valid() --- src/lalr/Parser.hpp | 11 +- src/lalr/Parser.ipp | 240 ++++++++++++++++++++++++-------------------- 2 files changed, 135 insertions(+), 116 deletions(-) diff --git a/src/lalr/Parser.hpp b/src/lalr/Parser.hpp index 425ab6d..a9e2a69 100644 --- a/src/lalr/Parser.hpp +++ b/src/lalr/Parser.hpp @@ -41,7 +41,7 @@ public: private: struct ParserActionHandler { - const ParserAction* action_; + const ParserAction* action_; ParserActionFunction function_; ParserActionHandler( const ParserAction* action, ParserActionFunction function ); }; @@ -60,12 +60,9 @@ private: public: Parser( const ParserStateMachine* state_machine, ErrorPolicy* error_policy = nullptr ); - void reset(); - void parse( Iterator start, Iterator finish ); - bool parse( const void* symbol, const std::basic_string& lexeme, int line, int column ); - bool parse( const ParserSymbol* symbol, const std::basic_string& lexeme, int line, int column ); bool accepted() const; bool full() const; + bool valid() const; const UserData& user_data() const; const Lexer& lexer() const; void fire_error(int line, int column, int error, const char* format, ... ) const; @@ -78,6 +75,10 @@ public: void set_action_handler( const char* identifier, ParserActionFunction function ); void set_lexer_action_handler( const char* identifier, LexerActionFunction function ); void set_debug_enabled( bool debug_enabled ); + void reset(); + void parse( Iterator start, Iterator finish ); + bool parse( const void* symbol, const std::basic_string& lexeme, int line, int column ); + bool parse( const ParserSymbol* symbol, const std::basic_string& lexeme, int line, int column ); private: const ParserTransition* find_transition( const ParserSymbol* symbol, const ParserState* state ) const; diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index 2fa1995..30f5670 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -88,117 +88,6 @@ Parser::Parser( const ParserStateMa user_data_.push_back( UserData() ); } -/** -// Reset this Parser so that it can parse another sequence of input. -*/ -template -void Parser::reset() -{ - accepted_ = false; - full_ = false; - nodes_.clear(); - user_data_.clear(); - nodes_.push_back( ParserNode(state_machine_->start_state, nullptr, 0, 1) ); - user_data_.push_back( UserData() ); -} - -/** -// Parse [\e start, \e finish). -// -// After the parse the Parser::full() and Parser::accepted() functions can -// be used to determine whether or not the parse was successful and whether -// or not it consumed all of the available input. -// -// In the case of a successful parse the Parser::user_data() function can -// be used to retrieve the user data that resulted from the parse. -// -// @param start -// The first character in the sequence to parse. -// -// @param finish -// One past the last character in the sequence to parse. -*/ -template -void Parser::parse( Iterator start, Iterator finish ) -{ - LALR_ASSERT( state_machine_ ); - - reset(); - lexer_.reset( start, finish ); - lexer_.advance(); - const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); - while ( parse(symbol, lexer_.lexeme(), lexer_.line(), lexer_.column()) ) - { - lexer_.advance(); - symbol = reinterpret_cast( lexer_.symbol() ); - } - - full_ = lexer_.full(); -} - -/** -// Continue a parse by accepting \e symbol as the next token. -// -// @param symbol -// The next token from the lexical analyzer in the current parse (assumed to -// be a ParserSymbol). -// -// @param lexeme -// The lexeme of the next token from the lexical analyzer. -// -// @param line -// The line number at the start of the next token. -// -// @return -// True until parsing is complete or an error occurs. -*/ -template -bool Parser::parse( const void* symbol, const std::basic_string& lexeme, int line, int column ) -{ - return parse( reinterpret_cast(symbol), lexeme, line, column ); -} - -/** -// Continue a parse by accepting \e symbol as the next token. -// -// @param symbol -// The next token from the lexical analyzer in the current parse. -// -// @param lexeme -// The lexeme of the next token from the lexical analyzer. -// -// @param line -// The line number at the start of the next token. -// -// @return -// True until parsing is complete or an error occurs. -*/ -template -bool Parser::parse( const ParserSymbol* symbol, const std::basic_string& lexeme, int line, int column ) -{ - bool accepted = false; - bool rejected = false; - - const ParserTransition* transition = find_transition( symbol, nodes_.back().state() ); - while ( !accepted && !rejected && transition && transition->reduced_symbol ) - { - reduce( transition, &accepted, &rejected ); - transition = find_transition( symbol, nodes_.back().state() ); - } - - if ( transition && transition->state ) - { - shift( transition, lexeme, line, column ); - } - else - { - error( &accepted, &rejected, line, column); - } - - accepted_ = accepted; - return !accepted_ && !rejected; -} - /** // Did the most recent parse accept input successfully? // @@ -223,6 +112,22 @@ bool Parser::full() const return full_; } +/** +// Is this Parser valid? +// +// Reports errors for and returns false if the lexer is missing any action +// handlers. +// +// @return +// True if this Parser is valid or false if there are any missing +// action handlers. +*/ +template +bool Parser::valid() const +{ + return lexer_.valid(); +} + /** // Get the user data that resulted from the most recent call to // Parser::parser() on this %Parser. @@ -413,6 +318,119 @@ void Parser::set_debug_enabled( boo debug_enabled_ = debug_enabled; } +/** +// Reset this Parser so that it can parse another sequence of input. +*/ +template +void Parser::reset() +{ + accepted_ = false; + full_ = false; + nodes_.clear(); + user_data_.clear(); + nodes_.push_back( ParserNode(state_machine_->start_state, nullptr, 0, 1) ); + user_data_.push_back( UserData() ); +} + +/** +// Parse [\e start, \e finish). +// +// After the parse the Parser::full() and Parser::accepted() functions can +// be used to determine whether or not the parse was successful and whether +// or not it consumed all of the available input. +// +// In the case of a successful parse the Parser::user_data() function can +// be used to retrieve the user data that resulted from the parse. +// +// @param start +// The first character in the sequence to parse. +// +// @param finish +// One past the last character in the sequence to parse. +*/ +template +void Parser::parse( Iterator start, Iterator finish ) +{ + LALR_ASSERT( state_machine_ ); + if ( valid() ) + { + reset(); + lexer_.reset( start, finish ); + lexer_.advance(); + const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); + while ( parse(symbol, lexer_.lexeme(), lexer_.line(), lexer_.column()) ) + { + lexer_.advance(); + symbol = reinterpret_cast( lexer_.symbol() ); + } + + full_ = lexer_.full(); + } +} + +/** +// Continue a parse by accepting \e symbol as the next token. +// +// @param symbol +// The next token from the lexical analyzer in the current parse (assumed to +// be a ParserSymbol). +// +// @param lexeme +// The lexeme of the next token from the lexical analyzer. +// +// @param line +// The line number at the start of the next token. +// +// @return +// True until parsing is complete or an error occurs. +*/ +template +bool Parser::parse( const void* symbol, const std::basic_string& lexeme, int line, int column ) +{ + return parse( reinterpret_cast(symbol), lexeme, line, column ); +} + +/** +// Continue a parse by accepting \e symbol as the next token. +// +// @param symbol +// The next token from the lexical analyzer in the current parse. +// +// @param lexeme +// The lexeme of the next token from the lexical analyzer. +// +// @param line +// The line number at the start of the next token. +// +// @return +// True until parsing is complete or an error occurs. +*/ +template +bool Parser::parse( const ParserSymbol* symbol, const std::basic_string& lexeme, int line, int column ) +{ + bool accepted = false; + bool rejected = false; + + const ParserTransition* transition = find_transition( symbol, nodes_.back().state() ); + while ( !accepted && !rejected && transition && transition->reduced_symbol ) + { + reduce( transition, &accepted, &rejected ); + transition = find_transition( symbol, nodes_.back().state() ); + } + + if ( transition && transition->state ) + { + shift( transition, lexeme, line, column ); + } + else + { + error( &accepted, &rejected, line, column); + } + + accepted_ = accepted; + return !accepted_ && !rejected; +} + /** // Find the Transition for \e symbol in \e state. //