1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | /* SI 413 Fall 2012 * Lab 7 * This file contains the implementations of longer methods in the * AST class hierarchy. */ #include "ast.hpp" SymbolTable ST; // The actual declaration of the global symbol table /* Adds this node and all children to the output stream in DOT format. * nextnode is the index of the next node to add. */ void AST::addToDot(ostream& out, int& nextnode) { int root = nextnode; ++nextnode; out << "\tn" << root << " [label=\"" << nodeLabel << "\"];" << endl; for (int i=0; i < children.size(); ++i) { int child = nextnode; children[i]->addToDot(out, nextnode); out << "\tn" << root << " -> n" << child << ";" << endl; } } /* Writes this AST to a .dot file as named. */ void AST::writeDot(const char* fname) { ofstream fout(fname); int nodes = 1; fout << "digraph AST {" << endl; addToDot (fout, nodes); fout << "}" << endl; fout.close(); } // ArithOp constructor ArithOp::ArithOp(Exp* l, Oper o, Exp* r) { op = o; left = l; right = r; nodeLabel = "Exp:ArithOp:"; switch(o) { case ADD: nodeLabel += '+'; break; case SUB: nodeLabel += '-'; break; case MUL: nodeLabel += '*'; break; case DIV: nodeLabel += '/'; break; default: nodeLabel += "ERROR"; } ASTchild(left); ASTchild(right); } // Evaluates an arithmetic operation Value ArithOp::eval() { int l = left->eval().num(); int r = right->eval().num(); switch(op) { case ADD: return l + r; case SUB: return l - r; case MUL: return l * r; case DIV: if (r != 0) return l / r; else if (!error) { error = true; errout << "ERROR: Divide by zero" << endl; } return Value(); default: return Value(); // shouldn't get here... } } // Constructor for CompOp CompOp::CompOp(Exp* l, Oper o, Exp* r) { op = o; left = l; right = r; nodeLabel = "Exp:CompOp:"; switch(o) { case LT: nodeLabel += "<"; break; case GT: nodeLabel += ">"; break; case LE: nodeLabel += "<="; break; case GE: nodeLabel += ">="; break; case EQ: nodeLabel += "="; break; case NE: nodeLabel += "!="; break; default: nodeLabel += "ERROR"; break; } ASTchild(left); ASTchild(right); } // Constructor for BoolOp BoolOp::BoolOp(Exp* l, Oper o, Exp* r) { op = o; left = l; right = r; nodeLabel = "Exp:BoolOp:"; if (o == AND) nodeLabel += "and"; else nodeLabel += "or"; ASTchild(left); ASTchild(right); } // Appends b to the end of a and returns the result. Stmt* Stmt::append(Stmt* a, Stmt* b) { if (! a->hasNext()) return b; Stmt* last = a; while (last->getNext()->hasNext()) last = last->getNext(); last->setNext(b); return a; } // Default constructor for Stmt. // This HAS to be declared here because it uses NullStmt, which // hasn't been defined yet in the header file! Stmt::Stmt() { next = new NullStmt(); children.push_back(next); } |