Don't wanna be here? Send us removal request.
Text
Self compiling C compiler, written in C
// symboltable.h
#ifndef _SYMBOLTABLE_GUARD #define _SYMBOLTABLE_GUARD
using namespace std;
#include <string> #include "symbol.h" #include <list> #include <iostream>
// David Haltinner ******************************************************* // The SymbolTable class implements a symbol table, which is a set of // pointers to Symbols. // David Haltinner ******************************************************* // // public member functions // ======================= // // constructor/destructor // ====================== // not needed -- the defaults work fine // // mutators/modifiers // ================== // void Insert(SymbolPtr sym) -- add sym to the table (error if there is // -- already a symbol with the same name) // // other operations // ================ // SymbolPtr Lookup(string k) -- if there is a symbol with the given name, // -- return a pointer to it; // -- otherwise, return NULL // Print(ostream & out) // -- print the names of all the symbols, one // -- per line, to the given output stream
class SymbolTable { public: // mutator/modifier member functions
void Insert(SymbolPtr sym);
// other operations
SymbolPtr Lookup(string k); void Print(ostream &out);
private: static const int TABLESIZE = 17; list<SymbolPtr> bucket[TABLESIZE]; int Hash(string & S); };
#endif # Makefile for p4
CC = g++ CFLAGS = -Wall -g
LEX = flex LEXLIB = -lfl YACC = bison -yd
OBJ = main.o message.o symbol.o symboltable.o symlist.o ast.o \ y.tab.o lex.yy.o namecheck.o typecheck.o unparse.o int2str.o\ codegen.o emit.o
p5: $(OBJ) $(CC) $(OBJ) -o p5 $(LEXLIB) wosym: main.o message.o symbol.o symboltable.o symlist.obj ast.o y.tab.o lex.yy.o namecheck.o typecheck.o unparse.o int2str.o $(CC) main.o message.o symbol.o symboltable.o symlist.obj ast.o y.tab.o lex.yy.o namecheck.o typecheck.o unparse.o int2str.o -o p4 $(LEXLIB)
main.o: main.cc ast.h symbol.h scanner.h $(CC) -c $(CFLAGS) main.cc message.o: message.cc message.h $(CC) -c $(CFLAGS) message.cc symbol.o: symbol.cc symbol.h $(CC) -c $(CFLAGS) symbol.cc symboltable.o: symboltable.cc symbol.h symboltable.h $(CC) -c $(CFLAGS) symboltable.cc symlist.o: symlist.cc symlist.h $(CC) -c $(CFLAGS) symlist.cc ast.o: ast.cc ast.h symbol.h $(CC) -c $(CFLAGS) ast.cc unparse.o: unparse.cc ast.h symbol.h y.tab.h $(CC) -c $(CFLAGS) unparse.cc
int2str.o: int2str.cc int2str.h $(CC) -c $(CFLAGS) int2str.cc
namecheck.o: namecheck.cc ast.h symbol.h symboltable.h message.h \ symlist.h $(CC) -c $(CFLAGS) namecheck.cc typecheck.o: typecheck.cc ast.h symbol.h symboltable.h message.h \ symlist.h $(CC) -c $(CFLAGS) typecheck.cc
codegen.o: codegen.cc ast.h emit.h scanner.h y.tab.h message.h symlist.h\ symboltable.h int2str.h $(CC) -c $(CFLAGS) codegen.cc
emit.o: emit.cc emit.h ast.h message.h int2str.h $(CC) -c $(CFLAGS) emit.cc
y.tab.o: y.tab.c $(CC) -c $(CFLAGS) y.tab.c y.tab.h: y.tab.c touch y.tab.h y.tab.c: grammar.yacc ast.h symbol.h scanner.h $(YACC) grammar.yacc
lex.yy.o: lex.yy.c ast.h symbol.h scanner.h message.h int2str.h y.tab.h $(CC) -c $(CFLAGS) lex.yy.c -DYY_NO_UNPUT lex.yy.c: tokens.lex y.tab.h $(LEX) tokens.lex
listings: enscript -2r -P halseyLinux \ main.cc Makefile codegen.cc
test: Go clean: /bin/rm -f *.o lex.yy.c y.tab.* erase: /bin/rm -f *.o *.s lex.yy.c y.tab.* p5 preClean: /bin/rm -f *.s // symlist.h
#ifndef SYMLIST_H_ #define SYMLIST_H_
#include <list> #include <string>
#include "symboltable.h" using namespace std;
typedef SymbolTable *PSymbolTable;
class SymTableList {
public: SymTableList(); ~SymTableList();
void push( PSymbolTable v ); // AddToFront PSymbolTable pop(); // RemoveFromFront PSymbolTable top(); // current scope
SymbolPtr lookUp( string id ); // is id in any scope?
private: list<PSymbolTable> * symTableList; // STL list };
#endif // message.cc
#include <iostream> #include <iomanip> #include "message.h"
// GLOBAL VARIABLE bool errorFlag = false;
// David Haltinner ******************************************************* // Error // write the given error message, preceded by <line>:<col> to cerr // also set the global errorFlag to true // David Haltinner ******************************************************* void Error(int line, int col, string msg) { cerr << "ERROR line " << setw(2) << line << " column " << setw(2) << col << ": " << msg << endl; errorFlag = true; }
// David Haltinner ******************************************************* // Warn // write the given warning message, preceded by <line>:<col> to cerr // David Haltinner ******************************************************* void Warn(int line, int col, string msg) { cerr << "WARNING line " << setw(2) << line << " column " << setw(2) << col << ": " << msg << endl; }
// David Haltinner ******************************************************* // InternalError // write the given error message to cerr and quit // David Haltinner ******************************************************* void InternalError(string msg) { cerr << endl << "INTERNAL COMPILER ERROR: " << msg << endl<<endl; exit(1); } // this is just a test of string labels for print
int main(){ print("This is a test of the labeling"); print("\n"); print("This is a test of the labeling"); print("\n"); print("This is a test of the labeling"); print("\n"); print("This is a test of the labeling"); print("\n"); print("I hope this works"); print("\n"); print("This is a test of the labeling"); print("\n"); print("I hope this works"); print("\n"); print("This is a test of the labeling"); print("\n"); print("I hope this works"); print("\n"); print("This is a"); print("\n"); print("This is a test of the labeling"); print("\n"); } // test of various types of globals
int x; bool y; int w[2]; bool z[2];
int t(){ int x; bool z; z = true && y; // 1st true 2nd false x = 99; // 1st the then is executed // 2nd the else is executed if(z){ print("z is ", z, " x is ", x); print("\n"); x = 3; } else{ print("z failed", "\n"); x = 1; }
return x; }
int main(){ y = 3 == 3 && 4 < 5 && 7 != 9; // true x = 7; print("X before ", x, "\n"); w[0] = t(); print("X after ", x, "\n"); y = false; z[0] = false; z[1] = false; w[1] = t(); // this executes if(w[0] != w[1]){ print("Just as I thought", "\n"); print("W[0] is ", w[0], " and W[1] is ", w[1], "\n"); } return 1; } /* grammar.yacc */
%{ // stuff here is copied directly into y.tab.c above (outside of) yyparse()
#include "ast.h" #include "scanner.h"
// bison needs these two forward declarations (but yacc doesn't) extern int yylex(); int yyerror( char *msg);
// just need "one" null node // don't need to create a "new" null node every time we need one static NullNode * NULLnode = new NullNode();
%}
/* define the data type of the value stack (YYSTYPE) the "value" associated with some tokens will be data type TokenType the "value" associated with nonterminals will be data type ...Node * */
%union{ TokenType t;
ProgramNode * Program ; GlobalListNode * GlobalList ; FunctionListNode * FunctionList ; FunctionDeclNode * FunctionDecl ; TypeNode * Type ; ParametersNode * Parameters ; ParamListNode * ParamList ; ParamNode * Param ; VarListNode * VarList ; DeclNode * Decl ; ArgListNode * ArgList ; StmtListNode * StmtList ; StmtNode * Stmt ; PrintListNode * PrintList ; PrintItemNode * PrintItem ; CoutListNode * CoutList ; CoutItemNode * CoutItem ; OrNode * Or ; AndNode * And ; RelOpNode * RelOp ; ArithOpNode * ArithOp ; ExpressionNode * Expression ; TargetNode * Target ; IdentifierNode * Identifier ; StringLiteralNode * StringLiteral ; }
/* since the value stack is a struct(union), it seems we need to use the notation $2.t or $$.a; the actual ugly notation is $<t>2 or $<a>$ the %type directive lets us use $2 or $$ because it tells yacc/bison which member of the struct(union) should be referenced */
/*** do not change these token and type specifications! ***/ /* David Haltinner ====================================================== */ %token SEMICOLON RPAREN RBRACE RBRACKET %token <t> ID INTLITERAL STRINGLITERAL ASSIGN PRINT INT VOID TRUE FALSE %token <t> LPAREN LBRACE LBRACKET PLUS MINUS TIMES SLASH BOOL AND OR %token <t> IF ELSE WHILE RETURN LT GT LEQ GEQ EQ NEQ COMMA %token <t> COUT AARROW
%type <Program> program %type <GlobalList> globalList %type <FunctionList> functionList %type <FunctionDecl> functionDecl %type <Type> type %type <Decl> variableDecl %type <Parameters> parameters %type <ParamList> paramList %type <Param> param %type <VarList> varList %type <StmtList> stmtList %type <ArgList> argList %type <Stmt> stmt %type <PrintList> printList %type <PrintItem> printItem %type <CoutList> coutList %type <PrintItem> coutItem
%type <Expression> expression %type <Expression> term %type <Expression> factor %type <Expression> primary %type <Expression> unit %type <Expression> nameVar %type <Expression> arrayVar %type <Expression> intLiteral
%type <Expression> ORexpression %type <Expression> ANDexpression %type <Expression> ORlist %type <Expression> ANDlist
%type <Target> target %type <Identifier> identifier %type <StringLiteral> stringLiteral /* David Haltinner ====================================================== */
%nonassoc THEN %nonassoc ELSE
%start program
%%
program : globalList functionList { astRoot = new ProgramNode($1,$2, $1->line,$1->column); } ;
globalList : globalList variableDecl { $$ = new GlobalListNode($1, $2, $1->line,$1->column ); } | { $$ = (GlobalListNode *)NULLnode; } ;
functionList : functionList functionDecl { $$ = new FunctionListNode($1, $2, $2->line, $2->column); } | functionDecl {$$ = new FunctionListNode( (FunctionListNode *)NULLnode, $1,$1->line,$1->column);} ;
type : INT {$$ = new TypeIntNode ( $1.line,$1.column ); } | BOOL {$$ = new TypeBoolNode( $1.line, $1.column); } ;
variableDecl : type identifier SEMICOLON {$$ = new VariableDeclNode( $1,$2, $2->line,$2->column );} | type identifier LBRACKET intLiteral RBRACKET SEMICOLON {$$ = new ArrayDeclNode($1, $2, $4, $2->line, $2->column );} ;
functionDecl : VOID identifier parameters LBRACE varList stmtList RBRACE {$$ = new FunctionDeclNode( (TypeNode *)NULLnode, $2,$3,$5,$6,$2->line,$2->column);} | type identifier parameters LBRACE varList stmtList RBRACE {$$ = new FunctionDeclNode($1, $2, $3, $5, $6, $2->line, $2->column);} ;
parameters : LPAREN RPAREN { ParamListNode * n = (ParamListNode *)NULLnode; $$ = new ParametersNode( n, $1.line,$1.column ); } | LPAREN paramList RPAREN { $$ = new ParametersNode($2, $1.line, $1.column); } ;
paramList : paramList COMMA param { $$ = new ParamListNode($1, $3, $2.line, $2.column); } | param { $$ = new ParamListNode( (ParamListNode *)NULLnode, $1, $1->line, $1->column); } ;
param : type identifier { $$ = new ParamValNode($1, $2, $1->line, $1->column); } | type identifier LBRACKET RBRACKET { $$ = new ParamArrayNode($1, $2, $1->line, $1->column); } ;
varList : { $$ = (VarListNode *)NULLnode; } | varList variableDecl { $$ = new VarListNode($1, $2, $1->line, $1->column); } ;
stmtList : stmtList stmt { $$ = new StmtListNode( $1, $2, $1->line,$1->column ); } | { $$ = (StmtListNode *)NULLnode; } ;
stmt : target ASSIGN expression SEMICOLON { $$ = new AssignNode( $1, $3, $2.line,$2.column ); } | PRINT LPAREN printList RPAREN SEMICOLON { $$ = new PrintNode( $3, $1.line,$1.column ); } | COUT AARROW coutList SEMICOLON { $$ = new CoutNode( $3, $1.line, $1.column ); } | IF LPAREN expression RPAREN stmt %prec THEN { $$ = new IfNode($3, $5, (StmtNode *)NULLnode, $2.line, $2.column); } | IF LPAREN expression RPAREN stmt ELSE stmt { $$ = new IfNode($3, $5, $7, $2.line, $2.column); } | WHILE LPAREN expression RPAREN stmt { $$ = new WhileNode($3, $5, $1.line, $1.column); } | LBRACE varList stmtList RBRACE { $$ = new BlockNode($2, $3, $1.line, $1.column); } | RETURN SEMICOLON { $$ = new ReturnNode((ExpressionNode *)NULLnode, $1.line, $1.column); } | RETURN expression SEMICOLON { $$ = new ReturnNode($2, $1.line, $1.column); } | identifier LPAREN RPAREN SEMICOLON { ArgListNode * n = (ArgListNode *)NULLnode; $$ = new ProcCallNode($1, n, $2.line, $2.column); } | identifier LPAREN argList RPAREN SEMICOLON { $$ = new ProcCallNode($1, $3, $2.line, $2.column); } ;
argList : argList COMMA expression { $$ = new ArgListNode($1, $3, $1->line, $1->column); } | expression { $$ = new ArgListNode((ArgListNode *)NULLnode, $1, $1->line, $1->column); } ;
printList : printList COMMA printItem { $$ = new PrintListNode($1, $3, $1->line, $1->column); } | printItem { PrintListNode * n = (PrintListNode *)NULLnode; $$ = new PrintListNode( n, $1, $1->line,$1->column); } ;
printItem : stringLiteral { $$ = $1; } | expression { $$ = $1; } ;
coutList : coutList AARROW coutItem { $$ = new CoutListNode($1, $3, $1->line, $1->column); } | coutItem { CoutListNode *n = (CoutListNode *)NULLnode; $$ = new CoutListNode( n, $1, $1->line, $1->column); } ;
coutItem : stringLiteral {$$ = $1; } | expression {$$ = $1; };
expression : ORexpression { $$ = $1; };
ORexpression: ORlist { $$ = $1; };
ORlist: ORlist OR ANDexpression { $$ = new OrNode($1, $3, $2.line, $2.column); } | ANDexpression { $$ = $1; } ;
ANDexpression: ANDlist { $$ = $1; };
ANDlist: ANDlist AND term { $$ = new AndNode($1, $3, $2.line, $2.column); } | term { $$ = $1; };
term : factor LT factor { $$ = new RelOpNode( LT, $1, $3, $2.line, $2.column); } | factor GT factor { $$ = new RelOpNode( GT, $1, $3, $2.line, $2.column); } | factor LEQ factor { $$ = new RelOpNode( LEQ, $1, $3, $2.line, $2.column); } | factor GEQ factor { $$ = new RelOpNode( GEQ, $1, $3, $2.line, $2.column); } | factor EQ factor { $$ = new RelOpNode( EQ, $1, $3, $2.line, $2.column); } | factor NEQ factor { $$ = new RelOpNode( NEQ, $1, $3, $2.line, $2.column); } | factor { $$ = $1; } ;
factor : factor PLUS primary { $$ = new ArithOpNode( PLUS , $1, $3, $2.line,$2.column ); } | factor MINUS primary { $$ = new ArithOpNode( MINUS, $1, $3, $2.line,$2.column ); } | primary { $$ = $1; } ;
primary : primary TIMES unit { $$ = new ArithOpNode( TIMES, $1, $3, $2.line, $2.column); } | primary SLASH unit { $$ = new ArithOpNode( SLASH, $1, $3, $2.line, $2.column); } | unit { $$ = $1; } ;
unit : nameVar { $$ = $1; } | arrayVar { $$=$1;} | intLiteral { $$=$1;} | MINUS intLiteral { $$=$2; $$->myIntVal=-$2->myIntVal;} | identifier LPAREN RPAREN { $$= new FnCallNode($1, (ArgListNode *)NULLnode, $2.line, $2.column); } | identifier LPAREN argList RPAREN { $$= new FnCallNode($1, $3, $2.line, $2.column); } | TRUE { $$ = new TrueNode($1.line, $1.column);} | FALSE { $$ = new FalseNode($1.line, $1.column);} | LPAREN expression RPAREN { $$=$2; } ;
nameVar : identifier { $$ = new NameVarNode( $1, $1->line,$1->column ); };
arrayVar: identifier LBRACKET expression RBRACKET { $$ = new ArrayVarNode( $1, $3, $1->line, $1->column); };
intLiteral : INTLITERAL { $$ = new IntLiteralNode($1.intVal, $1.line,$1.column); };
stringLiteral : STRINGLITERAL { $$ = new StringLiteralNode($1.stringVal, $1.line, $1.column);};
target : identifier { ExpressionNode * n = (ExpressionNode *)NULLnode; $$ = new TargetNode( $1, n, $1->line,$1->column ); } | identifier LBRACKET expression RBRACKET { $$ = new TargetNode($1, $3, $1->line, $1->column ); } ;
identifier : ID { $$ = new IdentifierNode($1.stringVal, $1.line,$1.column); } ;
%%
extern char *yytext; /* we must supply the yyerror function */ /* bison demands int; yacc accepts int or void */ int yyerror( char *msg ) { cerr << "\nbison: " << msg << " line " << yylval.t.line << " column " << yylval.t.column << " (yytext=\"" << yytext << "\")\n\n"; exit(1); } // symbol.h
#ifndef SYMBOL_GUARD #define SYMBOL_GUARD
#include <string> using namespace std;
// ********************************************* // The Symbol class defines a symbol-table entry // ********************************************* // // Member functions // ================ // // constructor // =========== // Symbol(string S) -- constructor: creates a Symbol with the given name //
enum SymbolType {VoidType, IntType, BoolType, StringType, ErrorType}; enum SymbolKind {VarKind,ArrayKind, FnKind, ValParamKind,ArrayParamKind, ErrorKind}; enum SymbolAdr {Global, Local};
class Symbol { public: Symbol(string S); // constructor
string symbolName; // symbol name
//set by the name checker
SymbolType symbolType; SymbolKind symbolKind;
int arraySize; int offset; int parameterCount; // only for functions int localVarCount; // only for functions int frameSize; // only for functions
//set by the code generator
SymbolAdr adr;
// class function (for debugging) static string printSymbolType( SymbolType t ); };
typedef Symbol * SymbolPtr;
#endif // t1.z // A demonstration of bools and if // it also prints intLits and global ints, and string lits
int x; int y; bool b; bool t; bool f;
int main() { x = 3; y = x; print( x, " ", y, " ", 5 ); print("\n");
if (true ) print("true"); else print("false"); print("\n"); if (false) print("true"); else print("false"); print("\n");
t = true; f = false; b = true ; if (b) print("true"); else print("false"); print("\n"); b = false; if (b) print("true"); else print("false"); print("\n"); b = t ; if (b) print("true"); print("\n"); t = f ; if (t) print("true"); else print("false"); print("\n");
return 0; } // ast.h
#ifndef AST_H_ #define AST_H_
#include <iostream> #include <iomanip> #include "symbol.h"
// forward class GlobalListNode ; class FunctionListNode ; class DeclNode ; class FunctionDeclNode ; class TypeNode ; class ParametersNode ; class ParamListNode ; class ParamNode ; class VarListNode ; class StmtListNode ; class StmtNode ; class ArgListNode ; class PrintListNode ; class PrintItemNode ; class ExpressionNode ; class TargetNode ; class IntLiteralNode ; class CoutListNode ; class CoutItemNode ;
class ASTnode // ABSTRACT BASE CLASS { public:
// every node will have a line number and a column number // so unparsing can produce a kind of pretty-printing const int line ; const int column; void doLineNum() { cout << setw(6) << line << ": "; } int Reg; int lbl;
SymbolType nodeType;
ASTnode(int l, int c) : line(l), column(c) {};
virtual bool isNull () { return false; } virtual bool isBlock() { return false; } virtual bool isName() { return false; } virtual bool isOr() { return false; } virtual bool isAnd() { return false; } virtual bool isRel() { return false; } virtual bool isTrue() { return false; } virtual bool isFalse() { return false; } virtual void unparse(int indent=0) =0; virtual void checkNames() =0; virtual void checkTypes() =0; virtual void emitCode() =0; private:
// disable copy constructor and copy assignment operator ASTnode(const ASTnode & n); ASTnode & operator= (const ASTnode & n); };
class IdentifierNode : public ASTnode { private: string * myStringVal; Symbol * mySymbolTableEntry; public: IdentifierNode(string *, int, int); string getMyStringVal() { return * myStringVal; } void setMySymbolTableEntry(Symbol * s) { mySymbolTableEntry = s; } Symbol * getSymbol() { return mySymbolTableEntry; } virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode() {return;} };
class ProgramNode : public ASTnode { private: GlobalListNode * myGlobalList; FunctionListNode * myFunctionList; public: ProgramNode(GlobalListNode*, FunctionListNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class GlobalListNode : public ASTnode { private: GlobalListNode * myGlobalList; DeclNode * myDecl; public: GlobalListNode(GlobalListNode*, DeclNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class FunctionListNode : public ASTnode { private: FunctionListNode * myFunctionList; FunctionDeclNode * myFunctionDecl; public: FunctionListNode(FunctionListNode*, FunctionDeclNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class FunctionDeclNode : public ASTnode { private: TypeNode * myType; IdentifierNode * myIdentifier; ParametersNode * myParameters; VarListNode * myVarList; StmtListNode * myStmtList; Symbol * mySymbolTableEntry; public: FunctionDeclNode( TypeNode*, IdentifierNode*, ParametersNode*, VarListNode*, StmtListNode*, int, int); void setMySymbolTableEntry(Symbol * s) { mySymbolTableEntry = s; } virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class TypeNode : public ASTnode // ABSTRACT BASE CLASS { public: TypeNode(int, int); virtual void unparse(int indent=0) =0; virtual void checkNames() = 0; virtual void checkTypes() = 0; }; // --------------- SUBCLASSES OF TypeNode --------------- class TypeIntNode : public TypeNode { public: TypeIntNode(int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class TypeBoolNode : public TypeNode { public: TypeBoolNode(int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); }; // --------------- SUBCLASSES OF TypeNode ---------------
class DeclNode : public ASTnode // ABSTRACT BASE CLASS { public: DeclNode(int, int); virtual void unparse(int indent=0) =0; virtual void checkNames() = 0; virtual void checkTypes() = 0; virtual void emitCode() = 0; }; // --------------- SUBCLASSES OF DeclNode ---------------
class VariableDeclNode : public DeclNode { private: TypeNode * myType; IdentifierNode * myIdentifier; public: VariableDeclNode(TypeNode*, IdentifierNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ArrayDeclNode : public DeclNode { private: TypeNode * myType; IdentifierNode * myIdentifier; ExpressionNode * myIntLit; public: ArrayDeclNode(TypeNode*, IdentifierNode*, ExpressionNode*, int,int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); }; // --------------- SUBCLASSES OF DeclNode ---------------
class ParametersNode : public ASTnode { private: ParamListNode * myParamList; public: ParametersNode :: ParametersNode(ParamListNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ParamListNode : public ASTnode { private: ParamListNode * myParamList; ParamNode * myParam ; public: ParamListNode :: ParamListNode(ParamListNode*, ParamNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ParamNode : public ASTnode // ABSTRACT BASE CLASS { public: ParamNode :: ParamNode(int, int); virtual void unparse(int indent=0) =0; virtual void checkNames() =0; virtual void checkTypes() =0; virtual void emitCode() =0; }; // --------------- SUBCLASSES OF ParamNode --------------- class ParamValNode : public ParamNode { private: TypeNode * myType ; IdentifierNode * myIdentifier; public: ParamValNode :: ParamValNode(TypeNode*, IdentifierNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ParamArrayNode : public ParamNode { private: TypeNode * myType ; IdentifierNode * myIdentifier; public: ParamArrayNode::ParamArrayNode(TypeNode*, IdentifierNode*, int,int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); }; // --------------- SUBCLASSES OF ParamNode ---------------
class VarListNode : public ASTnode { private: VarListNode * myVarList; DeclNode * myDecl; public: VarListNode(VarListNode *, DeclNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class StmtListNode : public ASTnode { private: StmtListNode * myStmtList; StmtNode * myStmt; public: StmtListNode(StmtListNode *, StmtNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class StmtNode : public ASTnode // ABSTRACT BASE CLASS { public: StmtNode(int, int); virtual void unparse(int indent=0) =0; virtual void checkNames() =0; virtual void checkTypes() =0; virtual void emitCode() =0; }; // --------------- SUBCLASSES OF StmtNode --------------- class AssignNode : public StmtNode { private: TargetNode * myTarget; ExpressionNode * myExpression; public: AssignNode(TargetNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class IfNode : public StmtNode { private: ExpressionNode * myExpression; StmtNode * myThenStmt; StmtNode * myElseStmt; public: IfNode(ExpressionNode *, StmtNode *, StmtNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class WhileNode : public StmtNode { private: ExpressionNode * myExpression; StmtNode * myStmt; public: WhileNode(ExpressionNode *, StmtNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class BlockNode : public StmtNode { private: VarListNode * myVarList; StmtListNode * myStmtList; public: BlockNode( VarListNode*, StmtListNode*, int, int); virtual bool isBlock() { return true; } virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ReturnNode : public StmtNode { private: ExpressionNode * myReturnVal; public: ReturnNode(ExpressionNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class ProcCallNode : public StmtNode { private: IdentifierNode * myIdentifier; ArgListNode * myArgList ; public: ProcCallNode(IdentifierNode*, ArgListNode*, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class PrintNode : public StmtNode { private: PrintListNode * myPrintList; public: PrintNode(PrintListNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class CoutNode : public StmtNode { private: CoutListNode * myCoutList; public: CoutNode(CoutListNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames() {return;} virtual void checkTypes() {return;} virtual void emitCode() {return;} }; // --------------- SUBCLASSES OF StmtNode ---------------
class ArgListNode : public ASTnode { private: ArgListNode * myArgList ; ExpressionNode * myExpression;
public: ArgListNode(ArgListNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class PrintListNode : public ASTnode { private: PrintListNode * myPrintList; PrintItemNode * myPrintItem; public: PrintListNode(PrintListNode *, PrintItemNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class CoutListNode : public ASTnode { private: CoutListNode * myCoutList; PrintItemNode * myCoutItem; public: CoutListNode(CoutListNode *, PrintItemNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames() {return;} virtual void checkTypes() {return;} virtual void emitCode() {return;} };
class PrintItemNode : public ASTnode // ABSTRACT BASE CLASS { public: SymbolType myType; Symbol * mySymbolTableEntry; void setMySymbolTableEntry(Symbol * s) { mySymbolTableEntry = s; } PrintItemNode(int,int); virtual void unparse(int indent=0) =0; virtual void checkNames() =0; virtual void checkTypes() =0; virtual void emitCode() =0; };
class ExpressionNode : public PrintItemNode // ABSTRACT BASE CLASS { public: int myIntVal;
ExpressionNode(int,int); virtual void unparse(int indent=0) =0; virtual void checkNames() =0; virtual void checkTypes() =0; virtual void emitCode() =0; int emitRight() { return -1;} int emitLeft() { return -1;} ExpressionNode * getL() {return NULL;} ExpressionNode * getR() {return NULL;} virtual IdentifierNode * getID() {return NULL;} virtual void doSethiUllmanLabeling() =0; virtual void doSethiUllmanCodeGen() =0; int getOp() {return -1;} }; // --------------- SUBCLASSES OF ExpressionNode --------------- class OrNode : public ExpressionNode { private: ExpressionNode * myLeft ; ExpressionNode * myRight ; public: OrNode(ExpressionNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling() { return; } virtual void doSethiUllmanCodeGen() { return; } virtual bool isOr() { return true; } ExpressionNode * getL() {return myLeft;} ExpressionNode * getR() {return myRight;} };
class AndNode : public ExpressionNode { private: ExpressionNode * myLeft ; ExpressionNode * myRight ; public: AndNode(ExpressionNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling() { return; } virtual void doSethiUllmanCodeGen() { return; } virtual bool isAnd() { return true; } ExpressionNode * getL() {return myLeft;} ExpressionNode * getR() {return myRight;} };
class RelOpNode : public ExpressionNode { private: int myRelOp; ExpressionNode * myLeft ; ExpressionNode * myRight; public: RelOpNode(int, ExpressionNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling() { return; } virtual void doSethiUllmanCodeGen() { return; } int emitRight() { myRight->emitCode(); return myRight->Reg;} int emitLeft() { myLeft->emitCode(); return myLeft->Reg;} int getOp() { return myRelOp;} virtual bool isRel() { return true; } };
class ArithOpNode : public ExpressionNode { private: int myArithOp; ExpressionNode * myLeft ; ExpressionNode * myRight; public: ArithOpNode(int, ExpressionNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling(); virtual void doSethiUllmanCodeGen(); };
class FnCallNode : public ExpressionNode { private: IdentifierNode * myIdentifier; ArgListNode * myArgList ; public: FnCallNode(IdentifierNode *, ArgListNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling(); virtual void doSethiUllmanCodeGen(); IdentifierNode * getID() { return myIdentifier; } };
class TrueNode : public ExpressionNode { public: TrueNode(int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling() { return; } virtual void doSethiUllmanCodeGen() { return; } virtual bool isTrue() { return true; } };
class FalseNode : public ExpressionNode { public: FalseNode(int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling() { return; } virtual void doSethiUllmanCodeGen() { return; } virtual bool isFalse() { return true; } };
class NameVarNode : public ExpressionNode { private: IdentifierNode * myIdentifier; public: NameVarNode( IdentifierNode *, int, int); virtual bool isName() { return true;} virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling(); virtual void doSethiUllmanCodeGen(); virtual IdentifierNode * getID() {return myIdentifier;} };
class ArrayVarNode : public ExpressionNode { private: IdentifierNode * myIdentifier; ExpressionNode * myExpression; public: ArrayVarNode( IdentifierNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling(); virtual void doSethiUllmanCodeGen(); };
class IntLiteralNode : public ExpressionNode { public: IntLiteralNode(int, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); virtual void doSethiUllmanLabeling(); virtual void doSethiUllmanCodeGen(); }; // --------------- SUBCLASSES OF ExpressionNode ---------------
class TargetNode : public ASTnode { private: IdentifierNode * myIdentifier; ExpressionNode * myExpression; public: TargetNode(IdentifierNode *, ExpressionNode *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); IdentifierNode * getID() { return myIdentifier; } ExpressionNode * getExp() {return myExpression; } };
class StringLiteralNode : public PrintItemNode { private: string * myStringVal; public: StringLiteralNode(string *, int, int); virtual void unparse(int indent=0); virtual void checkNames(); virtual void checkTypes(); virtual void emitCode(); };
class NullNode : public ASTnode { public: NullNode() : ASTnode(0,0) {} virtual bool isNull() { return true; } virtual void unparse(int indentVal=0) { return; } virtual void checkNames() { return; }; virtual void checkTypes() { return; }; virtual void emitCode() {return;} };
extern ASTnode * astRoot;
#endif /* scanner.h */
#ifndef SCANNER_H_ #define SCANNER_H_
#include <stdio.h> #include <iostream> #include <string> using namespace std;
//input file pointer used by yylex(); defined in lex.yy.c extern FILE *yyin;
struct TokenType { int line; int column; int intVal; // used by integer token string *stringVal; // used by identifier and string tokens };
#endif // namecheck.cc
/* * build symbol table and check for declaration/use errors: * a) multiply declared identifiers * b) undeclared identifiers * find errors with the "main" function * compute offsets and other information */ using namespace std; #include <string> #include "symbol.h" #include "symboltable.h" #include "symlist.h" #include "ast.h" #include "message.h"
#define DEBUG 0 #define BUG(d) if(d)cerr<<whoami()<<endl;cerr.flush();
static SymTableList symList; static SymbolTable * ptrCurrentSymTab;
int declErrors = 0; int currentOffset = 0; int numParameters = 0; int localVarCount = 0; bool isGlobal = true;
void ProgramNode :: checkNames() { // Global Symbol Table symList.push( new SymbolTable ); ptrCurrentSymTab = symList.top(); // ... your code goes here myGlobalList->checkNames(); isGlobal = false; myFunctionList->checkNames(); string str = "main"; if( symList.lookUp(str) == NULL || symList.lookUp(str)->symbolKind != FnKind){ string msg = "function main is missing"; Error(0,0,msg); declErrors++; } symList.pop(); }
void GlobalListNode :: checkNames() { myGlobalList -> checkNames(); myDecl -> checkNames(); }
void FunctionListNode :: checkNames() { myFunctionList -> checkNames(); myFunctionDecl -> checkNames(); } // in file namecheck.cc, these are the only two nodes that // will record a data type in the member nodeType // this is done so that symbols entered in the symbol table // will have complete information // the next pass, implemented in file typecheck.cc, will // give other nodeType members data type information
void TypeIntNode :: checkNames() { nodeType = IntType; } void TypeBoolNode :: checkNames() { nodeType = BoolType; }
void VariableDeclNode :: checkNames() // int x; { myType -> checkNames(); // data type localVarCount++;
// name is being DECLARED // check for multiply-declared variable name
// strategy // we cannot recurse to the identifier node because // identifier node assumes the USAGE of a name // so, we must access identifier node information indirectly // by following the pointer to the identifier node
string varName = myIdentifier -> getMyStringVal(); // variable name Symbol * symbol = ptrCurrentSymTab -> Lookup(varName); // look it up
if (symbol != NULL) { // name is already in the symbol table // ERROR : variable is MULTIPLY_DECLARED string msg = varName + " is already declared"; Error(line,column,msg); declErrors++; } else{ // create symbol Symbol * s = new Symbol(varName); s->symbolType = myType->nodeType; s->symbolKind = VarKind; s->offset = currentOffset; if(isGlobal){ s->adr = Global; } else{ s->adr = Local; }
currentOffset += 4; s->arraySize = 0; ptrCurrentSymTab->Insert(s); myIdentifier->setMySymbolTableEntry(s); } }
void ArrayDeclNode :: checkNames() { myType -> checkNames();
string varName = myIdentifier -> getMyStringVal(); Symbol * symbol = ptrCurrentSymTab -> Lookup(varName);
if (symbol != NULL) { // name is already in the symbol table // ERROR : variable is MULTIPLY_DECLARED string msg = varName + " is already declared"; Error(line,column,msg); declErrors++; } else{ // create symbol Symbol * s = new Symbol(varName); s->symbolType = myType-> nodeType; s->symbolKind = ArrayKind; s->arraySize = myIntLit->myIntVal; if(isGlobal){ s->adr = Global; } else{ s->adr = Local; } localVarCount += s->arraySize; currentOffset += s->arraySize * 4; s->offset = currentOffset - 4; ptrCurrentSymTab->Insert(s); myIdentifier->setMySymbolTableEntry(s); } }
void FunctionDeclNode :: checkNames() { bool multipleDecl = false; currentOffset = 0; numParameters = 0; localVarCount = 0;
myType -> checkNames();
// your code goes here string varName = myIdentifier -> getMyStringVal(); // variable name Symbol * symbol = ptrCurrentSymTab -> Lookup(varName); // look it up
if (varName == "main") { if(myType->isNull() || myType->nodeType == BoolType){ string msg = varName + " does not return int"; Error(line,column,msg); declErrors++; } }
if (symbol != NULL) { // name is already in the symbol table // ERROR : function is MULTIPLY_DECLARED multipleDecl = true; string msg = varName + " is already declared"; Error(line,column,msg); declErrors++; } // create symbol mySymbolTableEntry = new Symbol(varName);
if(!multipleDecl) ptrCurrentSymTab->Insert(mySymbolTableEntry); // make new Symbol table and set it as the current one symList.push(new SymbolTable); ptrCurrentSymTab = symList.top();
myParameters -> checkNames(); currentOffset += 8;
if(numParameters != 0 && varName == "main"){ string msg = varName + " has a parameter"; Error(line, column, msg); declErrors++; } // in either case, keep going; name check body of function myVarList -> checkNames(); myStmtList -> checkNames();
symList.pop(); ptrCurrentSymTab = symList.top();
// if not multiply declared // insert values into Symbol then put it into the symbolTable if(! multipleDecl ){ if(!myType->isNull()){ mySymbolTableEntry->symbolType = myType->nodeType; } else{ mySymbolTableEntry->symbolType = VoidType; } mySymbolTableEntry->symbolKind = FnKind; mySymbolTableEntry->parameterCount = numParameters; mySymbolTableEntry->frameSize = (numParameters + localVarCount + 2) * 4; mySymbolTableEntry->localVarCount = localVarCount; //ptrCurrentSymTab->Insert(mySymbolTableEntry); } }
void ParametersNode :: checkNames() { myParamList->checkNames(); }
void ParamListNode :: checkNames() { myParamList->checkNames(); myParam ->checkNames(); }
void ArgListNode :: checkNames() { myArgList ->checkNames(); myExpression->checkNames(); }
void ParamValNode :: checkNames() { myType -> checkNames(); numParameters++;
string varName = myIdentifier -> getMyStringVal(); // variable name Symbol * symbol = ptrCurrentSymTab -> Lookup(varName); // look it up
if (symbol != NULL) { // name is already in the symbol table // ERROR : variable is MULTIPLY_DECLARED string msg = varName + " is already declared"; Error(line,column,msg); declErrors++; } else{ // create symbol Symbol * s = new Symbol(varName); s->symbolType = myType -> nodeType; s->symbolKind = ValParamKind; s->offset = currentOffset; currentOffset += 4; s->arraySize = 0; s->adr = Local; ptrCurrentSymTab->Insert(s); myIdentifier->setMySymbolTableEntry(s); } }
void ParamArrayNode :: checkNames() { myType -> checkNames(); numParameters++;
string varName = myIdentifier -> getMyStringVal(); // variable name Symbol * symbol = ptrCurrentSymTab -> Lookup(varName); // look it up
if (symbol != NULL) { // name is already in the symbol table // ERROR : variable is MULTIPLY_DECLARED string msg = varName + " is already declared"; Error(line,column,msg); declErrors++; } else{ // create symbol Symbol * s = new Symbol(varName); s->symbolType = myType -> nodeType; s->symbolKind = ArrayParamKind; s->offset = currentOffset; s->adr = Local; currentOffset += 4; ptrCurrentSymTab->Insert(s); myIdentifier->setMySymbolTableEntry(s); } }
void VarListNode :: checkNames() { myVarList->checkNames(); myDecl ->checkNames(); }
void StmtListNode :: checkNames() { myStmtList -> checkNames(); myStmt -> checkNames(); }
void AssignNode :: checkNames() { myTarget -> checkNames(); myExpression -> checkNames(); }
void IfNode :: checkNames() { myExpression-> checkNames(); myThenStmt -> checkNames(); myElseStmt -> checkNames(); }
void WhileNode :: checkNames() { myExpression -> checkNames(); myStmt -> checkNames(); }
void BlockNode :: checkNames() { // make new Symbol table and set it as the current one symList.push(new SymbolTable); ptrCurrentSymTab = symList.top();
// check the children's names myVarList -> checkNames(); myStmtList -> checkNames();
// now that you're leaving take the symboltable off the stack symList.pop(); ptrCurrentSymTab = symList.top(); }
void ReturnNode :: checkNames() { myReturnVal->checkNames(); }
void ProcCallNode :: checkNames() { myIdentifier -> checkNames(); myArgList -> checkNames(); }
void PrintNode :: checkNames() { myPrintList -> checkNames(); }
void PrintListNode :: checkNames() { myPrintList-> checkNames(); myPrintItem-> checkNames(); }
void OrNode :: checkNames() { myLeft -> checkNames(); myRight -> checkNames(); }
void AndNode :: checkNames() { myLeft -> checkNames(); myRight -> checkNames(); }
void RelOpNode :: checkNames() { myLeft -> checkNames(); myRight -> checkNames(); }
void ArithOpNode :: checkNames() { myLeft -> checkNames(); myRight -> checkNames(); }
void TrueNode :: checkNames() { return; }
void FalseNode :: checkNames() { return; }
void NameVarNode :: checkNames() { myIdentifier-> checkNames(); }
void ArrayVarNode :: checkNames() { myIdentifier->checkNames(); myExpression->checkNames(); }
void FnCallNode :: checkNames() { myIdentifier->checkNames(); myArgList ->checkNames(); }
void IntLiteralNode :: checkNames() { return; }
void TargetNode :: checkNames() { myIdentifier->checkNames(); myExpression->checkNames(); }
void StringLiteralNode :: checkNames() { return; }
void IdentifierNode :: checkNames() // name USAGE { // getting here recursively means that a // name is being USED; check for undefined name string varName = getMyStringVal(); Symbol * symbol = symList.lookUp(varName);
if (symbol == NULL){ string msg = varName + " is undeclared"; Error(this->line, this->column, msg); declErrors ++; symbol = new Symbol(varName); symbol->symbolType = ErrorType; ptrCurrentSymTab -> Insert(symbol); } setMySymbolTableEntry(symbol); } // codegen.cc OO
using namespace std; #include "ast.h" #include "scanner.h" #include "y.tab.h" #include "message.h" #include "symlist.h" #include "symboltable.h" #include "int2str.h" #include "emit.h" #include <list> #include <map>
#define BUG(m) // cerr<<m<<endl #define EMIT(m) // emitComment(m)
#define NUMERIC false // Turn on numeric style coding / turn off control flow
void emitPrintString(); void emitPrintInt ( int reg ); void emitPrintBool( int reg );
void emitL ( string label, string opcode="", string arg1="", string arg2="", string arg3="" ); void emitProgramHeader(); void emitProgramFooter(); void emitFunctionPrologue( string fn, int frameSize, int localVarCount ); void emitFunctionEpilogue( string fn, int parameterCount, int frameSize ); void declareGlobalVar ( string name ); void declareGlobalArray( string name, int size ); void emitStringDefinition( string label, string String );
extern ofstream asmFile; extern bool SethiUllmanFlag; static string currentFunctionName(""); static SymbolPtr currentFunctionSym = NULL; map<string, string> l; //// static list<ExpressionNode *> * argumentList = NULL; // David Haltinner ===========================================================
string setRelOp( int kind ) { string s;
switch (kind) { case LT : s = "slt"; break; case LEQ: s = "sle"; break; case GT : s = "sgt"; break; case GEQ: s = "sge"; break; case EQ : s = "seq"; break; case NEQ: s = "sne"; break; default : assert(0); break; } return s; }
string binaryOp( int kind ) { string s;
switch (kind) { case PLUS : s = "add" ; break; case MINUS: s = "sub" ; break; case TIMES: s = "mulo"; break; case SLASH: s = "div" ; break; default : assert(0) ; break; } return s; }
//*************storeIntoTarget is complete**************** void storeIntoTarget( ExpressionNode *astR, TargetNode *astL ) { int reg = astR->Reg; Symbol *ptrL = astL->getID()->getSymbol();
if(ptrL->adr == Global && ptrL->symbolKind == VarKind){ emit( "sw", "$t"+IntToStr(reg), ptrL->symbolName+".v" ); } else if( ptrL->adr == Global && ptrL->symbolKind == ArrayKind){ int regEx = astL->Reg; string regStr = "0($t"+IntToStr(regEx)+")"; emit("sw", "$t"+IntToStr(reg), regStr); freeReg(regEx); } else if( ptrL->adr == Local && ( ptrL->symbolKind == VarKind || ptrL->symbolKind == ValParamKind )){ int o = ptrL->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; emit("sw", "$t"+IntToStr(reg), off+"($fp)"); } else if( ptrL->adr == Local && ptrL->symbolKind == ArrayKind){ int regEx = astL->Reg; int o = ptrL->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; string regStr = off+"($t"+IntToStr(regEx)+")"; emit("sw", "$t"+IntToStr(reg), regStr); freeReg(regEx); } else if( ptrL->adr == Local && ptrL->symbolKind == ArrayParamKind){ int regEx = astL->Reg; string regStr = "0($t"+IntToStr(regEx)+")"; emit("sw", "$t"+IntToStr(reg), regStr); freeReg(regEx); } }
void evaluateCondition( ExpressionNode *ast, string t, string f ) { if(ast->isAnd()) { string right(NextLabel()); evaluateCondition(((AndNode *)ast)->getL(), right, f); emitLabel(right); evaluateCondition(((AndNode *)ast)->getR(), t, f); } else if(ast->isOr()) { string next(NextLabel()); evaluateCondition(((OrNode *)ast)->getL(), t, next); emitLabel(next); evaluateCondition(((OrNode *)ast)->getR(), t, f); } else if(ast->isRel()){ string op; int kind = ((RelOpNode *)ast)->getOp(); int leftReg = ((RelOpNode *)ast)->emitLeft(); int rightReg = ((RelOpNode *)ast)->emitRight(); string left = "$t" + IntToStr(leftReg); string right = "$t" + IntToStr(rightReg); switch (kind) { case LT : op = "blt"; break; case LEQ: op = "ble"; break; case GT : op = "bgt"; break; case GEQ: op = "bge"; break; case EQ : op = "beq"; break; case NEQ: op = "bne"; break; default : assert(0); break; } emit(op, left, right, t); emit("j", f);
freeReg(leftReg); freeReg(rightReg); } else if(ast -> isTrue()){ emit("j", t); } else if(ast -> isFalse()){ emit("j", f); } else{ ast->emitCode(); emit( "beqz", ast->Reg, f ); emit( "j", t ); freeReg(ast->Reg); } } // David Haltinner ===========================================================
void ProgramNode :: emitCode() { emitProgramHeader(); myGlobalList -> emitCode(); myFunctionList -> emitCode(); emitProgramFooter(); }
void GlobalListNode :: emitCode() { myGlobalList -> emitCode(); myDecl -> emitCode(); }
void FunctionListNode :: emitCode() { myFunctionList -> emitCode(); myFunctionDecl -> emitCode(); }
void ParametersNode :: emitCode() { myParamList -> emitCode(); }
void ParamListNode :: emitCode() { myParamList -> emitCode(); myParam -> emitCode(); }
void VarListNode:: emitCode() { myVarList -> emitCode(); myDecl -> emitCode(); }
void StmtListNode :: emitCode() { myStmtList -> emitCode(); myStmt -> emitCode(); }
void PrintNode :: emitCode() { myPrintList -> emitCode(); }
void TypeIntNode :: emitCode() {return;} void TypeBoolNode :: emitCode() {return;}
void BlockNode :: emitCode() { myVarList->emitCode(); myStmtList->emitCode(); }
void ParamValNode :: emitCode() { return; }
void ParamArrayNode :: emitCode() { return; }
void ArgListNode :: emitCode() { myArgList->emitCode(); myExpression->emitCode(); int reg = myExpression->Reg; emit("subu", "$sp", "$sp", IntToStr(4), "# argument"); emit("sw", "$t"+IntToStr(reg), "($sp)"); freeReg(reg); }
// David Haltinner ===========================================================
void VariableDeclNode :: emitCode() // int x; { //zinc always allocates 4 bytes for int and bool //so, do not need to visit myType
if(myIdentifier->getSymbol()->adr == Global){ declareGlobalVar( myIdentifier->getMyStringVal()+".v" ); } }
void ArrayDeclNode :: emitCode() { Symbol * s = myIdentifier->getSymbol();
if(s->adr == Global){ declareGlobalArray( s->symbolName+".v" , s->arraySize * 4 ); } }
void FunctionDeclNode :: emitCode() { currentFunctionName = myIdentifier -> getMyStringVal(); currentFunctionSym = mySymbolTableEntry; emitFunctionPrologue( currentFunctionName, currentFunctionSym->frameSize, currentFunctionSym->localVarCount);
myParameters -> emitCode(); myVarList -> emitCode(); myStmtList -> emitCode();
emitFunctionEpilogue ( currentFunctionName, currentFunctionSym->frameSize, currentFunctionSym->parameterCount );
if (currentFunctionName!="main") emit( "jr", "$ra" ); // return else{ emitEmptyLine(); emit( "li", "$v0", 10 ); // halt emit( "syscall", "\t\t# program exit" ); } }
// David Haltinner ===========================================================
void PrintListNode :: emitCode() { myPrintList -> emitCode(); //emitComment( "print" );
myPrintItem -> emitCode(); // string literal or expression
switch( myPrintItem->nodeType ) {
case StringType: emitPrintString(); break; case IntType: emitPrintInt( myPrintItem->Reg ); freeReg(myPrintItem->Reg); break; case BoolType: if(NUMERIC){ emitPrintBool( myPrintItem->Reg ); freeReg(myPrintItem->Reg); } else{ string endLabel = NextLabel(); emit( "la", "$a0", ".false" ); emit( "beqz", myPrintItem->Reg, endLabel); emit( "la", "$a0", ".true" ); emitLabel(endLabel); emitPrintString(); freeReg(myPrintItem->Reg); } break; default: assert(0); break; } }
void AssignNode :: emitCode() { emitComment( "assignment" );
myExpression -> emitCode(); // translate RHS (expression) myTarget -> emitCode(); // translate LHS (targetNode)
storeIntoTarget( myExpression, myTarget );
freeReg( myExpression->Reg ); freeReg( myTarget ->Reg ); }
void IfNode :: emitCode() { emitComment("if"); string trueLabel ( NextLabel() ); string falseLabel( NextLabel() ); string endifLabel( NextLabel() );
if(NUMERIC){ myExpression -> emitCode(); emit( "beqz", myExpression->Reg, falseLabel ); freeReg(myExpression->Reg); } else{ evaluateCondition(myExpression, trueLabel, falseLabel); }
emitLabel(trueLabel); emitComment("then"); myThenStmt -> emitCode(); // then clause emit( "j", endifLabel );
emitLabel(falseLabel); emitComment("else"); myElseStmt -> emitCode(); // else clause
emitLabel(endifLabel); }
void WhileNode :: emitCode() { if(NUMERIC){ string compareLabel( NextLabel()); string trueLabel( NextLabel());
emitComment("while"); emit("j", compareLabel); emitLabel(trueLabel); myStmt -> emitCode(); emitLabel(compareLabel); myExpression->emitCode(); emit("bnez", myExpression->Reg, trueLabel); freeReg(myExpression->Reg); } else{ string compareLabel( NextLabel()); string trueLabel( NextLabel()); string falseLabel( NextLabel() );
emitComment("while"); emit("j", compareLabel); emitLabel(trueLabel); myStmt -> emitCode(); emitLabel(compareLabel); evaluateCondition(myExpression, trueLabel, falseLabel); emitLabel(falseLabel); } }
void ProcCallNode :: emitCode() { Symbol * s = myIdentifier->getSymbol(); emitComment("call"); saveRegs(); //throw args on stack myArgList->emitCode(); emit("jal", s->symbolName+".f"); restoreRegs(); }
void ReturnNode :: emitCode() { emitEmptyLine(); emitComment("return");
if( !myReturnVal->isNull()) { myReturnVal -> emitCode(); emit( "move", "$v0", "$t"+IntToStr(myReturnVal->Reg) ); freeReg( myReturnVal->Reg ); }
if(currentFunctionName=="main") emit( "j", currentFunctionName+".." ); else emit( "j", currentFunctionName+".f.." ); }
// David Haltinner ===========================================================
void OrNode :: emitCode() { if(NUMERIC){ string falseLabel( NextLabel() ); string endLabel( NextLabel() );
myLeft->emitCode(); string regL = "$t"+IntToStr(myLeft->Reg); emit("beqz", regL, falseLabel ); emit("j", endLabel); emitLabel(falseLabel);
freeReg(myLeft->Reg); myRight->emitCode(); string regR = "$t"+IntToStr(myRight->Reg); emitLabel(endLabel); Reg = myRight->Reg; } else{ // THIS IS CONTROL FLOW CODE --------------------- string falseLabel = NextLabel(); string trueLabel = NextLabel(); string endLabel = NextLabel(); evaluateCondition(this, trueLabel, falseLabel); emitLabel(trueLabel); Reg = getReg(); emit( "li", Reg, 1 ); emit( "j", endLabel); emitLabel(falseLabel); emit( "li", Reg, 0 ); emitLabel(endLabel); } }
void AndNode :: emitCode() { if(NUMERIC){ string endLabel( NextLabel() ); myLeft->emitCode(); string regL = "$t"+IntToStr(myLeft->Reg); emit("beqz", regL, endLabel); freeReg(myLeft->Reg); myRight->emitCode(); Reg = myRight->Reg; emitLabel(endLabel); } else{ // THIS IS CONTROL FLOW CODE --------------------- string falseLabel = NextLabel(); string trueLabel = NextLabel(); string endLabel = NextLabel(); evaluateCondition(this, trueLabel, falseLabel); emitLabel(trueLabel); Reg = getReg(); emit( "li", Reg, 1 ); emit( "j", endLabel); emitLabel(falseLabel); emit( "li", Reg, 0 ); emitLabel(endLabel); } }
void RelOpNode :: emitCode() { if(NUMERIC){ // THIS IS NUMERIC CODE ----------- string op = setRelOp(myRelOp); int regL, regR; myLeft->emitCode(); myRight->emitCode(); regL = myLeft-> Reg; regR = myRight-> Reg; emit(op, "$t"+IntToStr(regL), "$t"+IntToStr(regL), "$t"+IntToStr(regR)); Reg = regL; freeReg(regR); // ------------------------------- } else{ // THIS IS CONTROL FLOW CODE--------------------- string trueLabel = NextLabel(); string falseLabel = NextLabel(); string endLabel = NextLabel(); evaluateCondition(this, trueLabel, falseLabel); // Might need to load a 1 or a 0 into Reg for this to work emitLabel(trueLabel); Reg = getReg(); emit( "li", Reg, 1 ); emit( "j", endLabel); emitLabel(falseLabel); emit( "li", Reg, 0 ); emitLabel(endLabel); } }
void ArithOpNode :: emitCode() { // ***************** ArithOpNode is finished ****************** if(SethiUllmanFlag){ doSethiUllmanLabeling(); doSethiUllmanCodeGen(); } else{ string op = binaryOp(myArithOp); int regL, regR; myLeft->emitCode(); myRight->emitCode(); regL = myLeft->Reg; regR = myRight->Reg; emit(op, "$t"+IntToStr(regL), "$t"+IntToStr(regL), "$t"+IntToStr(regR)); Reg = regL; freeReg(regR); } }
// David Haltinner ===========================================================
void FnCallNode :: emitCode() { emitComment("call"); saveRegs(); //save args if any myArgList->emitCode(); emit("jal", myIdentifier->getMyStringVal()+".f"); Reg=getReg(); emitComment("function value"); emit("move", Reg, "$v0"); }
void NameVarNode :: emitCode() { Reg = getReg(); if(myIdentifier->getSymbol()->adr == Global && myIdentifier->getSymbol()->symbolKind == VarKind){ string name = myIdentifier->getMyStringVal(); emit( "lw", Reg, name+".v" ); // SUFFIX(variable) } else if(myIdentifier->getSymbol()->symbolKind == ArrayKind && myIdentifier->getSymbol()->adr == Global){ string name = myIdentifier->getMyStringVal(); emit("la", Reg, name+".v" ); } else if(myIdentifier->getSymbol()->symbolKind == ArrayKind || myIdentifier->getSymbol()->symbolKind == ArrayParamKind ){ Symbol * s = myIdentifier->getSymbol(); int o = s->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; emit( "addi", "$t"+IntToStr(Reg), "$fp", off); } else if(myIdentifier->getSymbol()->symbolKind == VarKind || myIdentifier->getSymbol()->symbolKind == ValParamKind){ Symbol * s = myIdentifier->getSymbol(); int o = s->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; string regStr = off+ "($fp)"; emit( "lw", "$t"+IntToStr(Reg), regStr ); } else{ assert(0); } }
void ArrayVarNode :: emitCode() { //need for all 3 myExpression->emitCode(); int RegFromExp=myExpression->Reg; emit("sll", "$t"+IntToStr(RegFromExp), "$t"+IntToStr(RegFromExp), "2");
//global only if(myIdentifier->getSymbol()->adr == Global){ Reg=getReg(); string str(myIdentifier->getMyStringVal()); emit("la","$t"+IntToStr(Reg), str+".v"); emit("add","$t"+IntToStr(RegFromExp), "$t"+IntToStr(RegFromExp) , "$t"+IntToStr(Reg)); emit("lw", "$t"+IntToStr(RegFromExp), "($t"+IntToStr(RegFromExp)+")"); freeReg(Reg); //am i really done with it? Reg = RegFromExp; } else if(myIdentifier->getSymbol()->adr == Local && myIdentifier->getSymbol()->symbolKind == ArrayKind){ //local Symbol * s = myIdentifier->getSymbol(); emit("add", "$t"+IntToStr(RegFromExp), "$fp", "$t"+IntToStr(RegFromExp)); int o = s->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; emit("lw", "$t"+IntToStr(RegFromExp), off+"($t"+IntToStr(RegFromExp)+")"); //freeReg(Reg); Reg = RegFromExp; } else{ //Param Reg=getReg(); Symbol * s = myIdentifier->getSymbol(); int o = s->offset; string off = IntToStr(o); if(o > 0) off= "-"+off; string regStr = off+ "($fp)"; emit("lw", "$t"+IntToStr(Reg), regStr); emit("add", "$t"+IntToStr(RegFromExp), "$t"+IntToStr(Reg), "$t"+IntToStr(RegFromExp)); emit("lw", "$t"+IntToStr(RegFromExp), "0($t"+IntToStr(RegFromExp)+")"); freeReg(Reg); //ami really done with it though? Reg = RegFromExp; } }
void IntLiteralNode :: emitCode() { Reg = getReg(); emit( "li", Reg, myIntVal ); }
void TrueNode :: emitCode() { Reg = getReg(); emit( "li", Reg, 1 ); }
void FalseNode :: emitCode() { Reg = getReg(); emit( "li", Reg, 0 ); }
// David Haltinner ===========================================================
void TargetNode :: emitCode() { // Explicitly tell the target it is the fp // since all local vars are offset from fp // and globals don't use registers Reg = 30; Symbol *ptrL = getID()->getSymbol();
if(ptrL->adr == Global && ptrL->symbolKind == VarKind){ return; } else if( ptrL->adr == Global && ptrL->symbolKind == ArrayKind){ getExp()->emitCode(); int regEx = getExp()->Reg; int global = getReg(); string regStr = "$t"+IntToStr(regEx); emit("sll", regStr, regStr, IntToStr(2)); emit("la", "$t"+IntToStr(global), ptrL->symbolName+".v"); emit("add", regStr, regStr, "$t"+IntToStr(global)); freeReg(global); Reg = regEx; } else if( ptrL->adr == Local && ( ptrL->symbolKind == VarKind || ptrL->symbolKind == ValParamKind )){ return; } else if( ptrL->adr == Local && ptrL->symbolKind == ArrayKind){ getExp()->emitCode(); int regEx = getExp()->Reg; string regStr = "$t"+IntToStr(regEx); emit("sll", regStr, regStr, IntToStr(2)); emit("add", regStr, "$fp", regStr); Reg = regEx; } else if( ptrL->adr == Local && ptrL->symbolKind == ArrayParamKind){ getExp()->emitCode(); int reg = getReg(); int regEx = getExp()->Reg; int o = ptrL->offset; string regS = "$t"+IntToStr(reg); string regStr = "$t"+IntToStr(regEx); string off = IntToStr(o)+"($fp)"; if(o != 0) off = "-" + off; emit("sll", regStr, regStr, IntToStr(2)); emit("lw", regS, off); emit("add", regStr, regS, regStr); Reg = regEx; freeReg(reg); } }
void StringLiteralNode :: emitCode() { string label;
if ( *myStringVal == "\"\\n\"" ) label = ".nl"; else{ if(l.find((*myStringVal)) == l.end()){ label = NextLabel(); emitStringDefinition( label, *myStringVal ); l[(*myStringVal)] = label; } else{ label = l[*myStringVal]; } }
// load into $a0 so it can be printed; can do it here // because a string literal is only used in print statements emit( "la", "$a0", label ); }
// David Haltinner =========================================================== // // H I G H E R - L E V E L E M I T R O U T I N E S // // David Haltinner ===========================================================
void emitPrintString() { emit( "li", "$v0", 4 ); emit( "syscall", "\t\t# print_string" ); }
void emitPrintInt( int reg ) { emit( "move", "$a0", "$t"+IntToStr(reg) ); emit( "li" , "$v0", 1 ); emit( "syscall", "\t\t# print_int" ); }
void emitPrintBool( int reg ) { string falseLabel = NextLabel(); string endLabel = NextLabel(); emit( "beqz", "$t"+IntToStr(reg), falseLabel); emit( "la", "$a0", ".true" ); emit( "j", endLabel); emitLabel(falseLabel); emit( "la", "$a0", ".false" ); emitLabel(endLabel); emit( "li", "$v0", 4); emit( "syscall", "\t\t# print_bool" ); }
// David Haltinner ===========================================================
void emitL (string label, string opcode,string arg1,string arg2,string arg3) { asmFile << label << ":\t" ; if ( opcode=="" ) {asmFile<<endl; return;} else asmFile << opcode; if ( arg1 =="" ) {asmFile<<endl; return;} else asmFile << arg1; if ( arg2 =="" ) {asmFile<<endl; return;} else asmFile << arg2; if ( arg3 =="" ) {asmFile<<endl; return;} else asmFile << arg3; asmFile<<endl; asmFile.flush(); }
// David Haltinner ===========================================================
void emitProgramHeader() { emit ( ".data" ); emitL( ".true" , ".asciiz\t", "\"true\"" ); emitL( ".false", ".asciiz\t", "\"false\"" ); emitL( ".nl" , ".asciiz\t", "\"\\n\"" ); emit ( ".text" ); emit ( ".globl main" ); emitEmptyLine(); }
void emitProgramFooter() { asmFile.close(); }
// David Haltinner ===========================================================
void emitFunctionPrologue( string fn, int frameSize, int localVarCount ) { emitEmptyLine(); if(fn!="main") emitLabel( fn+".f" ); else emitLabel( fn ); emitBlockComment( "PROLOGUE" );
string space( IntToStr(localVarCount*4+8) ); if (localVarCount == 0) emit( "subu", "$sp", "$sp", "8" , "# registers ra & fp" ); else emit( "subu", "$sp", "$sp", space, "# ra, fp & locals" ); emit( "sw" , "$ra", IntToStr(localVarCount*4+4)+"($sp)" ); emit( "sw" , "$fp", IntToStr(localVarCount*4 )+"($sp)" );
emit( "addu", "$fp", "$sp", IntToStr(frameSize-4), "# set new fp" ); }
void emitFunctionEpilogue( string fn, int frameSize, int parameterCount ) { emitEmptyLine(); if(fn!="main") emitLabel( fn+".f.." ); else emitLabel( fn+".." ); emitBlockComment( "EPILOGUE" );
emitOffset( "lw" , "$ra", parameterCount*4, "$fp", "# restore ra" ); emitOffset( "lw" , "$fp", parameterCount*4+4, "$fp", "# restore fp" );
emit( "addu", "$sp", "$sp", IntToStr(frameSize), "# Pop" ); }
// David Haltinner ===========================================================
void declareGlobalVar( string name ) { emit ( ".data" ); emit ( ".align 2" ); emitL( name, ".space 4" ); //always 4 for simplicity emit ( ".text" ); emitEmptyLine(); }
void declareGlobalArray( string name, int size ) { emit ( ".data" ); emit ( ".align 2" ); emitL( name, ".space "+IntToStr(size) ); emit ( ".text" ); emitEmptyLine(); }
void emitStringDefinition( string label, string String ) { emitEmptyLine(); emit ( ".data" ); emitL( label, ".asciiz\t ", String ); emit ( ".text" ); emitEmptyLine(); }
// David Haltinner =========================================================== // // S E T H I - U L L M A N // // David Haltinner ===========================================================
void ArithOpNode :: doSethiUllmanLabeling() { myLeft->doSethiUllmanLabeling(); myRight->doSethiUllmanLabeling(); if(myLeft->lbl == myRight->lbl){ lbl = myLeft->lbl+1; } else if(myLeft->lbl > myRight->lbl){ lbl = myLeft->lbl; } else{ lbl = myRight->lbl; } }
void IntLiteralNode :: doSethiUllmanLabeling() { lbl = 1; } void NameVarNode :: doSethiUllmanLabeling() { lbl = 1; } void ArrayVarNode :: doSethiUllmanLabeling() { lbl = 1; } void FnCallNode :: doSethiUllmanLabeling() { lbl = 1; }
void ArithOpNode :: doSethiUllmanCodeGen() { string op = binaryOp(myArithOp); int regL, regR;
if(myLeft->lbl > myRight->lbl){ myLeft->doSethiUllmanCodeGen(); myRight->doSethiUllmanCodeGen(); } if(myRight->lbl >= myLeft->lbl){ myRight->doSethiUllmanCodeGen(); myLeft->doSethiUllmanCodeGen(); }
regL = myLeft->Reg; regR = myRight->Reg; emit(op, "$t"+IntToStr(regL), "$t"+IntToStr(regL), "$t"+IntToStr(regR)); Reg = regL; freeReg(regR); }
void IntLiteralNode :: doSethiUllmanCodeGen() { emitCode(); } void NameVarNode :: doSethiUllmanCodeGen() { emitCode(); } void ArrayVarNode :: doSethiUllmanCodeGen() { emitCode(); } void FnCallNode :: doSethiUllmanCodeGen() { emitCode(); } int j(int x, int y){ //tests function call, arithmatic operations, as well as print statements it should return 7 as the answer int z; z = 3; z = x + y + z; print(z);print("\n"); return z; } int main(){ //tests the main function, calls a function, and prints. Should print 7. int y; int x; x = 2; y = j(2, x); print(y);print("\n"); return 1; } int main(){ //tests printing and arithmatic operations plus, multiply, and divide. Should print "x is 28" followed by a new line int x; x = 2 + 3 * 5 / 4 * 8 + 2; print("x is ", x, "\n"); return x; } /* tokens.lex */
/* * char *yytext contains the lexeme of each token * int yyleng is the length of the lexeme */
/* * section 1: names for regular expressions */
delimiter [ \t] newline [\n] whitespace {delimiter}+ digit [0-9] letter [a-zA-Z] integer {digit}+ other . identifier ({letter}|_)({letter}|{digit}|_)* comment1 "//"[^\n]*[\n] comment2 "//"[^\n]* mgcStrLt \"([^\"\n]|\\[^\n])*\" strLt \"([^\"\000-\037\177\n\\]|\\[^\000-\037\177\n])*\" rnAwyStrLt \"([^\"\000-\037\177\n]|\\[^\000-\037\177\n])*
%{ /* * stuff here is copied directly into lex.yy.c * as info outside of (above) yylex() */ using namespace std; #include "ast.h" #include "message.h" #include "scanner.h" #include "y.tab.h" // token definitions created by bison #include "int2str.h"
#define MAXINT 2147483647
static int line = 1; /* current line number */ static int column = 1; /* current column number */
/* forward */ void setPosition(); void doIntConvert(); int idScreener(string *lexeme);
%}
%%
%{ /* * section 2: rules for regular expressions */ %}
{whitespace} { column += yyleng; } {newline} { line++; column=1; }
"=" { setPosition(); return ASSIGN; } "," { setPosition(); return COMMA; } ";" { setPosition(); return SEMICOLON; } "(" { setPosition(); return LPAREN; } ")" { setPosition(); return RPAREN; } "{" { setPosition(); return LBRACE; } "}" { setPosition(); return RBRACE; } "[" { setPosition(); return LBRACKET; } "]" { setPosition(); return RBRACKET; } "+" { setPosition(); return PLUS; } "-" { setPosition(); return MINUS; } "*" { setPosition(); return TIMES; } "/" { setPosition(); return SLASH; } ">" { setPosition(); return GT; } "<" { setPosition(); return LT; } "==" { setPosition(); return EQ; } "!=" { setPosition(); return NEQ; } ">=" { setPosition(); return GEQ; } "<=" { setPosition(); return LEQ; } "&&" { setPosition(); return AND; } "||" { setPosition(); return OR; } "<<" { setPosition(); return AARROW; }
{integer} { doIntConvert(); setPosition(); return INTLITERAL; }
{identifier} { setPosition(); string *lexeme = new string(yytext); yylval.t.stringVal = lexeme; return idScreener(lexeme); }
{strLt} { setPosition(); yylval.t.stringVal = new string(yytext); return STRINGLITERAL; }
{rnAwyStrLt} { string c(yytext); string msg = "unterminated string "; msg = msg + c; Warn(line,column, msg); column += yyleng; }
{mgcStrLt} { string c(yytext); string msg = "magic string "; msg = msg + c; Warn(line,column, msg); column += yyleng; }
{comment1} { line++; column = 1; } {comment2} { line++; column = 1; }
{other} { int bad = yytext[0]; string c(IntToStr(bad)); string msg = "yylex(): ignoring illegal character "; msg = msg + " (ascii code " + c + ")"; Warn(line,column, msg); column += yyleng; }
%%
/* * section 3: functions used in section 2 */
void setPosition() { yylval.t.line = line ; yylval.t.column = column; column += yyleng; }
int idScreener(string *lexeme) { if ( *lexeme == "print" ) return PRINT; if ( *lexeme == "cout" ) return COUT; else if ( *lexeme == "int" ) return INT; else if ( *lexeme == "void" ) return VOID; else if ( *lexeme == "if" ) return IF; else if ( *lexeme == "else" ) return ELSE; else if ( *lexeme == "while" ) return WHILE; else if ( *lexeme == "bool" ) return BOOL; else if ( *lexeme == "true" ) return TRUE; else if ( *lexeme == "false" ) return FALSE; else if ( *lexeme == "return" ) return RETURN; else return ID; }
void doIntConvert() { if(atof(yytext) > MAXINT){ yylval.t.intVal = MAXINT; string msg = "int literal exceeds MAXINT;\n\tsubstituting MAXINT"; Warn(line, column, msg); } else{ yylval.t.intVal = atoi(yytext); } } // unparse.cc
#include <assert.h> #include <iomanip> #include <typeinfo> #include "ast.h" #include "scanner.h" #include "y.tab.h"
void indent(int indentVal=0) { for (int i=1; i<=indentVal; i++) cout << " "; // 3 spaces }
//============================================================
void ProgramNode :: unparse( int indentVal ) { indent(indentVal+1); cout<<"functionName<parameters:locals:frameSize>;"<<endl; indent(indentVal+1); cout<<"variableName<offset>\n"; myGlobalList -> unparse(); myFunctionList -> unparse(); }
void GlobalListNode :: unparse( int indentVal ) { myGlobalList -> unparse(); myDecl -> unparse(); }
void TypeIntNode :: unparse( int indentVal ) { cout << "int "; }
void TypeBoolNode :: unparse( int indentVal ) { cout << "bool "; }
void VariableDeclNode :: unparse( int indentVal ) { doLineNum(); indent(indentVal); myType -> unparse(indentVal); myIdentifier -> unparse(indentVal); if(myIdentifier->getSymbol()->adr == Local){ cout<<" <" << myIdentifier->getSymbol()->offset << "> "; } cout << ";" << endl; }
void FunctionDeclNode :: unparse( int indentVal ) { doLineNum(); myType -> unparse(indentVal); if(myType->isNull()) { indent(indentVal); cout<<"void "; } myIdentifier -> unparse(indentVal); cout<<" <"<<mySymbolTableEntry->parameterCount<<":" <<mySymbolTableEntry->localVarCount<<":"<<mySymbolTableEntry->frameSize <<"> ("; myParameters -> unparse(indentVal); cout << ")" << endl;
doLineNum(); cout << "{" << endl; myVarList->unparse(indentVal+1); myStmtList -> unparse(indentVal+1); doLineNum(); cout << "}" << endl; }
void ParametersNode:: unparse(int indentVal){ myParamList -> unparse(indentVal); }
void ParamListNode:: unparse(int indentVal){ if(!myParamList->isNull()){ myParamList->unparse(indentVal); cout<< ", "; } cout<<endl; doLineNum(); indent(indentVal+2); myParam->unparse(indentVal); }
void ParamValNode::unparse(int indentVal){ myType->unparse(indentVal); myIdentifier->unparse(indentVal); cout << " <" << myIdentifier->getSymbol()->offset << "> "; }
void ParamArrayNode::unparse(int indentVal){ myType->unparse(indentVal); myIdentifier->unparse(indentVal); cout<< " <" << myIdentifier->getSymbol()->offset << "> " << "[]"; }
void ArgListNode :: unparse(int indentVal){ if (!myArgList->isNull()) { myArgList->unparse(indentVal); cout<<", "; } myExpression->unparse(indentVal); }
void OrNode :: unparse(int indentVal){ if(!myLeft->isNull()){ cout << "("; myLeft->unparse(indentVal); cout <<" || "; myRight->unparse(indentVal); cout << ")"; return; } myRight->unparse(indentVal); }
void StringLiteralNode::unparse(int indentVal){ cout<< *myStringVal; }
void FnCallNode::unparse(int indentVal){ myIdentifier->unparse(indentVal); cout<<"("; myArgList->unparse(indentVal); cout<<")"; }
void TrueNode::unparse(int indentVal){ cout<<"true"; }
void FalseNode::unparse(int indentVal){ cout<<"false"; }
void ArrayVarNode::unparse(int indentVal){ myIdentifier->unparse(indentVal); cout<<"["; myExpression->unparse(indentVal); cout<<"]"; }
void AndNode::unparse(int indentVal){ if(!myLeft->isNull()){ cout << "("; myLeft->unparse(indentVal); cout << " && "; myRight->unparse(indentVal); cout << ")"; return; } myRight->unparse(indentVal); }
void ReturnNode::unparse(int indentVal){ doLineNum(); indent(indentVal); cout<<"return"; if(!myReturnVal->isNull()){ cout << " "; myReturnVal -> unparse(indentVal); } cout << ";" << endl; }
void IfNode::unparse(int indentVal){ doLineNum(); indent(indentVal); cout<<"if ("; myExpression->unparse(indentVal); cout<<")"<<endl; if(!myThenStmt->isBlock()){ indentVal++; } myThenStmt->unparse(indentVal); if(!myElseStmt->isNull()){ doLineNum(); if(!myThenStmt->isBlock()){ indentVal = indentVal - 1; } indent(indentVal); cout<<"else"<<endl; if(!myElseStmt->isBlock()){ indentVal = indentVal + 1; } myElseStmt->unparse(indentVal); } }
void BlockNode::unparse(int indentVal){ doLineNum(); indent(indentVal); cout<<"{"<<endl; if(!myVarList->isNull()){ myVarList->unparse(indentVal+1); } myStmtList->unparse(indentVal+1); doLineNum(); indent(indentVal); cout<<"}"<<endl; }
void WhileNode::unparse(int indentVal){ doLineNum(); indent(indentVal); cout<<"while ("; myExpression->unparse(indentVal); cout<<")"<<endl; if(!myStmt->isBlock()){ indentVal = indentVal + 1; } myStmt->unparse(indentVal); }
void VarListNode::unparse(int indentVal){ if(!myVarList->isNull()){ myVarList->unparse(indentVal); } myDecl->unparse(indentVal); }
void ProcCallNode::unparse(int indentVal){ doLineNum(); indent(indentVal); myIdentifier->unparse(indentVal); cout<<"("; myArgList->unparse(indentVal); cout<<");"<<endl; }
void ArrayDeclNode :: unparse( int indentVal ) { doLineNum(); indent(indentVal); myType -> unparse(indentVal); myIdentifier -> unparse(indentVal); cout << " <" <<myIdentifier->getSymbol()->offset<< "> "; cout << "["; myIntLit -> unparse(indentVal); cout << "];"<< endl; }
void FunctionListNode :: unparse( int indentVal ){ myFunctionList -> unparse(indentVal); myFunctionDecl -> unparse(indentVal); }
void StmtListNode :: unparse( int indentVal ){ myStmtList -> unparse(indentVal); myStmt -> unparse(indentVal); }
void AssignNode :: unparse( int indentVal ){ doLineNum(); indent(indentVal); myTarget -> unparse( indentVal ); cout << " = "; myExpression -> unparse( indentVal ); cout << ";" << endl; }
void PrintNode :: unparse( int indentVal ){ doLineNum(); indent(indentVal); cout<<"print("; myPrintList->unparse( indentVal ); cout<<");"<<endl; }
void PrintListNode :: unparse( int indentVal ){ if(!myPrintList->isNull()){ myPrintList->unparse( indentVal ); cout << ","; } myPrintItem->unparse( indentVal ); if (myPrintItem->nodeType==IntType) cout<<" <IntType>"; else if (myPrintItem->nodeType==BoolType) cout<<" <BoolType>"; else if (myPrintItem->nodeType==StringType) cout<<" <StringType>"; }
void CoutNode :: unparse( int indentVal ){ doLineNum(); indent(indentVal); cout<<"cout"; myCoutList->unparse( indentVal ); cout<<";"<<endl; }
void CoutListNode :: unparse( int indentVal ){ myCoutList->unparse( indentVal ); cout << "<<"; myCoutItem->unparse( indentVal ); }
void ArithOpNode :: unparse( int indentVal ) { cout << "("; myLeft -> unparse(indentVal); switch (myArithOp) { case PLUS : cout << " + "; break; case MINUS : cout << " - "; break; case TIMES : cout << " * "; break; case SLASH : cout << " / "; break; default : assert(0); } myRight -> unparse(indentVal); cout << ")"; }
void RelOpNode :: unparse(int indentVal ){ cout << "("; myLeft -> unparse(indentVal); ��switch (myRelOp) { case LT : cout << " < "; break; case GT : cout << " > "; break; case EQ : cout << " == "; break; case NEQ : cout << " != "; break; case LEQ : cout << " <= "; break; case GEQ : cout << " >= "; break; default : assert(0); } myRight -> unparse(indentVal); cout << ")"; }
void NameVarNode :: unparse( int indentVal ){ myIdentifier -> unparse(indentVal); }
void IdentifierNode :: unparse( int indentVal ){ cout << myStringVal->c_str(); }
void TargetNode :: unparse(int indentVal ){ myIdentifier -> unparse(indentVal); if(!myExpression->isNull()){ cout <<"["; myExpression -> unparse(indentVal); cout <<"]"; } }
void IntLiteralNode :: unparse( int indentVal ){ cout << myIntVal; }
// symbol.cc
#include "symbol.h" #include <string>
// implementation of Symbol class
// David Haltinner ******************************************************* // Symbol constructor: initialize Symbol to have given name // David Haltinner ******************************************************* Symbol::Symbol(string S) : symbolName(S), symbolType(ErrorType), symbolKind(ErrorKind) {} // main.cc
/* * Description: * This is a compiler for the language zinc * * Usage: * $ p5 <source_file> * $ p5 -u <source_file> * $ p5 -R <source_file> * S p5 -u -R <source_file> * $ p5 -R -u <source_file> * * Input: * p5 takes between 1 and 3 arguments the last argument * must always be the source file to be compiled, which must end * in .z. the flags -u and -R are optional. -u == unparse (or pretty * print info about the source file) and -R == Sethi Ullman Register * Allocation is to be used in code generation. * * Written by: * Shawn Gens and David Haltinner */
using namespace std; #include <iostream> #include <fstream>
#include "ast.h" #include "scanner.h" // yyin is here
ASTnode * astRoot; // root of AST
extern int declErrors; extern int typeErrors; bool SethiUllmanFlag; extern ofstream asmFile;
int main( int argc, char **argv ) { // Check for correct usage (arguments) if ( argc==1 || argc==3 && (strcmp(argv[1],"-u")!=0&&strcmp(argv[1],"-R")!=0) || argc==4 && ((strcmp(argv[1], "-u")!=0&&strcmp(argv[2], "-R")!=0)&& (strcmp(argv[1], "-R")!=0&&strcmp(argv[2], "-u")!=0))|| argc>4 ) { cerr << "\nusage: " << argv[0] << " <source_file>" <<endl; cerr << " " << argv[0] << " -u <source_file>" <<endl; cerr << " " << argv[0] << " -R <source_file>" <<endl; cerr << " " << argv[0] << " -u -R <source_file>" <<endl; cerr << " " << argv[0] << " -R -u <source_file>" <<endl; cerr << " options: -u==unparse, -R==SethiAllman register allocation" <<endl<<endl; return 1; }
bool unparse = false; SethiUllmanFlag = false; int fileName = 1;
// Which flags (if any) are set? if ( (argc==3||argc==4) && strcmp(argv[1],"-u")==0 ) { unparse = true; fileName = 2; } if( (argc==3||argc==4) && strcmp(argv[1], "-R")==0 ) { SethiUllmanFlag = true; fileName = 2; } if( argc==4 && strcmp(argv[2], "-R")==0 ) { SethiUllmanFlag = true; fileName = 3; } if( argc==4 && strcmp(argv[2], "-u")==0 ) { unparse = true; fileName = 3; }
// Now look at the source file string file_name = argv[fileName]; string asmfile = file_name; string ex = "s"; if (file_name.size() <= 2) { cerr << endl << argv[0] << ": " << argv[1] << " does not have a \".z\" extension" << endl << endl; return 1; } if (file_name.substr(file_name.size()-2, 2) != ".z") { cerr << endl << argv[0] << ": " << argv[1] << " does not have a \".z\" extension" << endl << endl; return 1; }
if ( (yyin = fopen(argv[fileName],"r")) == NULL ) { cerr<<endl<<argv[0] << ": could not open " << argv[fileName] <<endl<<endl; return 1; }
asmfile[asmfile.length()-1] = ex[0]; char afile[asmfile.length()]; for(unsigned int i=0; i<=asmfile.length(); i++){ afile[i] = asmfile[i]; }
asmFile.open(afile); if(asmFile.fail()){ cerr << endl << argv[0] << ": could not open " << asmfile <<endl<<endl; return 1; }
// Start compilation extern int yyparse(); cout << "source file: " << argv[fileName] << endl; cout << "...parse" << endl;
if ( yyparse() == 0 ) {
cout << "...name check" << endl; astRoot->checkNames(); if (declErrors>0) { string msg = "error"; if (declErrors>1) msg = msg + "s"; cerr << declErrors << " declaration/use " << msg << " found" << endl; cerr << "Compilation aborted." << endl; return 1; }
cout << "...type check" << endl; astRoot->checkTypes(); if (typeErrors>0) { string msg = "error"; if (typeErrors>1) msg = msg + "s"; cerr << typeErrors << " type " << msg << " found" << endl; cerr << "Compilation aborted." << endl; return 1; }
// The file made it to code generation cout << "...emit code"; if( SethiUllmanFlag ) { // Sethi Ullman Flag has been set...tell the user cout << " using Sethi Ullman register allocation"; } cout << endl; astRoot->emitCode();
if ( unparse ) { // The unparse flag is set...tell the user cout << "...unparse" << endl; astRoot->unparse(); } }
fclose(yyin); return 0; } // test of some complex expressions using &&
int x(bool q, int z[], bool y[], int w){ y[w] = q; //y[1] = true z[2] = 2; // this is true if(q && 3 > 2 && true && true && (q || true) && (true && true)){ print("HERE", "\n"); // prints z[2] = z[2] + 4 - 1 - 3 + w / w; // z[2] = 3 print("z[2] is: ", z[2], "\n"); } return (3 + 8 + z[2]); }
int main(){ bool y[6]; int v[2]; bool q; int hi; v[2] = 0; q = 4 < 1; y[1] = true && true || false || true && q; //y[1] = true v[1] = x(true, v, y, 1); // v[1] = 14 print("v[1] ", v[1], " v[2] ", v[2], " y[1] ", y[1], "\n"); return 0; } .data .true: .asciiz "true" .false: .asciiz "false" .nl: .asciiz "\n" .text .globl main
j.f: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 12 # ra, fp & locals sw $ra, 8($sp) sw $fp, 4($sp) addu $fp, $sp, 16 # set new fp #assignment li $t0, 3 sw $t0, -16($fp) #assignment lw $t0, 0($fp) lw $t1, -4($fp) add $t0, $t0, $t1 lw $t1, -16($fp) add $t0, $t0, $t1 sw $t0, -16($fp)
#return lw $t0, -16($fp) move $v0, $t0 j j.f..
j.f..: ##### ####### EPILOGUE ####### ##### lw $ra, -8($fp) # restore ra lw $fp, -12($fp) # restore fp addu $sp, $sp, 20 # Pop jr $ra
t.f: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 8 # registers ra & fp sw $ra, 4($sp) sw $fp, 0($sp) addu $fp, $sp, 16 # set new fp
t.f..: ##### ####### EPILOGUE ####### ##### lw $ra, -12($fp) # restore ra lw $fp, -16($fp) # restore fp addu $sp, $sp, 20 # Pop jr $ra
main: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 28 # ra, fp & locals sw $ra, 24($sp) sw $fp, 20($sp) addu $fp, $sp, 24 # set new fp #assignment lw $t0, -24($fp) li $t1, 3 li $t2, 3 mulo $t1, $t1, $t2 add $t0, $t0, $t1 sw $t0, -24($fp)
#return li $t0, 1 move $v0, $t0 j main..
main..: ##### ####### EPILOGUE ####### ##### lw $ra, 0($fp) # restore ra lw $fp, -4($fp) # restore fp addu $sp, $sp, 28 # Pop
li $v0, 10 syscall # program exit source file: OO/test.z ...parse ...name check ...type check ...code generation ...unparse functionName<parameters:locals:frameSize>; variableName<offset> 1: int j <2:1:20> ( 1: int x <0> , 1: int y <4> ) 1: { 2: int z <16> ; 3: z = 3; 4: z = ((x + y) + z); 5: return z; 1: } 8: void t <3:0:20> ( 8: int z <0> , 8: int q <4> [], 8: bool e <8> ) 8: { 8: } 10: int main <0:5:28> () 10: { 11: int y <20> [4]; 12: int x <24> ; 14: y[1] = (((x + 3) + x) - (y[3] * 2)); 17: return 1; 10: }
******** p5/OO/typecheck.obj: Not a text file ********
source file: test.z ...parse ...name check ...type check ...unparse functionName<parameters:locals:frameSize>; variableName<offset> 1: int j <2:1:20> ( 1: int x <0> , 1: int y <4> ) 1: { 2: int z <16> ; 3: z = 3; 4: z = ((x + y) + z); 5: return z; 1: } 8: void t <3:0:20> ( 8: int z <0> , 8: int q <4> [], 8: bool e <8> ) 8: { 8: } 10: int main <0:5:28> () 10: { 11: int y <20> [4]; 12: int x <24> ; 14: y[1] = (((x + 3) + x) - (y[3] * 2)); 17: return 1; 10: } ...emit code int j(int x, int y){ int z; z = 3; z = x + y + z; return z; }
void t(int z, int q[], bool e){}
int main(){ int y[4]; int x; //x = 2; x = x + 3 * 3; //y[3] = j(2, x); //t(x, y, true); return 1; }
******** p5/OO/namecheck.obj: Not a text file ********
.data .true: .asciiz "true" .false: .asciiz "false" .nl: .asciiz "\n" .text .globl main
j.f: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 12 # ra, fp & locals sw $ra, 8($sp) sw $fp, 4($sp) addu $fp, $sp, 16 # set new fp #assignment li $t0, 3 sw $t0, -16($fp) #assignment lw $t0, -4($fp) lw $t1, 0($fp) add $t1, $t1, $t0 lw $t0, -16($fp) add $t1, $t1, $t0 sw $t1, -16($fp)
#return lw $t0, -16($fp) move $v0, $t0 j j.f..
j.f..: ##### ####### EPILOGUE ####### ##### lw $ra, -8($fp) # restore ra lw $fp, -12($fp) # restore fp addu $sp, $sp, 20 # Pop jr $ra
t.f: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 8 # registers ra & fp sw $ra, 4($sp) sw $fp, 0($sp) addu $fp, $sp, 16 # set new fp
t.f..: ##### ####### EPILOGUE ####### ##### lw $ra, -12($fp) # restore ra lw $fp, -16($fp) # restore fp addu $sp, $sp, 20 # Pop jr $ra
main: ##### ####### PROLOGUE ####### ##### subu $sp, $sp, 28 # ra, fp & locals sw $ra, 24($sp) sw $fp, 20($sp) addu $fp, $sp, 24 # set new fp #assignment li $t0, 3 li $t1, 3 mulo $t1, $t1, $t0 lw $t0, -24($fp) add $t0, $t0, $t1 sw $t0, -24($fp)
#return li $t0, 1 move $v0, $t0 j main..
main..: ##### ####### EPILOGUE ####### ##### lw $ra, 0($fp) # restore ra lw $fp, -4($fp) # restore fp addu $sp, $sp, 28 # Pop
li $v0, 10 syscall # program exit
******** p5/OO/z5: Not a text file ********
// message.h
#ifndef MESSAGE_GUARD #define MESSAGE_GUARD
#include <string> using namespace std;
void Error(int line, int col, string msg); void Warn (int line, int col, string msg); void InternalError(string msg);
// GLOBAL VARIABLE extern bool errorFlag;
#endif #! /bin/csh
# usage # zoc test
echo "p5" $1.z
./p5 $1.z if ( $status != 0 ) exit -1
echo "...peephole optimization" /home/perrie/spim/bin/copt peephole.rules <$1.s >$1.S
echo "...assemble and execute" echo "/home/perrie/spim/bin/spim -file " $1".S"
/home/perrie/spim/bin/spim -file $1.S
echo "" echo "" echo "differences between" $1".s and" $1".S:" diff $1.s $1.S echo "" int x; //test global variables bool y; int w[2]; bool q[2];
int z(int i, bool b, int v[], bool n[]){ //tests functin calls int t; int h[2]; bool p[2]; bool m; h[1] = i; //local arrays h[0] = h[1] + 3 + v[0] / x; //mathematic operations with local arrays t = 1 + (x - i) / v[0] * v[1] - w[0] + w[1]; m = b && i != 6 || b && t <= 4; //boolean math with local variables p[1] = true; p[0] = p[1] && b && y && q[0] && q[1]; print(1,2,3, true, false, "\n"); //a bunch of prints print("t is local and it is...", t, "\n"); print("m is local and it is ...", m, "\n"); print("p[1] is local and it is ...", p[1], "\n"); print("h[0] is local and it is ...", h[0], "\n"); print("i is a param and it is ...", i, "\n"); print("v[1] is a param and it is ...", v[1], "\n"); print("n[0] is a param and it is ...", n[0], "\n"); print("b is a param and it is ...", b, "\n"); print("x is global and it is ...", x, "\n"); print("y is global and it is ...", y, "\n"); print("w[0] is global and it is ...", w[0], "\n"); print("q[1] is global and it is ...", q[1], "\n"); return h[1]; }
int main(){ //math with global and local arrays and variabales, as well as a funtion call int try; int tArray[2]; tArray[0] = 1; tArray[1] = 9; x = 1 + 3 + 2; y = false; w[0] = x * x; w[1] = x / 5; q[0] = true; q[1] = false; try = z(w[1], y, w, q); try = z(tArray[1], y, tArray, q); return w[1]; } // int2str.cc
#include "int2str.h" #include <assert.h>
//David Haltinner ******************************************************* // IntToStr // convert the given (non-negative) int to a String // David Haltinner ******************************************************* string IntToStr(int k) { int digit; string tmp = "";
assert(k >= 0); if (k == 0) return("0"); while (k>0) { digit = k % 10; k = k / 10; switch (digit) { case 0: tmp = "0" + tmp; break; case 1: tmp = "1" + tmp; break; case 2: tmp = "2" + tmp; break; case 3: tmp = "3" + tmp; break; case 4: tmp = "4" + tmp; break; case 5: tmp = "5" + tmp; break; case 6: tmp = "6" + tmp; break; case 7: tmp = "7" + tmp; break; case 8: tmp = "8" + tmp; break; case 9: tmp = "9" + tmp; break; } } return(tmp); }
// symboltable.cc
#include <cassert> #include <list> #include <string> #include <iostream> #include <iomanip> #include "symbol.h" #include "symboltable.h"
// implementation of the SymbolTable class using a hash table
/* Assignment #1: * a) Do not modify functions Hash or Print * b) Implement functions Insert and Lookup */
// David Haltinner ====================================================== // Insert // David Haltinner ====================================================== // add the given symbol to the table // error if there is already a symbol with the same name
void SymbolTable::Insert(SymbolPtr sym) { //error if Lookup(sym->symbolName)!=NULL assert(Lookup(sym->symbolName) == NULL);
// at this point, Lookup(sym->symbolName) == NULL // i.e. we have a guarantee that sym is not already in the symbol table // software needs to call Lookup before calling Insert // i.e. duplicate names will never be in the symbol table
// now, add sym to the symbol table // Hash the item int hashVal = Hash((sym->symbolName));
// Put it in the back of the bucket bucket[hashVal].push_back(sym); }
// David Haltinner ====================================================== // Lookup // David Haltinner ====================================================== // if there is a symbol with the given name in the table, return a // pointer to that symbol; // otherwise, return NULL
SymbolPtr SymbolTable::Lookup(string name) { int hashVal = Hash(name); // Which list to look in list<SymbolPtr> L; // Pointer to the list list<SymbolPtr>::iterator i; // Iterator for the list SymbolPtr sym; // Pointer for examining items in list bool found = false; // Tells if item is found or not L = bucket[hashVal]; i = L.begin();
while( i != L.end()){ sym = *i; if(sym->symbolName == name){ found = true; // The item is found return sym; // Now stop looking } i++; }
return NULL; }
// David Haltinner ====================================================== // Hash // David Haltinner ====================================================== // hash function
int SymbolTable::Hash(string & S) { int val = 0; for (int j=0; j<int(S.length()); j++) val = (val << 3) + S[j]; if (val < 0) val = -val; return(val % TABLESIZE); }
// David Haltinner ====================================================== // Print // David Haltinner ====================================================== // print the names of all the symbols, one per line
void SymbolTable::Print(ostream & out) { SymbolPtr sym; list<SymbolPtr> L; list<SymbolPtr>::iterator i;
for (int k=0; k<TABLESIZE; k++) { L = bucket[k]; i = L.begin(); while ( i != L.end() ) { sym = *i; out << sym->symbolName.c_str() << endl; i++; } } } // int2str.h
#ifndef _INT2STR_H #define _INT2STR_H
using namespace std; #include <string>
string IntToStr( int k );
#endif #! /bin/csh
# usage # zcc test
echo "" echo "p5" $1.z
./p5 $1.z if ( $status != 0 ) exit -1
echo "...assemble and execute" echo "spim -file " $1".s"
/home/perrie/spim/bin/spim -file $1.s echo "" // emit.cc
using namespace std; #include "ast.h" #include "emit.h" #include "int2str.h" #include "message.h"
#include <iostream> #include <iomanip> #include <fstream> #include <string> #include <assert.h>
ofstream asmFile;
//David Haltinner ============================================================ // // Reg Routines // //David Haltinner ============================================================
// oops. should have 10 $t registers static int regInUse[8] = { 0,0,0,0,0,0,0,0 }; // 0 == free; 1 == in use static int nRegInUse = 0;
static int argRegInUse[4] = { 0,0,0,0 }; // 0 == free; 1 == in use static int nArgRegInUse = 0;
int getReg() { int i;
for (i=0; i<8 && regInUse[i]==1; i++) {}; if ( i==8 ) InternalError("emit: out of registers in getReg");
regInUse[i] = 1; nRegInUse++; return i; }
void freeReg( int r ) { if (r==30) { return; } assert( r>=0 && r<=7 ); regInUse[r] = 0; nRegInUse--; }
static void emitOffsetSP ( string opcode, int rD, int offset ) { asmFile << "\t" << opcode << "\t" ; asmFile << "$t"+IntToStr(rD) << ", " << IntToStr(offset) << "($sp)" <<endl; asmFile.flush(); }
void saveRegs() { if(nRegInUse>0) emit( "subu", "$sp, $sp", IntToStr(nRegInUse*4) ); for (int i=0; i<8; i++) if(regInUse[i]==1) emitOffsetSP("sw", i, i*4 ); }
void restoreRegs() { for (int i=0; i<8; i++) if(regInUse[i]==1) emitOffsetSP("lw", i, i*4 ); if(nRegInUse>0) emit( "addu", "$sp, $sp", IntToStr(nRegInUse*4) ); }
int getArgReg() { int i;
for (i=0; i<4 && argRegInUse[i]==1; i++) {}; if ( i==4 ) InternalError("emit: out of registers in getArgReg");
argRegInUse[i] = 1; nArgRegInUse++; return i; }
void freeArgReg( int r ) { assert( r>=0 && r<=3 ); argRegInUse[r] = 0; nArgRegInUse--; }
// David Haltinner =========================================================== // // Emit Routines // // David Haltinner ===========================================================
void emit( string opcode, string arg1, string arg2, string arg3, string comment ) { asmFile << "\t" << opcode;
if ( arg1 != "" ) { asmFile << "\t" << arg1; if ( arg2 != "" ) { asmFile << ", " << arg2; if ( arg3 != "" ) { asmFile << ", " << arg3; if ( comment != "" ) asmFile << "\t" << comment; } } }
asmFile<<endl; asmFile.flush(); }
// David Haltinner ===========================================================
void emit( string opcode, int rD, string arg ) { asmFile << "\t" << opcode << "\t";
asmFile << "$t" << IntToStr(rD) << ", " << arg << endl; asmFile.flush(); }
void emit( string opcode, string rD, int arg ) { asmFile << "\t" << opcode << "\t";
asmFile << rD << ", " << arg << endl; asmFile.flush(); }
void emit( string opcode, int rD, int arg ) { asmFile << "\t" << opcode << "\t";
asmFile << "$t" << IntToStr(rD) << ", " << arg << endl; asmFile.flush(); }
// David Haltinner ===========================================================
void emitOffset ( string opcode, string arg1, int offset, string arg2, string comment ) { asmFile << "\t" << opcode << "\t" ;
string stringOffset = (offset==0) ? IntToStr(offset) : "-"+IntToStr(offset); asmFile << arg1 << ", " << stringOffset << "(" << arg2 << ")";
if (comment!="") asmFile << "\t" << comment;
asmFile<<endl; asmFile.flush(); }
void emitOffset ( string opcode, int rD, int offset, string arg2, string comment ) { asmFile << "\t" << opcode << "\t" ;
string stringOffset = (offset==0) ? IntToStr(offset) : "-"+IntToStr(offset); asmFile << "$t"+IntToStr(rD) << ", " << stringOffset << "(" << arg2 << ")";
if (comment!="") asmFile << "\t" << comment;
asmFile<<endl; asmFile.flush(); }
// David Haltinner ===========================================================
void emitComment( string comment ) { asmFile << "#" << comment << endl; asmFile.flush(); }
void emitBlockComment( string comment ) { asmFile << "\t#####" << endl; asmFile << "\t####### " << comment << " #######" << endl; asmFile << "\t#####" << endl; asmFile.flush(); }
void emitEmptyLine() { asmFile << endl; asmFile.flush(); }
// David Haltinner ===========================================================
void emitLabel( string label ) { asmFile << label << ":" << endl; }
// =================================== // Return a different label each time: // .L0, .L1, .L2, etc. // =================================== string NextLabel() { static int currLabel = 0;
string tmp = ".L" + IntToStr(currLabel++); return(tmp); } // typecheck.cc #include "ast.h" #include "message.h" #include "symbol.h" #include "symboltable.h" #include "symlist.h" #include "scanner.h" #include "y.tab.h"
/* * do type checking, i.e. find type errors * */
int typeErrors = 0;
void ProgramNode :: checkTypes() { myFunctionList -> checkTypes(); }
void GlobalListNode :: checkTypes() { return; }
void FunctionListNode :: checkTypes() { myFunctionList -> checkTypes(); myFunctionDecl -> checkTypes(); }
void FunctionDeclNode :: checkTypes() { myStmtList -> checkTypes(); }
void VariableDeclNode :: checkTypes() { return; }
void ArrayDeclNode :: checkTypes() { return; }
void TypeIntNode :: checkTypes() { return; }
void TypeBoolNode :: checkTypes() { return; }
void ParametersNode :: checkTypes() { return; }
void ParamListNode :: checkTypes() { return; }
void ArgListNode :: checkTypes() { myArgList -> checkTypes(); myExpression -> checkTypes(); }
void ParamValNode :: checkTypes() { return; }
void ParamArrayNode :: checkTypes() { return; }
void VarListNode :: checkTypes() { myVarList -> checkTypes(); myDecl -> checkTypes(); }
void StmtListNode :: checkTypes() { myStmtList -> checkTypes(); myStmt -> checkTypes(); }
void AssignNode :: checkTypes() { bool errors = false; myTarget -> checkTypes(); myExpression -> checkTypes(); Symbol * s = myTarget->getID()->getSymbol(); if((s->symbolKind == ArrayKind || s->symbolKind == ArrayParamKind) && myTarget->getExp()->isNull()){ typeErrors++; string msg = "assignment: LHS name is an array name"; Error(line, column, msg); errors = true; } if(s->symbolKind == FnKind){ typeErrors++; string msg = "assignment: LHS name is a function name"; Error(line, column, msg); errors = true; } if(myExpression->isName()){ s = myExpression->getID()->getSymbol(); if(s->symbolKind == FnKind){ typeErrors++; string msg = "assignment: RHS name is a function name"; Error(line, column, msg); errors = true; } else if(s->symbolKind == ArrayKind || s->symbolKind == ArrayParamKind){ typeErrors++; string msg = "assignment: RHS name is an array name"; Error(line, column, msg); errors = true; } } if(myExpression-> nodeType != myTarget->nodeType && !errors){ typeErrors++; string msg = "assignment: LHS type != RHS type"; Error(line, column, msg); } }
void IfNode :: checkTypes() { myExpression -> checkTypes(); myThenStmt -> checkTypes(); myElseStmt -> checkTypes(); }
void WhileNode :: checkTypes() { myExpression -> checkTypes(); myStmt -> checkTypes(); }
void BlockNode :: checkTypes() { myStmtList -> checkTypes(); return; }
void ReturnNode :: checkTypes() { myReturnVal -> checkTypes(); nodeType = myReturnVal -> nodeType; }
void ProcCallNode :: checkTypes() { myArgList->checkTypes(); }
void PrintNode :: checkTypes() { myPrintList -> checkTypes(); }
void PrintListNode :: checkTypes() { myPrintList -> checkTypes(); myPrintItem -> checkTypes(); if(myPrintItem->nodeType == VoidType){ typeErrors++; myPrintItem->nodeType = ErrorType; string msg = "print expression is void type"; Error(line, column, msg); } }
void OrNode :: checkTypes() { myLeft->checkTypes(); myRight->checkTypes(); nodeType = myRight -> nodeType; if(!myLeft->isNull() && !myRight->isNull()){ if(myLeft->nodeType != BoolType){ typeErrors++; string msg = "left operand of || is not bool"; Error(line, column, msg); } if(myRight->nodeType != BoolType){ typeErrors++; string msg = "right operand of || is not bool"; Error(line, column, msg); } nodeType = BoolType; } }
void AndNode :: checkTypes() { myLeft->checkTypes(); myRight->checkTypes(); nodeType = myRight->nodeType; if(!myLeft->isNull()&&!myRight->isNull()){ if(myLeft->nodeType != BoolType){ typeErrors++; string msg = "left operand of && is not bool"; Error(line, column, msg); }
if(myRight->nodeType != BoolType){ typeErrors++; string msg = "right operand of && is not bool"; Error(line, column, msg); } nodeType = BoolType; } }
void RelOpNode :: checkTypes() { myLeft->checkTypes(); myRight->checkTypes(); nodeType = myRight->nodeType; if(!myLeft->isNull()&&!myRight->isNull()){ if(myLeft->nodeType != IntType){ typeErrors++; string msg = "left operand of"; switch(myRelOp){ case LT: msg = msg + " < "; break; case GT: msg = msg + " > "; break; case LEQ: msg = msg + " <= "; break; case GEQ: msg = msg + " >= "; break; case EQ: msg = msg + " == "; break; case NEQ: msg = msg + " != "; break; } msg = msg + "is not int"; Error(line, column, msg); } if(myRight->nodeType != IntType){ typeErrors++; string msg = "right operand of"; switch(myRelOp){ case LT: msg = msg + " < "; break; case GT: msg = msg + " > "; break; case LEQ: msg = msg + " <= "; break; case GEQ: msg = msg + " >= "; break; case EQ: msg = msg + " == "; break; case NEQ: msg = msg + " != "; break; } msg = msg + "is not int"; Error(line, column, msg); } nodeType = BoolType; } }
void ArithOpNode :: checkTypes() { myLeft->checkTypes(); myRight->checkTypes(); nodeType = myRight->nodeType; if(!myLeft->isNull()&&!myRight->isNull()){ if(myLeft->nodeType != IntType){ typeErrors++; string msg = "left operand of "; switch(myArithOp){ case PLUS: msg = msg + " + "; break; case MINUS: msg = msg + " - "; break; case TIMES: msg = msg + " * "; break; case SLASH: msg = msg + " / "; break; } msg = msg + "is not int"; Error(line, column, msg); } if(myRight->nodeType != IntType){ typeErrors++; string msg = "right operand of "; switch(myArithOp){ case PLUS: msg = msg + " + "; break; case MINUS: msg = msg + " - "; break; case TIMES: msg = msg + " * "; break; case SLASH: msg = msg + " / "; break; } msg = msg + "is not int"; Error(line, column, msg); } nodeType = IntType; } }
void NameVarNode :: checkTypes() { myIdentifier -> checkTypes(); nodeType = myIdentifier->nodeType; }
void ArrayVarNode :: checkTypes() { myIdentifier -> checkTypes(); nodeType = myIdentifier->nodeType;
myExpression -> checkTypes(); }
void FnCallNode :: checkTypes() { myIdentifier->checkTypes(); nodeType = (myIdentifier->getSymbol())->symbolType; myArgList->checkTypes(); }
void TrueNode :: checkTypes() { nodeType = BoolType; } void FalseNode :: checkTypes() { nodeType = BoolType; } void IntLiteralNode :: checkTypes() { nodeType = IntType; } void TargetNode :: checkTypes() { Symbol * s = myIdentifier->getSymbol(); nodeType = s->symbolType; } void IdentifierNode :: checkTypes() { nodeType = mySymbolTableEntry->symbolType; } void StringLiteralNode :: checkTypes() { nodeType = StringType; } // more tests of booleans
bool y;
int main(){ bool x; x = false; //x = true; y = (x && true) || (false && x); // y = false print("X is ", x, "\n"); // false print("Y is ", y, "\n"); // false
// fails if(false || y && true || x){ print("Its true", "\n"); } else{ int i; i = 0; while(i < 3 || x){ print("Its false", "\n"); i = i + 1; } } } // emit.h
#ifndef EMIT_H_ #define EMIT_H_
#include <iostream> #include <iomanip> #include <fstream> #include <string> using namespace std;
int getReg(); void freeReg( int r ); int getArgReg(); void freeArgReg( int r );
void saveRegs(); void restoreRegs();
// David Haltinner ============================================================
void emit( string opcode, string arg1="", string arg2="", string arg3="", string comment="" );
void emit( string opcode, int rD, string arg ); void emit( string opcode, string rD, int arg ); void emit( string opcode, int rD, int arg );
// David Haltinner ============================================================
void emitOffset ( string opcode, string arg1, int offset, string arg2, string comment="" ); void emitOffset ( string opcode, int rD, int offset, string arg2, string comment="" );
// David Haltinner ============================================================
void emitLabel( string label ); void emitComment ( string comment ); void emitBlockComment( string comment ); void emitEmptyLine ();
// David Haltinner ============================================================
string NextLabel();
#endif // test of assignment of functions and while
bool t(bool y){ bool z; // z is true // y is true z = y || y && false; print(z, "\n", y, "\n"); return true; }
int main(){ int x; x = 3; while(x > 0){ bool z; print("Test: ", x, "\n"); z = t(true); // z is true print("t returns: ", z, "\n"); x = x - 1; } return 1; } // ast.cc
#include "symbol.h" #include "ast.h"
ProgramNode :: ProgramNode(GlobalListNode*g, FunctionListNode*f, int l, int c) : ASTnode(l,c), myGlobalList(g), myFunctionList(f) {}
GlobalListNode :: GlobalListNode(GlobalListNode*g, DeclNode*v, int l, int c) : ASTnode(l,c), myGlobalList(g), myDecl(v) {}
FunctionListNode :: FunctionListNode(FunctionListNode*f, FunctionDeclNode*d, int l, int c) : ASTnode(l,c), myFunctionList(f), myFunctionDecl(d) {}
FunctionDeclNode :: FunctionDeclNode(TypeNode*t, IdentifierNode*i, ParametersNode*p, VarListNode*v, StmtListNode*s, int l, int c) : ASTnode(l,c), myType(t), myIdentifier(i), myParameters(p), myVarList(v), myStmtList(s) {}
TypeNode :: TypeNode(int l, int c) : ASTnode(l,c) {}
TypeIntNode :: TypeIntNode (int l, int c) : TypeNode(l,c) {} TypeBoolNode :: TypeBoolNode(int l, int c) : TypeNode(l,c) {}
DeclNode :: DeclNode(int l, int c) : ASTnode(l,c) {}
VariableDeclNode :: VariableDeclNode(TypeNode *t, IdentifierNode *i, int l, int c) : DeclNode(l,c), myType(t), myIdentifier(i) {}
ArrayDeclNode :: ArrayDeclNode(TypeNode*t, IdentifierNode*i, ExpressionNode*n, int l,int c) : DeclNode(l,c), myType(t), myIdentifier(i), myIntLit(n) {}
ParametersNode :: ParametersNode(ParamListNode* p, int l, int c) : ASTnode(l,c), myParamList(p) {}
ParamListNode :: ParamListNode(ParamListNode* p, ParamNode* n, int l, int c) : ASTnode(l,c), myParamList(p), myParam(n) {}
ArgListNode :: ArgListNode(ArgListNode *a, ExpressionNode *e, int l, int c) : ASTnode(l,c), myArgList(a), myExpression(e) {}
ParamNode :: ParamNode(int l, int c) : ASTnode(l,c) {}
ParamValNode :: ParamValNode(TypeNode* t, IdentifierNode* i, int l, int c) : ParamNode(l,c), myType(t), myIdentifier(i) {}
ParamArrayNode :: ParamArrayNode(TypeNode* t, IdentifierNode* i, int l,int c) : ParamNode(l,c), myType(t), myIdentifier(i) {}
VarListNode :: VarListNode(VarListNode *v, DeclNode *d, int l, int c) : ASTnode(l,c), myVarList(v), myDecl(d) {}
StmtListNode :: StmtListNode(StmtListNode *s, StmtNode *n, int l, int c) : ASTnode(l,c), myStmtList(s), myStmt(n) {}
StmtNode :: StmtNode(int l, int c) : ASTnode(l,c) {}
AssignNode :: AssignNode(TargetNode *t, ExpressionNode *e, int l, int c) : StmtNode(l,c), myTarget(t), myExpression(e) {}
IfNode :: IfNode(ExpressionNode *ex, StmtNode *t, StmtNode *e, int l, int c) : StmtNode(l,c), myExpression(ex), myThenStmt(t), myElseStmt(e) {}
WhileNode :: WhileNode(ExpressionNode *e, StmtNode *s, int l, int c) : StmtNode(l,c), myExpression(e), myStmt(s) {}
BlockNode :: BlockNode( VarListNode *v, StmtListNode *s, int l, int c) : StmtNode(l,c), myVarList(v), myStmtList(s) {}
ReturnNode :: ReturnNode(ExpressionNode *e, int l,int c) : StmtNode(l,c), myReturnVal(e) {}
ProcCallNode :: ProcCallNode(IdentifierNode*i, ArgListNode*a, int l, int c) : StmtNode(l,c), myIdentifier(i), myArgList(a) {}
PrintNode :: PrintNode(PrintListNode *p, int l, int c) : StmtNode(l,c), myPrintList(p) {}
CoutNode :: CoutNode(CoutListNode *p, int l, int c) : StmtNode(l,c), myCoutList(p) {}
PrintListNode :: PrintListNode(PrintListNode *p, PrintItemNode *i, int l, int c) : ASTnode(l,c), myPrintList(p), myPrintItem(i) {}
CoutListNode :: CoutListNode(CoutListNode *p, PrintItemNode *i, int l, int c) : ASTnode(l,c), myCoutList(p), myCoutItem(i) {}
PrintItemNode :: PrintItemNode(int l, int c) : ASTnode(l,c) {}
ExpressionNode :: ExpressionNode(int l, int c) : PrintItemNode(l,c) {}
OrNode :: OrNode(ExpressionNode *e1, ExpressionNode *e2, int l,int c) : ExpressionNode(l,c), myLeft(e1), myRight(e2) {}
AndNode :: AndNode(ExpressionNode *e1, ExpressionNode *e2, int l,int c) : ExpressionNode(l,c), myLeft(e1), myRight(e2) {}
RelOpNode :: RelOpNode(int o, ExpressionNode *e1, ExpressionNode *e2, int l,int c) : ExpressionNode(l,c), myRelOp(o), myLeft(e1), myRight(e2) {}
ArithOpNode :: ArithOpNode (int o,ExpressionNode *e1,ExpressionNode *e2, int l,int c) : ExpressionNode(l,c), myArithOp(o), myLeft(e1), myRight(e2) {}
TrueNode :: TrueNode (int l, int c) : ExpressionNode(l,c) {} FalseNode :: FalseNode(int l, int c) : ExpressionNode(l,c) {}
NameVarNode :: NameVarNode( IdentifierNode *n, int l, int c) : ExpressionNode(l,c), myIdentifier(n) {}
ArrayVarNode :: ArrayVarNode( IdentifierNode *n, ExpressionNode *e, int l, int c) : ExpressionNode(l,c), myIdentifier(n), myExpression(e) {}
FnCallNode :: FnCallNode(IdentifierNode *i, ArgListNode *a, int l, int c) : ExpressionNode(l,c), myIdentifier(i), myArgList(a) {}
IntLiteralNode :: IntLiteralNode(int n, int l, int c) : ExpressionNode(l,c) { myIntVal=n; }
TargetNode :: TargetNode(IdentifierNode *i, ExpressionNode *e, int l, int c) : ASTnode(l,c), myIdentifier(i), myExpression(e) {}
IdentifierNode :: IdentifierNode(string *s, int l, int c) : ASTnode(l,c), myStringVal(s) {}
StringLiteralNode :: StringLiteralNode(string *s, int l, int c) : PrintItemNode(l,c), myStringVal(s) {} // test of global arrays and while loops
int x[3]; bool y[3];
void fill(){ int j[3]; bool k[3]; int i; i = 0; while(i < 3){ j[i] = i; x[i] = j[i]; // 0, 1 y[i] = true; k[i] = y[i]; // true print("k[", i, "] is ", k[i], "\n"); print("j[", i, "] is ", j[i], "\n"); i = i + 1; } }
void printItems(){ int i; i = 0; while(i < 3){ print("y[", i, "] is ", y[i], "\n"); print("x[", i, "] is ", x[i], "\n"); i = i + 1; } }
int main(){ fill(); printItems(); return 1; } #!/bin/sh
for i in 1 2 3 4 5 6 7 do echo "****************" zcc "t$i" echo "****************" done for i in 1 2 3 do echo "****************" zcc "test$i" echo "****************" done echo "Printing Big and Bad" echo "" echo "*************" echo "Big" zcc eBig echo "*************" echo "Bad" zcc eBad echo "*************"
******** p5/z5: Not a text file ********
// This is a test to use all 8 registers
int main(){ int x; int y; int z; x = 1; y = 2; z = 3;
// Lets use all of the registers x = x + x * (3 + 4 * (z + 3 * (4 * 1))); // Print the value 64 print("X is ", x, " and it uses a lot of registers"); print("\n"); } // This is a test to run out of registers
int main(){ int x; int y; int z; x = 1; z = 3; // Now lets break the compiler x = x - x / (3 - 4 / (z - 3 / (4 - 4 / 1))); } // symlist.cc
#include "message.h" #include "symlist.h"
SymTableList::SymTableList() { symTableList = new list<PSymbolTable>(); }
SymTableList::~SymTableList() { delete symTableList; }
void SymTableList::push(PSymbolTable v) { symTableList->push_front(v); } PSymbolTable SymTableList::pop() { PSymbolTable p=symTableList->front(); symTableList->pop_front(); return p; } PSymbolTable SymTableList::top() { return symTableList->front(); } SymbolPtr SymTableList::lookUp(string id) { list<PSymbolTable>::iterator i; for (i=symTableList->begin(); i != symTableList->end(); i++) { SymbolPtr p=(*i)->Lookup(id); if (p!=NULL) return p; } return NULL; }
1 note
·
View note