#include "LR1.h" #include <iostream> #include <utility> #include <sstream> #include <fstream> using std::string; using std::pair; LR1Node::LR1Node(string s): s(s) {} LR1Node::~LR1Node() { for (auto child : children) { delete child; } } void LR1Node::addchild(LR1Node *child) { children.push_back(child); } void LR1Node::addToVector(std::vector<string> &v) { v.push_back(s); for (auto child : children) { child->addToVector(v); } } LR1::LR1() { stateStack.push_back(0); } LR1::~LR1() { for (auto node : TreeStack) { delete node; } } ParsingFailure::ParsingFailure(int prefix): prefix(prefix) {} const string ParsingFailure::what() const { return std::to_string(prefix + 1); } void LR1::initialize() { parseFile.open("parse.txt"); int numTerm, numNonTerm, numRules, numShiftReduce; string line; // read the number of terminals and move to the next line parseFile >> numTerm; term(numTerm); // read the number of non-terminals and move to the next line parseFile >> numNonTerm; nonTerm(numNonTerm); // read start symbol startSym(); // read the number of rules and move to the next line parseFile >> numRules; std::getline(parseFile, line); // clear line addRules(numRules); // read number of states statesNum(); // read shift reduce rules parseFile >> numShiftReduce; std::getline(parseFile, line); // clear line shiftReduceRules(numShiftReduce); parseFile.close(); } void LR1::term(int in) { string t; for (int i = 0; i < in; i++) { parseFile >> t; symbols.push_back(t); terminals.push_back(t); } } void LR1::nonTerm(int in) { string t; for (int i = 0; i < in; i++) { parseFile >> t; symbols.push_back(t); nonTerminals.push_back(t); } } void LR1::startSym() { parseFile >> start; } void LR1::addRules(int in) { string r; for (int i = 0; i < in; i++) { std::getline(parseFile, r); rules.push_back(r); } } void LR1::statesNum() { int n; parseFile >> n; states = n; reduceRules.resize(states); shiftRules.resize(states); } void LR1::shiftReduceRules(int in) { string r; for (int i = 0; i < in; i++) { std::getline(parseFile, r); std::istringstream iss (r); int initialState, nextState; string terminal, action; iss >> initialState; iss >> terminal; iss >> action; iss >> nextState; pair<int, string> lookahead = std::make_pair(initialState, terminal); pair<pair<int, string>, int> rule = std::make_pair(lookahead, nextState); if (action == "reduce") { reduceRules[initialState].push_back(rule); } else if (action == "shift") { shiftRules[initialState].push_back(rule); } } } int LR1::shift(string in) { int state = stateStack.back(); pair<int, string> top = std::make_pair(state, in); for (auto rule : shiftRules[state]) { if (rule.first == top) { return rule.second; } } return states + 1; } bool LR1::parseUtil(string in) { while (true) { // check reduce rules for in int state = stateStack.back(); pair<int, string> top = std::make_pair(state, in); bool reduced = false; for (auto rule : reduceRules[state]) { if (rule.first == top) { string reduceRule = rules[rule.second]; int nRight = 0; for (auto c : reduceRule) { if (c == ' ') { nRight++; } } LR1Node *reduce = new LR1Node(reduceRule); std::istringstream iss (reduceRule); string leftHand, rightHand; iss >> leftHand; for (int i = nRight; i > 0; i--) { iss >> rightHand; string sym = symStack[symStack.size() - i]; if (sym != rightHand) { delete reduce; return false; } symStack.erase(symStack.begin() + (symStack.size() - i)); reduce->addchild(TreeStack[TreeStack.size() - i]); TreeStack.erase(TreeStack.begin() + (TreeStack.size() - i)); stateStack.pop_back(); } symStack.push_back(leftHand); int shifted = shift(leftHand); if (shifted > states) { delete reduce; return false; } TreeStack.push_back(reduce); stateStack.push_back(shifted); reduced = true; break; } } if (!reduced) { break; } } symStack.push_back(in); int shifted = shift(in); if (shifted > states) { return false; } stateStack.push_back(shifted); return true; } void LR1::parse(std::vector<string> &tokens) { string in; int i = 0; parseUtil("BOF"); LR1Node *bof = new LR1Node("BOF BOF"); TreeStack.push_back(bof); while (tokens.size() != 0) { in = tokens.front(); tokens.erase(tokens.begin()); std::istringstream iss (in); string token; iss >> token; bool check = parseUtil(token); if (!check) { throw ParsingFailure(i); } LR1Node *terminal = new LR1Node(in); TreeStack.push_back(terminal); i++; } parseUtil("EOF"); LR1Node *eof = new LR1Node("EOF EOF"); TreeStack.push_back(eof); std::istringstream rule (rules[0]); string rightHand; rule >> rightHand; LR1Node *s = new LR1Node(rules[0]); for (int n = 3; n > 0; n--) { rule >> rightHand; string sym = symStack[symStack.size() - n]; if (sym != rightHand) { delete s; throw ParsingFailure(i); } s->addchild(TreeStack[TreeStack.size() - n]); TreeStack.erase(TreeStack.begin() + (TreeStack.size() - n)); } TreeStack.push_back(s); } std::vector<string> LR1::generate() { std::vector<string> nodeVector; for (auto s : TreeStack) { s->addToVector(nodeVector); } return nodeVector; }