CTacAddr* CAstStatIf::ToTac(CCodeBlock *cb, CTacLabel *next) { CTacLabel* truelabel = cb->CreateLabel("if_true"); // true label CTacLabel* falselabel = cb->CreateLabel("if_false"); // false label _cond->ToTac(cb, truelabel, falselabel); // calculate condition CAstStatement *s = _ifBody; cb->AddInstr(truelabel); // install true label while(s != NULL) { // TAC of ifBody CTacLabel* tempnext = cb->CreateLabel(); s->ToTac(cb, tempnext); cb->AddInstr(tempnext); s = s->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, next)); // skip to next s = _elseBody; cb->AddInstr(falselabel); // install false label while(s != NULL) { // TAC of elseBody CTacLabel* tempnext = cb->CreateLabel(); s->ToTac(cb, tempnext); cb->AddInstr(tempnext); s = s->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, next)); // goto next return NULL; }
void CAstScope::toDot(ostream &out, int indent) const { string ind(indent, ' '); CAstNode::toDot(out, indent); CAstStatement *s = GetStatementSequence(); if (s != NULL) { string prev = dotID(); do { s->toDot(out, indent); out << ind << prev << " -> " << s->dotID() << " [style=dotted];" << endl; prev = s->dotID(); s = s->GetNext(); } while (s != NULL); } vector<CAstScope*>::const_iterator it = _children.begin(); while (it != _children.end()) { CAstScope *s = *it++; s->toDot(out, indent); out << ind << dotID() << " -> " << s->dotID() << ";" << endl; } }
CTacAddr* CAstStatWhile::ToTac(CCodeBlock *cb, CTacLabel *next) { assert(cb != NULL && next != NULL); CAstExpression *cond = GetCondition(); CAstStatement *body = GetBody(); CTacLabel *while_cond = cb->CreateLabel("while_cond"); CTacLabel *c_true = cb->CreateLabel("while_body"); // while condition begins cb->AddInstr(while_cond); CTacAddr *tCond = cond->ToTac(cb, c_true, next); if(dynamic_cast<CAstDesignator*>(cond)) { // if cond is a single boolean cb->AddInstr(new CTacInstr(opEqual, c_true, tCond, new CTacConst(1))); cb->AddInstr(new CTacInstr(opGoto, next)); } // while body starts.. cb->AddInstr(c_true); while(body) { CTacLabel *while_next = cb->CreateLabel("while_next"); body->ToTac(cb, while_next); cb->AddInstr(while_next); body = body->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, while_cond)); return NULL; }
ostream& CAstScope::print(ostream &out, int indent) const { string ind(indent, ' '); out << ind << "CAstScope: '" << _name << "'" << endl; out << ind << " symbol table:" << endl; _symtab->print(out, indent+4); out << ind << " statement list:" << endl; CAstStatement *s = GetStatementSequence(); if (s != NULL) { do { s->print(out, indent+4); s = s->GetNext(); } while (s != NULL); } else { out << ind << " empty." << endl; } out << ind << " nested scopes:" << endl; if (_children.size() > 0) { for (size_t i=0; i<_children.size(); i++) { _children[i]->print(out, indent+4); } } else { out << ind << " empty." << endl; } out << ind << endl; return out; }
CTacAddr* CAstScope::ToTac(CCodeBlock *cb) { assert (cb != NULL); CAstStatement *s = GetStatementSequence(); while(s != NULL) { // statements -> TAC. connect each by "next" label CTacLabel *next = cb->CreateLabel(); s->ToTac(cb, next); cb->AddInstr(next); s = s->GetNext(); } cb->CleanupControlFlow(); // clean up control flow return NULL; }
CAstStatement* CParser::statSequence(CAstScope *s) { // // statSequence ::= [ statement { ";" statement } ]. // FIRST(statement) = {tIF, tWhile, tReturn, tIdent}. // FOLLOW(statSequence) = {tEnd, tElse}. // CAstStatement *head = NULL; CAstStatement *tail = NULL; EToken tt = _scanner->Peek().GetType(); switch(tt) { case tIf: case tWhile: case tReturn: case tIdent: head = tail = statement(s); assert(head != NULL); // for multiple statements. while(1) { if(_scanner->Peek().GetType() == tEnd || _scanner->Peek().GetType() == tElse) { break; } else { Consume(tSemicolon); CAstStatement *st = NULL; st = statement(s); assert(st != NULL); tail->SetNext(st); tail = st; } } break; default: break; } return head; }
bool CAstStatWhile::TypeCheck(CToken *t, string *msg) const { if(!_cond->TypeCheck(t, msg)) return false; // Do TypeCheck on condition expression if(!_cond->GetType()->IsBoolean()) { if(t != NULL) *t = _cond->GetToken(); if(msg != NULL) *msg = "boolean expression expected."; return false; } bool result = true; CAstStatement *s = _body; while(result && (s != NULL)) { // Do TypeCheck on all body-statements result = s->TypeCheck(t, msg); s = s->GetNext(); } return result; }
CTacAddr* CAstScope::ToTac(CCodeBlock *cb) { assert(cb != NULL); CAstStatement *s = GetStatementSequence(); // ToTac for all statement sequence. while (s != NULL) { CTacLabel *next = cb->CreateLabel(); s->ToTac(cb, next); cb->AddInstr(next); s = s->GetNext(); } // clean up all unnecessary labels. cb->CleanupControlFlow(); return NULL; }
ostream& CAstStatWhile::print(ostream &out, int indent) const { string ind(indent, ' '); out << ind << "while cond" << endl; _cond->print(out, indent+2); out << ind << "while-body" << endl; if (_body != NULL) { CAstStatement *s = _body; do { s->print(out, indent+2); s = s->GetNext(); } while (s != NULL); } else out << ind << " empty." << endl; return out; }
bool CAstStatIf::TypeCheck(CToken *t, string *msg) const { CAstExpression *cond = GetCondition(); bool result = true; if (!cond->TypeCheck(t, msg)) return false; if (cond->GetType() != CTypeManager::Get()->GetBool()) { if (t != NULL) *t = cond->GetToken(); if (msg != NULL) *msg = "boolean expression expected."; return false; } try { CAstStatement *ifBody = GetIfBody(); CAstStatement *elseBody = GetElseBody(); while (result && (ifBody != NULL)) { result = ifBody->TypeCheck(t, msg); ifBody = ifBody->GetNext(); } while (result && (elseBody != NULL)) { result = elseBody->TypeCheck(t, msg); elseBody = elseBody->GetNext(); } } catch (...) { result = false; } return result; }
CTacAddr* CAstStatWhile::ToTac(CCodeBlock *cb, CTacLabel *next) { CTacLabel* lcond = cb->CreateLabel("while_cond"); // condition label CTacLabel* lbody = cb->CreateLabel("while_body"); // body label cb->AddInstr(lcond); // install condition label _cond->ToTac(cb, lbody, next); cb->AddInstr(lbody); CAstStatement *s = _body; while(s != NULL) { CTacLabel *tempnext = cb->CreateLabel(); s->ToTac(cb, tempnext); cb->AddInstr(tempnext); s = s->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, lcond)); return NULL; }
bool CAstScope::TypeCheck(CToken *t, string *msg) const { bool result = true; try { CAstStatement *s = _statseq; while(result && (s != NULL)) { // do TypeCheck for all statements under this scope result = s->TypeCheck(t, msg); s = s->GetNext(); } vector<CAstScope*>::const_iterator it = _children.begin(); while(result && (it != _children.end())) { // do TypeCheck for all scopes under this scope result = (*it)->TypeCheck(t, msg); it++; } } catch(...) { result = false; } return result; }
void CAstStatWhile::toDot(ostream &out, int indent) const { string ind(indent, ' '); CAstNode::toDot(out, indent); _cond->toDot(out, indent); out << ind << dotID() << "->" << _cond->dotID() << ";" << endl; if (_body != NULL) { CAstStatement *s = _body; if (s != NULL) { string prev = dotID(); do { s->toDot(out, indent); out << ind << prev << " -> " << s->dotID() << " [style=dotted];" << endl; prev = s->dotID(); s = s->GetNext(); } while (s != NULL); } } }
CTacAddr* CAstStatIf::ToTac(CCodeBlock *cb, CTacLabel *next) { assert(cb != NULL && next != NULL); CAstExpression *cond = GetCondition(); CAstStatement *ifBody = GetIfBody(); CAstStatement *elseBody = GetElseBody(); CTacLabel *c_true = cb->CreateLabel("if_true"); CTacLabel *c_false = cb->CreateLabel("if_false"); // starting with translate condition CTacAddr *tCond = cond->ToTac(cb, c_true, c_false); if(dynamic_cast<CAstDesignator*>(cond)) { // if cond is a single boolean cb->AddInstr(new CTacInstr(opEqual, c_true, tCond, new CTacConst(1))); cb->AddInstr(new CTacInstr(opGoto, c_false)); } // if_body starts.. cb->AddInstr(c_true); while(ifBody) { CTacLabel *if_next = cb->CreateLabel("if_next"); ifBody->ToTac(cb, if_next); cb->AddInstr(if_next); ifBody = ifBody->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, next)); // if else_body exists, else_body starts.. cb->AddInstr(c_false); if(elseBody) { while(elseBody) { CTacLabel *else_next = cb->CreateLabel("else_next"); elseBody->ToTac(cb, else_next); cb->AddInstr(else_next); elseBody = elseBody->GetNext(); } cb->AddInstr(new CTacInstr(opGoto, next)); } return NULL; }
CAstStatement* CParser::statSequence(CAstScope *s) { // // stateSequence ::= [ statement { ";" statement } ]. // statement ::= assignment | subroutineCall // | ifStatement | whileStatement | returnStatement. // CAstStatement *head = NULL; CAstStatement *tail = NULL; CToken tt = _scanner->Peek(); while (!_abort && tt.GetType() != kEnd && tt.GetType() != kElse) { CAstStatement *st = NULL; // stateSequence -> ... statement ... tt = _scanner->Peek(); switch (tt.GetType()) { // statement -> assignment | subroutineCall case tIdent: { const CSymbol *sym = s->GetSymbolTable()->FindSymbol(tt.GetValue(), sLocal); if (!sym) sym = s->GetSymbolTable()->FindSymbol(tt.GetValue(), sGlobal); if (!sym) SetError(tt, "undeclared variable \"" + tt.GetValue() + "\""); ESymbolType stype = sym->GetSymbolType(); if (stype == stProcedure) st = subroutineCall(s); else st = assignment(s); } break; // statement -> ifStatement case kIf: st = ifStatement(s); break; // statement -> whileStatement case kWhile: st = whileStatement(s); break; // statement -> returnStatement case kReturn: st = returnStatement(s); break; default: SetError(_scanner->Peek(), "statement expected."); break; } assert(st); if (!head) head = st; else tail->SetNext(st); tail = st; tt = _scanner->Peek(); if (tt.GetType() == kEnd || tt.GetType() == kElse) break; // stateSequence -> ... ";" ... Consume(tSemicolon); } return head; }