#include "tree.h" AnalysisError::AnalysisError(string type): type(type) {} const string AnalysisError::what() const { return type; } Node::Node(string rule, Tree *t): rule(rule), isTerminal(false), t(t) { std::istringstream iss(rule); string sym; // Left Hand Side iss >> sym; symbol = sym; if ('A' <= symbol[0] && symbol[0] <= 'Z') { isTerminal = true; } // Right Hand Side if (isTerminal) { iss >> sym; value = sym; } else { while (iss >> sym) { string line = t->getNextToken(); Node *child = new Node(line, t); children.push_back(child); } } } Node::~Node() { for (auto &child : children) { delete child; } } void Node::print() { if (isTerminal) { std::cout << symbol << ' ' << value << std::endl; } else { std::cout << symbol << std::endl; } for (auto &child : children) { child->print(); } } void Node::traverse() { if (symbol == "procedure") { if (t->tables.find(children[1]->value) != t->tables.end()) { throw AnalysisError("AnalysisError: Multiple Procedure Declaration"); } t->currentProcedure = children[1]->value; // ID // Check Variable Declaration children[3]->checkParam(); // params children[6]->checkVar(); // dcls // add table to tables t->tables[t->currentProcedure] = std::make_pair(t->params, t->table); t->params.clear(); t->table.clear(); t->varOffsets[t->currentProcedure] = std::make_pair(t->varOffset, t->varCount); t->varOffset.clear(); t->varCount = 0; // Traverse statements, expr children[7]->traverse(); // statements children[9]->traverse(); // expr } else if (symbol == "main") { if (t->tables.find(children[1]->value) != t->tables.end()) { throw AnalysisError("AnalysisError: Multiple Procedure Declaration"); } t->currentProcedure = children[1]->value; // WAIN t->varOffset.clear(); t->varCount = 0; // Check dcl1 Node *dcl = children[3]; string dclType = dcl->children[0]->getType(); string dclId = dcl->children[1]->value; t->table[dclId] = dclType; t->params.push_back(dclType); t->varOffset[dclId] = t->varCount; t->varCount++; // Check dcl2 dcl = children[5]; dclType = dcl->children[0]->getType(); dclId = dcl->children[1]->value; if (dclType == "int*") { throw AnalysisError("AnalysisError: Invalid Type: int*"); } else if (t->table.find(dclId) != t->table.end()) { throw AnalysisError("AnalysisError: Multiple Variable Declaration"); } t->table[dclId] = dclType; t->params.push_back(dclType); t->varOffset[dclId] = t->varCount; t->varCount++; // Check dcls children[8]->checkVar(); // dcls // add table to tables t->tables[t->currentProcedure] = std::make_pair(t->params, t->table); t->params.clear(); t->table.clear(); t->varOffsets[t->currentProcedure] = std::make_pair(t->varOffset, t->varCount); t->varOffset.clear(); t->varCount = 0; // Traverse statements, expr children[9]->traverse(); // statements children[11]->traverse(); // expr } else if (symbol == "statements") { if (children.size() == 0) { // statements return; } else if (children[0]->symbol == "statements") { // statements statements statement children[0]->traverse(); // statements children[1]->traverse(); // statement } } else if (symbol == "statement") { if (children[0]->symbol == "lvalue") { // statement lvalue BECOMES expr SEMI string type1 = children[0]->getType(); // lvalue string type2 = children[2]->getType(); // expr if (type1 != type2) { throw AnalysisError("AnalysisError: Incompatible type in BECOMES"); } } else if (children[0]->symbol == "IF" || children[0]->symbol == "WHILE") { // statement IF/WHILE for (auto child : children) { if (!child->isTerminal) { child->traverse(); // test, statements } } } else if (children[0]->symbol == "PRINTLN") { // statement PRINTLN string type1 = children[2]->getType(); // expr if (type1 != "int") { throw AnalysisError("AnalysisError: Incorrect type in PRINTLN"); } } else if (children[0]->symbol == "DELETE") { // statement DELETE string type1 = children[3]->getType(); // expr if (type1 != "int*") { throw AnalysisError("AnalysisError: Incorrect type in DELETE"); } } } else if (symbol == "test") { // test expr TERM expr string type1 = children[0]->getType(); // left expr string type2 = children[2]->getType(); // right expr if (type1 != type2) { throw AnalysisError("AnalysisError: Incompatible type in test"); } } else if (symbol == "expr") { // expr @ RETURN string type1 = this->getType(); if (type1 != "int") { throw AnalysisError("AnalysisError: Incorrect RETURN type"); } } else { for (auto child : children) { if (!child->isTerminal) { child->traverse(); } } } } void Node::checkParam() { if (symbol == "dcl") { string type = children[0]->getType(); string id = children[1]->value; if (t->table.find(id) != t->table.end()) { throw AnalysisError("AnalysisError: Multiple Declaration"); } t->table[id] = type; t->params.push_back(type); // t->varOffset[id] = t->varCount; // add paramlist var to varOffset } else { for (auto child : children) { if (!child->isTerminal) { child->checkParam(); } } } } void Node::checkVar() { if (symbol == "dcls" && children.size() == 0) { return; } else if (symbol == "dcls" && children[3]->symbol == "NUM") { children[0]->checkVar(); string type = children[1]->children[0]->getType(); // dcl->type->getType if (type != "int") { throw AnalysisError("AnalysisError: Incorrect Variable Type Declaration"); } string id = children[1]->children[1]->value; // dcl->id if (t->table.find(id) != t->table.end()) { throw AnalysisError("AnalysisError: Multiple Declaration"); } t->table[id] = type; t->varOffset[id] = t->varCount; t->varCount++; } else if (symbol == "dcls" && children[3]->symbol == "NULL") { children[0]->checkVar(); string type = children[1]->children[0]->getType(); // dcl->type->getType if (type != "int*") { throw AnalysisError("AnalysisError: Incorrect Variable Type Declaration"); } string id = children[1]->children[1]->value; // dcl->id if (t->table.find(id) != t->table.end()) { throw AnalysisError("AnalysisError: Multiple Declaration"); } t->table[id] = type; t->varOffset[id] = t->varCount; t->varCount++; } else { for (auto child : children) { if (!child->isTerminal) { child->checkVar(); } } } } void checkArgs(Node *n, vector<string> &v) { if (n->symbol == "expr") { string t = n->getType(); v.push_back(t); } else { for (auto child : n->children) { if (!child->isTerminal) { checkArgs(child, v); } } } } string Node::getType() { if (symbol == "type") { // type INT, type INT STAR string type = ""; for (auto child : children) { type += child->value; } return type; } else if (symbol == "expr") { if (children.size() == 1) { // expr term return children[0]->getType(); // term } else if (children[1]->symbol == "PLUS") { // expr expr PLUS term string type1 = children[0]->getType(); // expr string type2 = children[2]->getType(); // term if (type1 == "int" && type2 == "int") { return "int"; } else if (type1 == "int" && type2 == "int*") { return "int*"; } else if (type1 == "int*" && type2 == "int") { return "int*"; } else { throw AnalysisError("AnalysisError: Incorrect Type: int* PLUS int*"); } } else if (children[1]->symbol == "MINUS") { // expr expr MINUS term string type1 = children[0]->getType(); // expr string type2 = children[2]->getType(); // term if (type1 == "int" && type2 == "int") { return "int"; } else if (type1 == "int*" && type2 == "int") { return "int*"; } else if (type1 == "int*" && type2 == "int*") { return "int"; } else { throw AnalysisError("AnalysisError: Incorrect Type: int* MINUS int*"); } } } else if (symbol == "term") { if (children.size() == 1) { // term factor return children[0]->getType(); // factor } else { // term term STAR/SLASH/PCT factor string type1 = children[0]->getType(); // term string type2 = children[2]->getType(); // factor if (type1 == "int" && type2 == "int") { return "int"; } else { throw AnalysisError("AnalysisError: Incorrect Type: int* at term"); } } } else if (symbol == "factor") { if (children[0]->symbol == "ID") { if (children.size() == 1) { // factor ID map<string, string> variables = t->tables[t->currentProcedure].second; if (variables.find(children[0]->value) == variables.end()) { throw AnalysisError("AnalysisError: Procedure used without Declaration"); } return variables[children[0]->value]; } else if (children.size() == 3) { // factor ID LPAREN RPAREN if (t->tables.find(children[0]->value) == t->tables.end()) { throw AnalysisError("AnalysisError: Procedure used without Declaration"); } else if (children[0]->value == "wain") { throw AnalysisError("AnalysisError: Invalid call of WAIN"); } vector<string> paramlist = t->tables[children[0]->value].first; if (paramlist.size() == 0) { return "int"; } else { throw AnalysisError("AnalysisError: Incorrect Procedure Arguments"); } } else if (children.size() == 4) { // factor ID LPAREN arglist RPAREN if (t->tables.find(children[0]->value) == t->tables.end()) { throw AnalysisError("AnalysisError: Procedure used without Declaration"); } else if (children[0]->value == "wain") { throw AnalysisError("AnalysisError: Invalid call of WAIN"); } vector<string> paramlist = t->tables[children[0]->value].first; vector<string> argslist; checkArgs(children[2], argslist); if (paramlist.size() == argslist.size() && std::equal(paramlist.begin(), paramlist.end(), argslist.begin())) { return "int"; } else { throw AnalysisError("AnalysisError: Incorrect Procedure Arguments"); } } } else if (children[0]->symbol == "NUM") { // factor NUM return "int"; } else if (children[0]->symbol == "NULL") { // factor NULL return "int*"; } else if (children[0]->symbol == "LPAREN") { // factor LPAREN expr RPAREN return children[1]->getType(); // expr } else if (children[0]->symbol == "AMP") { // factor AMP lvalue string type1 = children[1]->getType(); // lvalue if (type1 == "int") { return "int*"; } else { throw AnalysisError("AnalysisError: Incorrect Type: AMP int*"); } } else if (children[0]->symbol == "STAR") { // factor STAR factor string type1 = children[1]->getType(); // factor if (type1 == "int*") { return "int"; } else { throw AnalysisError("AnalysisError: Incorrect Type: STAR int"); } } else if (children[0]->symbol == "NEW") { // factor NEW INT LBRACK expr RBRACK string type1 = children[3]->getType(); // expr if (type1 == "int") { return "int*"; } else { throw AnalysisError("AnalysisError: Incorrect Type: NEW INT LBRACK int* RBRACK"); } } } else if (symbol == "lvalue") { if (children[0]->symbol == "ID") { // lvalue ID map<string, string> variables = t->tables[t->currentProcedure].second; if (variables.find(children[0]->value) == variables.end()) { throw AnalysisError("Procedure used without Declaration"); } return variables[children[0]->value]; } else if (children[0]->symbol == "STAR") { // lvalue STAR factor string type1 = children[1]->getType(); // factor if (type1 == "int*") { return "int"; } else { throw AnalysisError("Incorrect Type: STAR int"); } } else if (children[0]->symbol == "LPAREN") { // lvalue LPAREN lvalue RPAREN return children[1]->getType(); // lvalue } } return ""; } void pushReg(int n) { std::cout << "sw $" << n << ", -4($30) \t ; push $" << n << std::endl; std::cout << "sub $30, $30, $4" << std::endl; } void popReg(int n) { std::cout << "add $30, $30, $4" << std::endl; std::cout << "lw $" << n << ", -4($30) \t ; pop $" << n << std::endl; } void Node::generate() { if (symbol == "procedures") { if (children.size() == 1) { // procedures: main children[0]->generate(); } else { // procedures: procedure procedures children[1]->generate(); children[0]->generate(); } } else if (symbol == "procedure") { t->currentProcedure = children[1]->value; // ID t->argCount = 0; std::cout << std::endl << "F" << children[1]->value << ":" << std::endl; std::cout << "sub $29, $30, $4" << std::endl; // caller-saves old frame pointer children[3]->generate(); // params children[6]->generate(); // dcls children[7]->generate(); // statements children[9]->generate(); // expr int count = t->varOffsets[t->currentProcedure].second - t->argCount; for (int i = 0; i < count; i++) { std::cout << "add $30, $30, $4" << std::endl; // pop saved registers } std::cout << "add $30, $29, $4" << std::endl; std::cout << "jr $31" << std::endl; } else if (symbol == "main") { t->currentProcedure = children[1]->value; // WAIN t->argCount = 0; std::cout << "; begin prologue" << std::endl; std::cout << ".import print" << std::endl; std::cout << ".import init" << std::endl; std::cout << ".import new" << std::endl; std::cout << ".import delete" << std::endl; std::cout << "lis $4" << std::endl; std::cout << ".word 4" << std::endl; std::cout << "lis $10" << std::endl; std::cout << ".word print" << std::endl; std::cout << "lis $11" << std::endl; std::cout << ".word 1" << std::endl; std::cout << "sub $29, $30, $4 \t ; setup frame pointer" << std::endl; // dcl1 Node *dcl = children[3]; string dclId = dcl->children[1]->value; std::cout << "sw $1, 0($29) \t ; push variable " << dclId << std::endl; std::cout << "sub $30, $30, $4 \t ; update stack pointer" << std::endl; // dcl2 dcl = children[5]; dclId = dcl->children[1]->value; std::cout << "sw $2, -4($29) \t ; push variable " << dclId << std::endl; std::cout << "sub $30, $30, $4 \t ; update stack pointer" << std::endl; if (children[3]->children[0]->getType() == "int") { std::cout << "add $2, $0, $0 \t ; set $2 to 0" << std::endl; } // dcls children[8]->generate(); // dcls // init std::cout << "lis $5" << std::endl; std::cout << ".word init" << std::endl; pushReg(31); std::cout << "jalr $5" << std::endl; popReg(31); std::cout << "; end prologue" << std::endl << std::endl; // statements, expr children[9]->generate(); // statements children[11]->generate(); // expr std::cout << std::endl << "; begin epilogue" << std::endl; int count = t->varOffsets[t->currentProcedure].second; for (int i = 0; i < count; i++) { std::cout << "add $30, $30, $4" << std::endl; } std::cout << "jr $31" << std::endl; } else if (symbol == "params") { if (children.size() == 0) { // params: } else { // params: paramlist children[0]->generate(); } } else if (symbol == "paramlist") { // paramlist: dcl int argsCount = t->tables[t->currentProcedure].first.size(); int offset = argsCount - t->argCount; string id = children[0]->children[1]->value; // dcl -> id t->varOffsets[t->currentProcedure].first[id] = offset * (-1); // Update param offset t->argCount++; if (children.size() == 3) { // paramlist: dcl COMMA paramlist children[2]->generate(); } } else if (symbol == "arglist") { if (children.size() == 1) { // arglist: expr children[0]->generate(); // expr pushReg(3); } else { // arglist: expr COMMA arglist children[0]->generate(); // expr pushReg(3); children[2]->generate(); // arglist } } else if (symbol == "statements") { if (children.size() == 0) { // statements: } else if (children[0]->symbol == "statements") { // statements: statements statement children[0]->generate(); children[1]->generate(); } } else if (symbol == "statement") { if (children[0]->symbol == "lvalue") { // statement: lvalue BECOMES expr SEMI children[2]->generate(); children[0]->generate(); } else if (children[0]->symbol == "IF") { // statement: IF LPAREN test RPAREN LBRACE statements RBRACE ELSE LBRACE statements RBRACE int n = t->loopCount; t->loopCount++; children[2]->generate(); // test std::cout << "beq $3, $0, else" << n << std::endl; children[5]->generate(); // statements1 std::cout << "beq $0, $0, endif" << n << std::endl; std::cout << "else" << n << ":" << std::endl; children[9]->generate(); // statements2 std::cout << "endif" << n << ":" << std::endl; } else if (children[0]->symbol == "WHILE") { // statement: WHILE LPAREN test RPAREN LBRACE statements RBRACE int n = t->loopCount; t->loopCount++; std::cout << "startWhile" << n << ":" << std::endl; children[2]->generate(); // test std::cout << "beq $3, $0, endWhile" << n << std::endl; children[5]->generate(); // statements std::cout << "beq $0, $0, startWhile" << n << std::endl; std::cout << "endWhile" << n << ":" << std::endl; } else if (children[0]->symbol == "PRINTLN") { // statement: PRINTLN LPAREN expr RPAREN SEMI pushReg(1); children[2]->generate(); std::cout << "add $1, $3, $0" << std::endl; pushReg(31); std::cout << "jalr $10" << std::endl; popReg(31); popReg(1); } else if (children[0]->symbol == "DELETE") { // statement: DELETE LBRACK RBRACK expr SEMI children[3]->generate(); int n = t->loopCount; t->loopCount++; std::cout << "beq $3, $11, skipDelete" << n << std::endl; std::cout << "add $1, $3, $0 \t ; move $3 to $1" << std::endl; pushReg(31); std::cout << "lis $5" << std::endl; std::cout << ".word delete" << std::endl; std::cout << "jalr $5" << std::endl; popReg(31); std::cout << "skipDelete" << n << ":" << std::endl; } } else if (symbol == "test") { bool pointerCheck = (children[0]->getType() == "int*"); if (children[1]->symbol == "LT") { // test: expr LT expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $3, $5, $3" << std::endl; } else { std::cout << "slt $3, $5, $3" << std::endl; } } else if (children[1]->symbol == "GE") { // test: expr GE expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $3, $5, $3" << std::endl; } else { std::cout << "slt $3, $5, $3" << std::endl; } std::cout << "sub $3, $11, $3" << std::endl; } else if (children[1]->symbol == "GT") { // test: expr GT expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $3, $3, $5" << std::endl; } else { std::cout << "slt $3, $3, $5" << std::endl; } } else if (children[1]->symbol == "LE") { // test: expr GT expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $3, $3, $5" << std::endl; } else { std::cout << "slt $3, $3, $5" << std::endl; } std::cout << "sub $3, $11, $3" << std::endl; } else if (children[1]->symbol == "NE") { // test: expr NE expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $6, $3, $5" << std::endl; std::cout << "sltu $7, $5, $3" << std::endl; } else { std::cout << "slt $6, $3, $5" << std::endl; std::cout << "slt $7, $5, $3" << std::endl; } std::cout << "add $3, $6, $7" << std::endl; } else if (children[1]->symbol == "EQ") { // test: expr EQ expr children[0]->generate(); pushReg(3); children[2]->generate(); popReg(5); if (pointerCheck) { std::cout << "sltu $6, $3, $5" << std::endl; std::cout << "sltu $7, $5, $3" << std::endl; } else { std::cout << "slt $6, $3, $5" << std::endl; std::cout << "slt $7, $5, $3" << std::endl; } std::cout << "add $3, $6, $7" << std::endl; std::cout << "sub $3, $11, $3" << std::endl; } } else if (symbol == "expr") { if (children.size() == 1) { // expr: term children[0]->generate(); // term } else if (children[1]->symbol == "PLUS") { // expr: expr PLUS term children[0]->generate(); // expr if (children[2]->getType() == "int*") { std::cout << "mult $3, $4" << std::endl; std::cout << "mflo $3" << std::endl; } pushReg(3); children[2]->generate(); // term if (children[0]->getType() == "int*") { std::cout << "mult $3, $4" << std::endl; std::cout << "mflo $3" << std::endl; } popReg(5); std::cout << "add $3, $5, $3 \t ; expr PLUS term" << std::endl; } else if (children[1]->symbol == "MINUS") { // expr: expr MINUS term children[0]->generate(); // expr pushReg(3); children[2]->generate(); // term if (children[0]->getType() == "int*" && children[2]->getType() == "int") { std::cout << "mult $3, $4" << std::endl; std::cout << "mflo $3" << std::endl; } popReg(5); std::cout << "sub $3, $5, $3 \t ; expr MINUS term" << std::endl; if (children[0]->getType() == "int*" && children[2]->getType() == "int*") { std::cout << "div $3, $4" << std::endl; std::cout << "mflo $3" << std::endl; } } } else if (symbol == "term") { if (children.size() == 1) { // term: factor return children[0]->generate(); // factor } else { children[0]->generate(); // term pushReg(3); children[2]->generate(); // factor popReg(5); if (children[1]->symbol == "STAR") { // term: term STAR factor std::cout << "mult $5, $3" << std::endl; std::cout << "mflo $3" << std::endl; } else if (children[1]->symbol == "SLASH") { // term: term SLASH factor std::cout << "div $5, $3" << std::endl; std::cout << "mflo $3" << std::endl; } else if (children[1]->symbol == "PCT") { // term: term PCT factor std::cout << "div $5, $3" << std::endl; std::cout << "mfhi $3" << std::endl; } } } else if (symbol == "dcls") { if (children.size() == 0) { // dcls: return; } else if (children[3]->symbol == "NUM") { // dcls: dcls dcl BECOMES NUM SEMI children[0]->generate(); string id = children[1]->children[1]->value; // dcl->id int offset = (t->varOffsets[t->currentProcedure].first)[id]; std::cout << "lis $3" << std::endl; std::cout << ".word " << children[3]->value << std::endl; std::cout << "sw $3, " << offset * (-4) << "($29) \t ; push variable " << id << std::endl; std::cout << "sub $30, $30, $4 \t ; update stack pointer" << std::endl; } else if (children[3]->symbol == "NULL") { // dcls: dcls dcl BECOMES NULL SEMI children[0]->generate(); string id = children[1]->children[1]->value; // dcl->id int offset = (t->varOffsets[t->currentProcedure].first)[id]; std::cout << "sw $11, " << offset * (-4) << "($29) \t ; push variable " << id << std::endl; std::cout << "sub $30, $30, $4 \t ; update stack pointer" << std::endl; } } else if (symbol == "factor") { if (children[0]->symbol == "ID") { if (children.size() == 1) { // factor: ID int offset = (t->varOffsets[t->currentProcedure].first)[children[0]->value]; std::cout << "lw $3, " << offset * (-4) << "($29) \t ; variable " << children[0]->value << std::endl; } else if (children.size() == 3) { // factor: ID LPAREN RPAREN pushReg(29); pushReg(31); std::cout << "lis $5" << std::endl; std::cout << ".word F" << children[0]->value << std::endl; std::cout << "jalr $5" << std::endl; popReg(31); popReg(29); } else if (children.size() == 4) { // factor: ID LPAREN arglist RPAREN pushReg(29); pushReg(31); children[2]->generate(); std::cout << "lis $5" << std::endl; std::cout << ".word F" << children[0]->value << std::endl; std::cout << "jalr $5" << std::endl; int count = t->tables[children[0]->value].first.size(); for (int i = 0; i < count; i++) { std::cout << "add $30, $30, $4" << std::endl; } popReg(31); popReg(29); } } else if (children[0]->symbol == "NUM") { // factor: NUM std::cout << "lis $3" << std::endl; std::cout << ".word " << children[0]->value << std::endl; } else if (children[0]->symbol == "NULL") { // factor: NULL std::cout << "add $3, $0, $11" << std::endl; } else if (children[0]->symbol == "LPAREN") { // factor: LPAREN expr RPAREN children[1]->generate(); // expr } else if (children[0]->symbol == "AMP") { // factor: AMP lvalue Node *n = children[1]; // n = lvalue while (n->children.size() == 3) { n = n->children[1]; } if (n->children.size() == 1) { int offset = (t->varOffsets[t->currentProcedure].first)[n->children[0]->value]; std::cout << "lis $3" << std::endl; std::cout << ".word " << offset * (-4) << std::endl; std::cout << "add $3, $3, $29" << std::endl; } else if (n->children.size() == 2) { n->children[1]->generate(); } } else if (children[0]->symbol == "STAR") { // factor: STAR factor children[1]->generate(); // lvalue std::cout << "lw $3, 0($3)" << std::endl; } else if (children[0]->symbol == "NEW") { // factor: NEW INT LBRACK expr RBRACK children[3]->generate(); // expr std::cout << "add $1, $3, $0" << std::endl; pushReg(31); std::cout << "lis $5" << std::endl; std::cout << ".word new" << std::endl; std::cout << "jalr $5 \t ; call new" << std::endl; popReg(31); std::cout << "bne $3, $0, 1 \t ; check if call succeeded" << std::endl; std::cout << "add $3, $11, $0" << std::endl; } } else if (symbol == "lvalue") { if (children[0]->symbol == "ID") { // lvalue: ID int offset = (t->varOffsets[t->currentProcedure].first)[children[0]->value]; std::cout << "sw $3, " << offset * (-4) << "($29) \t ; variable" << children[0]->value << std::endl; } else if (children[0]->symbol == "STAR") { // lvalue: STAR factor pushReg(3); children[1]->generate(); popReg(5); std::cout << "sw $5, 0($3)" << std::endl; } else if (children[0]->symbol == "LPAREN") { // lvalue: LPAREN lvalue RPAREN children[1]->generate(); } } else { for (auto child : children) { if (!child->isTerminal) { child->generate(); } } } } Tree::Tree(vector<string> &parsedTokens): parsedTokens(parsedTokens) { varCount = 0; argCount = 0; loopCount = 0; string currentProcedure; string line = getNextToken(); root = new Node(line, this); } Tree::~Tree() { delete root; } void Tree::print() { root->print(); } void Tree::traverse() { root->traverse(); } string Tree::getNextToken() { string token = parsedTokens.back(); parsedTokens.pop_back(); return token; } void Tree::generate() { root->generate(); }