#include "L.hpp" #include "P.hpp" #include "dictionary.h" #include ////////////////////////////////////////////////////////////////////// // Parser ////////////////////////////////////////////////////////////////////// Expression* make_num( string s ) { istrstream iss(s.c_str()); if( s.find( "." ) != string::npos ) { float f; iss >> f; return new Float(f); } int i; iss >> i; return new Int(i); } ostream& operator<<( ostream& o, OP op ) { if( op == T_PLUS ) o << "+"; else if( op == T_MINUS ) o << "-"; else throw "Unknown operator"; return o; } ////////////////////////////////////////////////////////////////////// // Typechecker ////////////////////////////////////////////////////////////////////// Dictionary symbol_table; void declare( Declaration* d ) { if( symbol_table.contains( d->id() ) ) throw "Duplicate declataion of "+d->id(); else symbol_table.put( d->id(), d->type() ); } // Returns result type, promotes if necessary Type mix_type( MathOp* m ) { Type lhs = m->lhs()->type(); Type rhs = m->rhs()->type(); if( lhs==T_FLOAT && rhs==T_FLOAT ) return T_FLOAT; if( lhs==T_FLOAT ) { m->set_rhs( new IntToFloat( m->rhs() ) ); return T_FLOAT; } if( rhs==T_FLOAT ) { m->set_lhs( new IntToFloat( m->lhs() ) ); return T_FLOAT; } return T_INT; } void expr_check( Expression* e ) { if( typeid(*e) == typeid(Identifier) ) { Identifier* i = dynamic_cast(e); if( !symbol_table.contains( i->id() ) ) throw "Used undeclared variable"; i->set_type( symbol_table.at(i->id()) ); } else if( typeid(*e) == typeid(MathOp) ) { MathOp* m = dynamic_cast(e); expr_check( m->rhs() ); expr_check( m->lhs() ); m->set_type( mix_type(m) ); } else if( typeid(*e) == typeid(Int) ) { // do nothing } else if( typeid(*e) == typeid(Float) ) { // do nothing } else throw "Unknown expression type"; } void typecheck( Program* p ) { vector dv = p->declarations(); vector sv = p->statements(); for( vector::iterator i = dv.begin(); i != dv.end(); i++ ) declare( *i ); for( vector::iterator i = sv.begin(); i != sv.end(); i++ ) { if( typeid(**i) == typeid(PrintStatement) ) { // do nothing } else if( typeid(**i) == typeid(AssignStatement) ) { AssignStatement* s = dynamic_cast(*i); expr_check( s->rhs() ); expr_check( s->lhs() ); if( (s->lhs()->type() == T_INT) && (s->rhs()->type() == T_FLOAT) ) throw "Type mismatch"; } else throw "Unknown statement type"; } } ////////////////////////////////////////////////////////////////////// // Code generator ////////////////////////////////////////////////////////////////////// void codegen( Expression* e ) { if( typeid(*e) == typeid(MathOp) ) { MathOp* s = dynamic_cast( e ); codegen( s->lhs() ); codegen( s->rhs() ); cout << s->op() << endl; } else if( typeid(*e) == typeid(Identifier) ) { Identifier* s = dynamic_cast( e ); cout << "l" << s->id() << endl; } else if( typeid(*e) == typeid(IntToFloat) ) { IntToFloat* s = dynamic_cast( e ); codegen( s->exp() ); cout << "5 k" << endl; } else if( typeid(*e) == typeid(Int) ) { Int* s = dynamic_cast( e ); cout << s->value() << endl; } else if( typeid(*e) == typeid(Float) ) { Float* s = dynamic_cast( e ); cout << s->value() << endl; } else throw "Unknown expression type"; } void codegen( Program* p ) { cout << "dc version of program follows:" << endl << endl; vector sv = p->statements(); for( vector::iterator i = sv.begin(); i != sv.end(); i++ ) { if( typeid(**i) == typeid(AssignStatement) ) { AssignStatement* s = dynamic_cast( *i ); codegen( s->rhs() ); cout << "s" << s->lhs()->id() << endl; cout << "0 k" << endl; } else if( typeid(**i) == typeid(PrintStatement) ) { PrintStatement* s = dynamic_cast( *i ); codegen( s->id() ); cout << "p" << endl; cout << "si" << endl; } else throw "Unknown statement type"; } cout << endl; } ////////////////////////////////////////////////////////////////////// // Main ////////////////////////////////////////////////////////////////////// int main() { try { L lexer(cin); P parser(lexer); cout << "lexing and parsing" << endl; Program* p = parser.prog(); cout << "typechecking" << endl; typecheck(p); codegen(p); } catch( string s ) { cout << "Error: " << s << endl; } catch( char* s ) { cout << "Error: " << s << endl; } catch( ... ) { cout << "Unknown error" << endl; } }