diff --git a/CMakeLists.txt b/CMakeLists.txt index 7906821..cfd8c03 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/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/NodeTree.cpp src/Parser.cpp ) +set( MY_SOURCES main.cpp src/Parser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/NodeTree.cpp ) include_directories( ${MY_INCLUDES} ) diff --git a/include/ParseAction.h b/include/ParseAction.h new file mode 100644 index 0000000..270be4d --- /dev/null +++ b/include/ParseAction.h @@ -0,0 +1,28 @@ +#ifndef PARSE_ACTION_H +#define PARSE_ACTION_H + +#ifndef NULL +#define NULL 0 +#endif + +#include "ParseRule.h" + +#include +#include + +class ParseAction { + public: + enum ActionType { INVALID, REDUCE, SHIFT, ACCEPT, REJECT }; + ParseAction(ActionType action, ParseRule* reduceRule = NULL, int shiftState = 0); + ~ParseAction(); + std::string toString(); + static std::string actionToString(ActionType action); + + ActionType action; + ParseRule* reduceRule; + int shiftState; + + +}; + +#endif \ No newline at end of file diff --git a/include/ParseRule.h b/include/ParseRule.h index 4cc0289..9f2ab4b 100644 --- a/include/ParseRule.h +++ b/include/ParseRule.h @@ -22,6 +22,9 @@ class ParseRule { void setLeftHandle(Symbol* leftHandle); void appendToRight(Symbol* appendee); + Symbol* getLeftSide(); + std::vector getRightSide(); + bool advancePointer(); std::string toString(); diff --git a/include/Parser.h b/include/Parser.h index 21f371f..4a94b2a 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -6,11 +6,13 @@ #endif #include "ParseRule.h" +#include "ParseAction.h" #include "Symbol.h" #include "StringReader.h" #include #include +#include #include #include @@ -20,6 +22,10 @@ class Parser { ~Parser(); void loadGrammer(std::string grammerInputString); + int gotoTable(int state, Symbol* token); + ParseAction* actionTable(int state, Symbol* token); + void parseInput(std::string inputString); + std::string grammerToString(); std::string grammerToDOT(); private: @@ -27,6 +33,9 @@ class Parser { std::map symbols; std::vector loadedGrammer; + std::stack stateStack; + std::stack symbolStack; + Symbol* getOrAddSymbol(std::string symbolString, bool isTerminal); }; diff --git a/include/Symbol.h b/include/Symbol.h index 295ebf0..9a5b49d 100644 --- a/include/Symbol.h +++ b/include/Symbol.h @@ -12,6 +12,7 @@ class Symbol { public: Symbol(std::string name, bool isTerminal); ~Symbol(); + bool const operator==(const Symbol &other); std::string toString(); private: std::string name; diff --git a/src/ParseAction.cpp b/src/ParseAction.cpp new file mode 100644 index 0000000..62342d5 --- /dev/null +++ b/src/ParseAction.cpp @@ -0,0 +1,37 @@ +#include "ParseAction.h" + +ParseAction::ParseAction(ActionType action, ParseRule* reduceRule, int shiftState) { + this->action = action; + this->reduceRule = reduceRule; + this->shiftState = shiftState; +} + +ParseAction::~ParseAction() { + +} + +std::string ParseAction::actionToString(ActionType action) { + switch (action) { + case REDUCE: + return "reduce"; + break; + case SHIFT: + return "shift"; + break; + case ACCEPT: + return "accept"; + break; + case REJECT: + return "reject"; + break; + } +} + +std::string ParseAction::toString() { + std::string outputString = actionToString(action); + if (reduceRule) + outputString += " " + reduceRule->toString(); + if (shiftState) + outputString += " " + shiftState; + return(outputString); +} \ No newline at end of file diff --git a/src/ParseRule.cpp b/src/ParseRule.cpp index 14c4d40..f493cc1 100644 --- a/src/ParseRule.cpp +++ b/src/ParseRule.cpp @@ -27,6 +27,14 @@ void ParseRule::appendToRight(Symbol* appendee) { rightSide.push_back(appendee); } +Symbol* ParseRule::getLeftSide() { + return leftHandle; +} + +std::vector ParseRule::getRightSide() { + return rightSide; +} + bool ParseRule::advancePointer() { if (pointerIndex < rightSide.size()) { pointerIndex++; diff --git a/src/Parser.cpp b/src/Parser.cpp index 4722442..dbccab0 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -8,7 +8,6 @@ Parser::~Parser() { } - Symbol* Parser::getOrAddSymbol(std::string symbolString, bool isTerminal) { Symbol* symbol; if (symbols.find(symbolString) == symbols.end()) { @@ -52,6 +51,57 @@ void Parser::loadGrammer(std::string grammerInputString) { std::cout << "Parsed!\n"; } +int Parser::gotoTable(int state, Symbol* token) { + return 0; +} + +ParseAction* Parser::actionTable(int state, Symbol* token) { + return NULL; +} + +void Parser::parseInput(std::string inputString) { + StringReader inputReader; + inputReader.setString(inputString); + + Symbol* token = new Symbol(reader.word(), false); + ParseAction* action; + + stateStack.push(0); + symbolStack.push(new Symbol("INVALID", false)); + + while (true) { + action = actionTable(stateStack.top(), token); + switch (action->action) { + case ParseAction::REDUCE: + { + int rightSideLength = action->reduceRule->getRightSide().size(); + for (int i = 0; i < rightSideLength; i++) { + stateStack.pop(); + symbolStack.pop(); + } + symbolStack.push(action->reduceRule->getLeftSide()); + stateStack.push(gotoTable(stateStack.top(), symbolStack.top())); + std::cout << "Reduce by " << action->reduceRule->toString() << std::endl; + break; + } + case ParseAction::SHIFT: + symbolStack.push(token); + token = new Symbol(inputReader.word(), false); + stateStack.push(action->shiftState); + std::cout << "Shift " << symbolStack.top()->toString() << std::endl; + break; + case ParseAction::ACCEPT: + std::cout << "ACCEPTED!" << std::endl; + return; + break; + case ParseAction::REJECT: + std::cout << "REJECTED!" << std::endl; + return; + break; + } + } +} + std::string Parser::grammerToString() { //Iterate through the vector, adding string representation of each grammer rule std::cout << "About to toString\n"; diff --git a/src/Symbol.cpp b/src/Symbol.cpp index 8c8cad8..4da17da 100644 --- a/src/Symbol.cpp +++ b/src/Symbol.cpp @@ -9,6 +9,10 @@ Symbol::~Symbol() { } +const bool Symbol::operator==(const Symbol &other) { + return( name == other.name && isTerminal == other.isTerminal); +} + std::string Symbol::toString() { return(name); }