// Statement.cpp Dave Reed 10/20/03 // /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include "Token.h" #include "Tokenizer.h" #include "VarTable.h" #include "Statement.h" using namespace std; void Expression::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the expression in the expr vector { Token t = program.GetToken(); while (true) { if (t.GetType() == INTEGER || t.GetType() == IDENTIFIER) { expr.push_back(t); } else { cout << "SYNTAX ERROR: malformed expression" << endl; exit(0); } if (program.PeekAhead().GetValue() == "+" || program.PeekAhead().GetValue() == "-") { expr.push_back(program.GetToken()); t = program.GetToken(); } else { return; } } } int Expression::Evaluate(VarTable & variables) const // Assumes: variables is a table of variable names and values // Returns: the value of the expression { int Value = 0; for (int i = 0; i < expr.size(); i+=2) { int factor = 1; if (i > 0 && expr[i-1].GetValue() == "-") { factor = -1; } if (expr[i].GetType() == INTEGER) { Value += factor * atoi(expr[i].GetValue().c_str()); } else if (expr[i].GetType() == IDENTIFIER) { Value += factor * variables.Lookup(expr[i].GetValue()); } } return Value; } void Expression::Display() const // Results: displays the expression, with a space between token values { for (int i = 0; i < expr.size(); i++) { cout << expr[i].GetValue() << " "; } } void Test::Read(Tokenizer & program) { lhs.Read(program); op = program.GetToken(); if (op.GetValue() != "<" && op.GetValue() != "<=" && op.GetValue() != ">" && op.GetValue() != ">=" && op.GetValue() != "==" && op.GetValue() != "!=") { cout << "ERROR: bad test" << endl; exit(1); } rhs.Read(program); } bool Test::Evaluate(VarTable & variables) const { if (op.GetValue() == "<") { return lhs.Evaluate(variables) < rhs.Evaluate(variables); } else if (op.GetValue() == "<=") { return lhs.Evaluate(variables) <= rhs.Evaluate(variables); } else if (op.GetValue() == ">") { return lhs.Evaluate(variables) > rhs.Evaluate(variables); } else if (op.GetValue() == ">=") { return lhs.Evaluate(variables) >= rhs.Evaluate(variables); } else if (op.GetValue() == "==") { return lhs.Evaluate(variables) == rhs.Evaluate(variables); } else if (op.GetValue() == "!=") { return lhs.Evaluate(variables) != rhs.Evaluate(variables); } } void Test::Display() const { lhs.Display(); cout << op.GetValue() << " "; rhs.Display(); } ////////////////////////////////////////////////////// Statement * Statement::GetNext(Tokenizer & program) { Token next = program.PeekAhead(); if (next.GetType() == UNKNOWN) { return NULL; } Statement * stmt; if (next.GetValue() == "begin" || next.GetValue() == "end") { stmt = new BlockStatement(); } else if (next.GetValue() == "output") { stmt = new OutputStatement(); } else if (next.GetValue() == "if") { stmt = new IfStatement(); } else if (next.GetValue() == "while") { stmt = new WhileStatement(); } else if (next.GetType() == IDENTIFIER) { stmt = new AssignStatement(); } else { cout << "ERROR: unrecognized statement" << endl; exit(1); } stmt->Read(program); return stmt; } ////////////////////////////////////////////////////// void BlockStatement::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the parts of the output statement { keyword = program.GetToken(); } void BlockStatement::Execute(VarTable & variables) const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { // DOES NOTHING } STATEMENT_TYPE BlockStatement::GetType() const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { if (keyword.GetValue() == "begin") { return BEGIN; } else{ return END; } } void BlockStatement::Display() const // Results: displays the output statement, with a space between token values { cout << keyword.GetValue() << endl; } //////////////////////////////////////////////////////// void OutputStatement::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the parts of the output statement { Token output = program.GetToken(); Token outVal = program.PeekAhead(); if (output.GetValue() == "output" && outVal.GetType() == STRING) { outVal = program.GetToken(); constant = outVal.GetValue().substr(1, outVal.GetValue().length()-2); } else if (output.GetValue() == "output" && (outVal.GetType() == INTEGER || outVal.GetType() == IDENTIFIER)) { constant = ""; rhs.Read(program); } else { cout << "SYNTAX ERROR: malformed output" << endl; exit(0); } } void OutputStatement::Execute(VarTable & variables) const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { if (constant == "") { cout << rhs.Evaluate(variables) << endl; } else { cout << constant << endl; } } STATEMENT_TYPE OutputStatement::GetType() const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { return OUTPUT; } void OutputStatement::Display() const // Results: displays the output statement, with a space between token values { if (constant == "") { cout << "output "; rhs.Display(); cout << endl; } else { cout << "output " << constant << endl; } } //////////////////////////////////////////////////////// void AssignStatement::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the parts of the assignment statement { Token vbl = program.GetToken(); Token op = program.GetToken(); if (vbl.GetType() == IDENTIFIER && op.GetValue() == "=" && (program.PeekAhead().GetType() == INTEGER || program.PeekAhead().GetType() == IDENTIFIER)) { lhs = vbl.GetValue(); rhs.Read(program); } else { cout << "SYNTAX ERROR: malformed assignment" << endl; exit(0); } } void AssignStatement::Execute(VarTable & variables) const // Assumes: variables is a table of variable names and values // Results: executes the assignment statement (assigns lhs = rhs) { variables.Update(lhs, rhs.Evaluate(variables)); } STATEMENT_TYPE AssignStatement::GetType() const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { return ASSIGN; } void AssignStatement::Display() const // Results: displays the assignment statement, with a space between token values { cout << lhs << " = "; rhs.Display(); cout << endl; } //////////////////////////////////////////////////////// void IfStatement::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the parts of the assignment statement { Token start = program.GetToken(); ifTest.Read(program); Statement * next = GetNext(program); while (next != NULL && next->GetType() != END) { stmts.push_back(next); next = GetNext(program); } if (next == NULL) { cout << "SYNTAX ERROR: missing end" << endl; exit(0); } } void IfStatement::Execute(VarTable & variables) const // Assumes: variables is a table of variable names and values // Results: executes the assignment statement (assigns lhs = rhs) { if (ifTest.Evaluate(variables)) { for (int i = 0; i < stmts.size(); i++) { stmts[i]->Execute(variables); } } } STATEMENT_TYPE IfStatement::GetType() const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { return IF; } void IfStatement::Display() const // Results: displays the assignment statement, with a space between token values { cout << "if "; ifTest.Display(); cout << endl; for (int i = 0; i < stmts.size(); i++) { cout << " "; stmts[i]->Display(); } cout << "end" << endl; } //////////////////////////////////////////////////////// void WhileStatement::Read(Tokenizer & program) // Assumes: program is the input stream for the program // Results: reads and stores the parts of the assignment statement { Token start = program.GetToken(); whileTest.Read(program); Statement * next = GetNext(program); while (next != NULL && next->GetType() != END) { stmts.push_back(next); next = GetNext(program); } if (next == NULL) { cout << "SYNTAX ERROR: missing end" << endl; exit(0); } } void WhileStatement::Execute(VarTable & variables) const // Assumes: variables is a table of variable names and values // Results: executes the assignment statement (assigns lhs = rhs) { while (whileTest.Evaluate(variables)) { for (int i = 0; i < stmts.size(); i++) { stmts[i]->Execute(variables); } } } STATEMENT_TYPE WhileStatement::GetType() const // Assumes: variables is a table of variable names and values // Results: executes the output statement (displays the value of the rhs) { return WHILE; } void WhileStatement::Display() const // Results: displays the assignment statement, with a space between token values { cout << "while "; whileTest.Display(); cout << endl; for (int i = 0; i < stmts.size(); i++) { cout << " "; stmts[i]->Display(); } cout << "end" << endl; }