#ifndef BU_PARSER_H #define BU_PARSER_H #include "bu/string.h" #include "bu/list.h" #include "bu/array.h" #include "bu/hash.h" #include "bu/signals.h" #include "bu/lexer.h" namespace Bu { /** * The base framework for a LR(1) grammar parser. Provided a proper set of * ParserStates this will prase any input the lexer can provide. */ class Parser { public: Parser(); virtual ~Parser(); /** * When a Lexer is pushed onto the stack it becomes the source for * future tokens read by the parser until it is popped off the stack. * The Parser takes ownership of every Lexer pushed onto the stack, * and will delete it when it is popped off the stack. */ void pushLexer( Lexer *pLex ); /** * Pop a lexer off the stack, and delete it. */ void popLexer(); Lexer::Token *popToken(); void pushToken( Lexer::Token *pTok ); /** * Execute a parse. */ void parse(); void setRootNonTerminal( int iRoot ); void setRootNonTerminal( const Bu::String &sRoot ); typedef Bu::Signal1 Reduction; /** * Represents a possible state, either a terminal or non-terminal symbol * in a Production. */ class State { public: enum Type { typeTerminal, typeTerminalPush, typeNonTerminal, typeReduction }; State( Type eType, int iIndex ); virtual ~State(); //private: Type eType; int iIndex; }; typedef Bu::List Production; class NonTerminal { public: NonTerminal(); virtual ~NonTerminal(); void addProduction( Production p ); void setCanSkip(); // private: typedef Bu::List ProductionList; ProductionList lProduction; bool bCanSkip; }; int addNonTerminal( const Bu::String &sName, NonTerminal &nt ); int addNonTerminal( const Bu::String &sName ); void setNonTerminal( const Bu::String &sName, NonTerminal &nt ); int getNonTerminalId( const Bu::String &sName ); bool hasNonTerminal( const Bu::String &sName ); int addReduction( const Bu::String &sName, const Reduction &r ); int addReduction( const Bu::String &sName ); void setReduction( const Bu::String &sName, const Reduction &r ); int getReductionId( const Bu::String &sName ); bool hasReduction( const Bu::String &sName ); private: bool selectProduction( int iNt, Lexer::Token *ptCur ); void advanceState(); private: typedef Bu::List LexerStack; typedef Bu::List TokenStack; typedef Bu::List StateStack; typedef Bu::Array ReductionArray; typedef Bu::Hash NameIndexHash; typedef Bu::Array NonTerminalArray; LexerStack sLexer; TokenStack sToken; StateStack sState; ReductionArray aReduction; NameIndexHash hReductionName; NonTerminalArray aNonTerminal; NameIndexHash hNonTerminalName; int iRootNonTerminal; }; Bu::Formatter &operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ); Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::Parser::State &s ); }; #endif