%{ #include #include #include #include #define YYSTYPE void* #include "list.h" #include "cmp.h" #include "shared.h" #include "intcode.h" #include "env.h" #include "quad.h" #include "mem.h" void yyerror(const char *str) { fprintf(stderr,"error: %s at %d on %s\n",str,yylineno,yytext); printf("\n"); } void *makeArray(void *type, void *size); void *makeType(void *type); void *setID(void *type, void* id); void println(char* str); void *add(void* a, void* b); void *sub(void* a, void* b); void *mul(void *a, void *b); void *div_(void*a, void *b); env_t *inner_env; extern int yylex(void); %} %token ID NUM REAL BOOL BASIC WHILE FOR IF BREAK QUIT DO CONTINUE TRUE FALSE /*these are in this order to have the order of operations. Reduce and else are here to handle ambiguity with if statmements*/ %nonassoc REDUCE %nonassoc ELSE %token AND_OP OR_OP GE_OP LE_OP EQ_OP NE_OP %left '+' '-' %left '*' '/' %right UMINUS %start program %% /*this is the grammar from Appendix A.1 of the compiler design textbook*/ program : block { println("rule: program -> block");} | error {fprintf(stderr,"error: Unable to parse program. I don't even know where to start\n");} ; block : '{' {cur_env = env_scope_init(cur_env); inner_env = cur_env;} decls stmts '}' {println("rule: block -> '{' decls stmts '}'");$$ =$4;cur_env = env_pop(cur_env);} ; decls : decls decl {println("rule: decls -> decls decl"); $$=$2;} | /*empty*/ {println("rule: decls -> empty");} | error {fprintf(stderr,"error in parsing declaration at %s, line %d\n",yytext,yylineno);} ; decl : type ID ';' {println("rule: decl -> type id;"); $$ = setID($1,$2);} ; type : type '[' NUM ']' {println("rule: type -> type [ num ]"); $$ = makeArray($1,$3);} | BASIC {println("rule: type -> basic"); $$ = makeType($1);} ; stmts : stmts stmt {println("rule: stmts -> stmts stmt");if($1 == NULL) {$$=$2;} else { $$=$1; makeNextlist($1,$2);}} | /**empty*/ {println("rule: stmts -> empty");} ; /*all the various types of statments: if, while, do while, and break*/ stmt: loc '=' bool_ ';' {println("rule: loc = bool");$$=assignValue($1,$3,code_list, cur_env);} | IF '(' bool_ ')' stmt %prec REDUCE{println("rule: stmt -> if (bool) stmt");$$=handleIf($3,$5,code_list);} | IF '(' bool_ ')' stmt ELSE {gen2(code_list,NULL,NULL,NULL,NULL);} stmt {println("rule: stmt -> if (bool) stmt else stmt");$$=handleIfElse($3,$5,$7,code_list);} //not handeling while until I get blocks working right | WHILE '(' bool_ ')' stmt {println("rule: stmt -> while(bool) stmt");printf("\n");$$ = handleWhile($3,$5,code_list);} | DO stmt WHILE '(' bool_ ')'';' {println("rule: stmt -> do stmt while (bool)"); $$ = handleDoWhile($5,$2,code_list);} | BREAK ';' {println("rule: stmt -> break"); $$ = handleBreak(code_list);} | block {println("rule: stmt -> block");$$=$1;} ; /*how to reference ids*/ loc : loc '['bool_ ']' {println("rule: loc -> loc[bool]");$$ = makeArrayAddr($1,$3,code_list,cur_env);} | ID {println("rule: loc -> id");$$ = getSymbol($1,cur_env);} ; bool_ : bool_ OR_OP join {println("rule: bool -> bool || join");$$=makeOr($1,$3,code_list);} | join {println("rule: bool -> join");$$=$1;} ; join : join AND_OP equality {println("rule: join -> join && equality");$$=makeAnd($1,$3, code_list);} | equality {println("rule: join -> equality");$$=$1;} ; equality : equality EQ_OP rel {println("rule: equality -> equality == rel"); $$=makeRel($1,"==",$3,code_list,cur_env);} | equality NE_OP rel {println("rule: equality -> equality != rel");$$=makeRel($1,"!=",$3,code_list,cur_env);} | rel {println("rule: equality -> rel");$$=$1;} ; rel : expr '<' expr {println("rule: rel -> expr < expr");$$=makeRel($1,"<",$3,code_list,cur_env);} | expr LE_OP expr {println("rule: rel -> expr <= expr");$$=makeRel($1,"<=",$3,code_list, cur_env);} | expr GE_OP expr {println("rule: rel -> expr >= expr");$$=makeRel($1,">=",$3,code_list,cur_env);} | expr '>' expr {println("rule: rel -> expr > expr");$$=makeRel($1,">",$3,code_list,cur_env);} | expr {println("rule: rel -> expr");$$=$1;} ; expr : expr'+'term {println("rule: expr -> expr + term");$$=makeOp($1,"+",$3,code_list,cur_env);} | expr'-'term {println("rule: expr -> expr - term");$$=makeOp($1,"-",$3,code_list,cur_env);} | term {println("rule: expr -> term");$$=$1;} ; term : term'*'unary {println("rule: term -> term * unary");$$=makeOp($1,"*",$3,code_list,cur_env);} | term'/'unary {println("rule: term -> term / unary");$$=makeOp($1,"/",$3,code_list,cur_env);} | unary {println("rule: term -> unary");$$=$1;} ; unary : '-' unary %prec UMINUS {println("rule: unary -> - unary");$$=makeOp(NULL,"-",$2,code_list,cur_env);} | '!' unary {println("rule: bool-> ! (bool)");$$ = makeOp(NULL, "!",$2,code_list,cur_env);} | factor {println("rule: unary -> factor");$$=$1;} ; factor : '(' bool_ ')' {println("rule: factor -> (bool)");$$ = $2;} | loc {println("rule: factor -> loc"); $$=$1;} | NUM {println("rule: factor -> num"); $$ = makeNum($1);} | REAL {println("rule: factor -> real"); $$ = makeReal($1);} | BOOL {println("rule: factor -> bool");$$= makeBool($1,code_list);} | error {fprintf(stderr,"error: unable to determine type of token %s at line %d",yytext,yylineno);} ; %% list_head_t *list; /**type is an id_type struct, size is a void* to yylval. This mallocs another id_type, and sets everything for the array*/ void *makeArray(void *type, void* size) { id_type_t *newArray = malloc(sizeof(id_type_t)); id_type_t*parent = (id_type_t*)type; newArray->subtype = parent; newArray->dimension = parent->dimension + 1; newArray->type = parent->type; newArray->size = *((int*)size); newArray->temp = parent->temp; parent->supertype = newArray; newArray->loc = parent->loc; parent->loc = -1; return newArray; } /*defines the type of an ID based on the declaration*/ void *makeType(void *type) { id_type_t *newType = malloc(sizeof(id_type_t)); newType->type = type; newType->dimension = 0; newType->size = 0; newType->subtype = NULL; newType->temp = 0; newType->loc = 0; return newType; } void *setID2(void *type, void*id, env_t* env) { list_entry_t *new_ID = env_insert(env,id,type); if(new_ID == NULL ) { fprintf(stderr, "error: unable to create variable %s at line %d.\nVariable already defined",(char*)id,yylineno); } return new_ID; } /*Puts the new ID from the declaration into the symbol table. uses last_id to get that last list_entry_t*/ void *setID(void *type, void *id) { return setID2(type, id, cur_env); } /*just a small function so I don't have to remember the \\n on the end of every printf*/ void println(char* format) { // printf("%s\n",format); } void printValue(id_type_t *value) { char *type = (value->type == int_var) ? "int" : "float"; printf(" type:%s, dimension:%u, size:%u", type, value->dimension, value->size); if(value->subtype != NULL) { printf(", subtype: {"); printValue(value->subtype); printf("}"); } else { printf(", subtype: NULL"); } if(value->supertype != NULL) { printf(", supertype: %p",((id_type_t*)value)->supertype); } else { printf(", supertype: NULL"); } printf(", loc: %d", value->loc); } //this is the new main, for the parser*/ int main() { meminit(); yylineno = 1; code_list = code_init(); int val = yyparse(); printf("finished parse\n"); print_env(inner_env); printCodeList(code_list); env_delete(inner_env); run_tests(); freeall(); return val; }