diff --git a/CMakeLists.txt b/CMakeLists.txt index 87dff70..131db54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(Kraken) set( MY_INCLUDES ${PROJECT_SOURCE_DIR}/include) -set( MY_SOURCES main.cpp src/Parser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/State.cpp src/util.cpp src/Lexer.cpp src/RegEx.cpp src/RegExState.cpp src/Table.cpp ) +set( MY_SOURCES main.cpp src/Parser.cpp src/LALRParser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/State.cpp src/util.cpp src/Lexer.cpp src/RegEx.cpp src/RegExState.cpp src/Table.cpp ) include_directories( ${MY_INCLUDES} ) diff --git a/include/LALRParser.h b/include/LALRParser.h new file mode 100644 index 0000000..ef711e7 --- /dev/null +++ b/include/LALRParser.h @@ -0,0 +1,39 @@ +#ifndef LALRPARSER_H +#define LALRPARSER_H + +#include "Parser.h" +/* +#include "util.h" +#include "ParseRule.h" +#include "ParseAction.h" +#include "Symbol.h" +#include "State.h" +#include "StringReader.h" +#include "Lexer.h" +#include "NodeTree.h" +#include "Table.h" + +#include +#include +#include +#include +#include +#include +*/ +class LALRParser: public Parser { + public: + LALRParser(); + ~LALRParser(); + + //using Parser::loadGrammer; + + //Defaults in parser are mostly LALR, so we only need to + //implement the actual parsing function + NodeTree* parseInput(std::string inputString); + + private: + //Nothing + +}; + +#endif \ No newline at end of file diff --git a/include/Parser.h b/include/Parser.h index f23f542..97f5dec 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -23,24 +23,24 @@ class Parser { Parser(); ~Parser(); - void loadGrammer(std::string grammerInputString); - std::vector* firstSet(Symbol* token); - std::vector* firstSet(Symbol* token, std::vector &avoidList); - std::vector* incrementiveFollowSet(ParseRule* rule); - void createStateSet(); - void closure(State* state); - void addStates(std::vector< State* >* stateSets, State* state); - int stateNum(State* state); - std::string stateSetToString(); - - NodeTree* parseInput(std::string inputString); - - std::string grammerToString(); - std::string grammerToDOT(); + virtual void loadGrammer(std::string grammerInputString); + virtual void createStateSet(); + virtual std::string stateSetToString(); + virtual NodeTree* parseInput(std::string inputString) = 0; + virtual std::string grammerToString(); + virtual std::string grammerToDOT(); std::string tableToString(); - private: + protected: + std::vector* firstSet(Symbol* token); + std::vector* firstSet(Symbol* token, std::vector &avoidList); + std::vector* incrementiveFollowSet(ParseRule* rule); + virtual void closure(State* state); + virtual void addStates(std::vector< State* >* stateSets, State* state); + int stateNum(State* state); + + StringReader reader; Lexer lexer; std::map symbols; diff --git a/main.cpp b/main.cpp index 2f92f76..ac97e29 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ #include "NodeTree.h" #include "Symbol.h" #include "Lexer.h" -#include "Parser.h" +#include "LALRParser.h" #include #include #include @@ -43,7 +43,7 @@ int main(int argc, char* argv[]) { programInputFileString.append(line+"\n"); } - Parser parser; + LALRParser parser; parser.loadGrammer(grammerInputFileString); //std::cout << "Creating State Set from Main" << std::endl; std::cout << "\n\n\n\n\n\n\n\n\n\nState Set" << std::endl; diff --git a/src/LALRParser.cpp b/src/LALRParser.cpp new file mode 100644 index 0000000..b682b01 --- /dev/null +++ b/src/LALRParser.cpp @@ -0,0 +1,70 @@ +#include "LALRParser.h" + +LALRParser::LALRParser() { + //Nothing to do in this version +} +LALRParser::~LALRParser() { + //Nothing to do in this version +} + +NodeTree* LALRParser::parseInput(std::string inputString) { + lexer.setInput(inputString); + Symbol* token = lexer.next(); + std::vector* actionList; + ParseAction* action; + + stateStack.push(0); + symbolStack.push(new Symbol("INVALID", false)); + + while (true) { + std::cout << "In state: " << intToString(stateStack.top()) << std::endl; + actionList = table.get(stateStack.top(), token); + action = (*(actionList))[actionList->size()-1]; + //std::cout << "Doing ParseAction: " << action->toString() << std::endl; + switch (action->action) { + case ParseAction::REDUCE: + { + std::cout << "Reduce by " << action->reduceRule->toString() << std::endl; + + int rightSideLength = action->reduceRule->getRightSide().size(); + //Keep track of symbols popped for parse tree + std::vector poppedSymbols; + for (int i = 0; i < rightSideLength; i++) { + poppedSymbols.push_back(symbolStack.top()); + stateStack.pop(); + symbolStack.pop(); + } + std::reverse(poppedSymbols.begin(), poppedSymbols.end()); //To put in order + //Assign the new tree to the new Symbol + Symbol* newSymbol = action->reduceRule->getLeftSide()->clone(); + newSymbol->setSubTree(reduceTreeCombine(newSymbol, poppedSymbols)); + symbolStack.push(newSymbol); + std::cout << "top of state is " << intToString(stateStack.top()) << " symbolStack top is " << symbolStack.top()->toString() << std::endl; + + actionList = table.get(stateStack.top(), symbolStack.top()); + action = (*(actionList))[actionList->size()-1]; + + stateStack.push(action->shiftState); + //std::cout << "Reduced, now condition is" << std::endl; + //std::cout << "top of state is " << intToString(stateStack.top()) << " symbolStack top is " << symbolStack.top()->toString() << std::endl; + break; + } + case ParseAction::SHIFT: + std::cout << "Shift " << token->toString() << std::endl; + + symbolStack.push(token); + token = lexer.next(); + stateStack.push(action->shiftState); + break; + case ParseAction::ACCEPT: + std::cout << "ACCEPTED!" << std::endl; + return(symbolStack.top()->getSubTree()); + break; + case ParseAction::REJECT: + std::cout << "REJECTED!" << std::endl; + std::cout << "REJECTED Symbol was " << token->toString() << std::endl; + return(NULL); + break; + } + } +} \ No newline at end of file diff --git a/src/Parser.cpp b/src/Parser.cpp index d30d44a..048d666 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -310,67 +310,7 @@ std::string Parser::tableToString() { return table.toString(); } -NodeTree* Parser::parseInput(std::string inputString) { - lexer.setInput(inputString); - Symbol* token = lexer.next(); - std::vector* actionList; - ParseAction* action; - - stateStack.push(0); - symbolStack.push(new Symbol("INVALID", false)); - - while (true) { - std::cout << "In state: " << intToString(stateStack.top()) << std::endl; - actionList = table.get(stateStack.top(), token); - action = (*(actionList))[actionList->size()-1]; - //std::cout << "Doing ParseAction: " << action->toString() << std::endl; - switch (action->action) { - case ParseAction::REDUCE: - { - std::cout << "Reduce by " << action->reduceRule->toString() << std::endl; - - int rightSideLength = action->reduceRule->getRightSide().size(); - //Keep track of symbols popped for parse tree - std::vector poppedSymbols; - for (int i = 0; i < rightSideLength; i++) { - poppedSymbols.push_back(symbolStack.top()); - stateStack.pop(); - symbolStack.pop(); - } - std::reverse(poppedSymbols.begin(), poppedSymbols.end()); //To put in order - //Assign the new tree to the new Symbol - Symbol* newSymbol = action->reduceRule->getLeftSide()->clone(); - newSymbol->setSubTree(reduceTreeCombine(newSymbol, poppedSymbols)); - symbolStack.push(newSymbol); - std::cout << "top of state is " << intToString(stateStack.top()) << " symbolStack top is " << symbolStack.top()->toString() << std::endl; - - actionList = table.get(stateStack.top(), symbolStack.top()); - action = (*(actionList))[actionList->size()-1]; - - stateStack.push(action->shiftState); - //std::cout << "Reduced, now condition is" << std::endl; - //std::cout << "top of state is " << intToString(stateStack.top()) << " symbolStack top is " << symbolStack.top()->toString() << std::endl; - break; - } - case ParseAction::SHIFT: - std::cout << "Shift " << token->toString() << std::endl; - - symbolStack.push(token); - token = lexer.next(); - stateStack.push(action->shiftState); - break; - case ParseAction::ACCEPT: - std::cout << "ACCEPTED!" << std::endl; - return(symbolStack.top()->getSubTree()); - break; - case ParseAction::REJECT: - std::cout << "REJECTED!" << std::endl; - std::cout << "REJECTED Symbol was " << token->toString() << std::endl; - return(NULL); - break; - } - } -} +//parseInput is now pure virtual NodeTree* Parser::reduceTreeCombine(Symbol* newSymbol, std::vector &symbols) { NodeTree* newTree = new NodeTree(newSymbol->getName(), newSymbol);