PROGRAM 4
%{ /**************************************************************************/ /* author: anthony f. ortiz */ /* program: scanner.l */ /* class: cs 6110 theory and design of compilers */ /* date: november 23, 1998 */ /* description: this program implements the scanner and symbol table */ /* part of a compiler. */ /**************************************************************************/ #include "defs.h" #include "y.tab.h" #include #include #include int hash_it (char * word); struct word * add_symtable (char * word); struct word * lookup_symtable (char * word); void cleanup_symtable (); void print_symtable (); void update_program (char * str); void update_procedure (char * str); void update_procedure2 (char * str); void update_function (char * str, type_t type); void update_parameters (type_t type, int ref); void destroy_paramlist (); void decrement_address (); void increment_address (); void start_addressing (int start); void set_dim0 (); void increment_dim (); void update_variables (char * str, type_t type, int d, int low, int high); void update_varlist (char * str); void destroy_varlist (); void update_variables2 (type_t type, int d, int low, int high); void write_file(void); void print_quad (quad_t qq); void print_prog(void); int start_program (); void quit_program (int top); void handle_integers (type_t type, int value); void handle_reals (type_t type, double value); void handle_variables (type_t type, int first, int index); void handle_assignments (type_t type, int first, int index, type_t type2, int first2); void handle_writes (type_t type, int first); void handle_reads (type_t type, int first, int index); void handle_calculations (type_t type, int first, int sign, type_t type2, int first2); void handle_inequalities (type_t type, int first, int sign, type_t type2, int first2); void handle_bool (type_t type, int first, int sign, type_t type2, int first2); int handle_then (int first); int handle_else (int instr); void handle_end (int instr); int save_loc (); int start_while (int first); void end_while (int start, int end); void handle_procedures (int scope2, type_t type, int return_addr); int start_procedure (); void end_procedure (int top); void handle_return (int first); void save_offsets (); int start_block (); int handle_blocks (); void end_block (int top, int return_addr); void handle_scope (type_t type, int first, int index, int scope2); int declaring = 0; %} %% "and" { yylval.ival = AND; printf (" "); return (AND); } "array" { printf (" "); return (ARRAY); } "boolean" { printf (" "); return (BOOL); } "break" { printf (" "); return (BREAK); } "continue" { printf (" "); return (CONT); } "case" { printf (" "); return (CASE); } "declare" { declaring = 1; printf (" "); return (DECLARE); } "div" { yylval.ival = DIV; printf (" "); return (MULTOP); } "do" { printf (" "); return (DO); } "else" { printf (" "); return (ELSE); } "end" { if (declaring == 1) declaring = 0; printf (" "); return (END); } "function" { declaring = 1; printf (" "); return (FUNCTION); } "if" { printf (" "); return (IF); } "integer" { printf (" "); return (INT); } "mod" { yylval.ival = MOD; printf (" "); return (MULTOP); } "not" { yylval.ival = NOT; printf (" "); return (NOT); } "of" { printf (" "); return (OF); } "or" { yylval.ival = OR; printf (" "); return (OR); } "procedure" { declaring = 1; printf (" "); return (PROCEDURE); } "program" { printf ("\nTOKENS: "); return (PROGRAM); } "read" { printf (" "); return (READ); } "real" { printf (" "); return (REAL); } "ref" { printf (" "); return (REF); } "return" { printf (" "); return (RETURN); } "returns" { printf (" "); return (RETURNS); } "then" { printf (" "); return (THEN); } "while" { printf (" "); return (WHILE); } "write" { printf (" "); return (WRITE); } "true" { yylval.ival = TRUE; printf ("", yylval.ival); return (BCONST); } "false" { yylval.ival = FALSE; printf ("", yylval.ival); return (BCONST); } [ \n\t]+ {/* white space */} "//".*"\n" {/* comments */} ":=" { printf (" "); return (ASSGN); } ":" { printf (" "); return (COL); } "," { printf (" "); return (COMMA); } "=" { yylval.ival = EQ; printf (" "); return (RELOP); } "/" { yylval.ival = FDIV; printf (" "); return (MULTOP); } ">=" { yylval.ival = GEQ; printf (" "); return (RELOP); } ">" { yylval.ival = GR; printf (" "); return (RELOP); } [A-Za-z_][A-Za-z0-9_]* { yylval.pval = lookup_symtable (yytext); if (yylval.pval == NULL || declaring == 1) { yylval.pval = add_symtable (yytext); } printf (" ", yytext); return (IDENT); } [0-9]+ { yylval.ival = atoi (yytext); printf (" ", yylval.ival); return (INTCONST); } "[" { printf (" "); return (LBRACK); } "{" { printf (""); return (LBRACE); } "<=" { yylval.ival = LEQ; printf (" "); return (RELOP); } "<" { yylval.ival = LESS; printf (" "); return (RELOP); } "(" { printf (" "); return (LP); } "-" { yylval.ival = MINUS; printf (" "); return (ADDOP); } "!=" { yylval.ival = NEQ; printf (" "); return (RELOP); } "+" { yylval.ival = PLUS; printf (" "); return (ADDOP); } ".." { printf (" "); return (RANGE); } "]" { printf (" "); return (RBRACK); } "}" { printf (" "); return (RBRACE); } ")" { printf (" "); return (RP); } (([0-9]+)|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { yylval.rval = (float) (atof (yytext)); printf ("", yylval.rval); return (REALCONST); } ";" { if (declaring == 1) declaring = 0; printf (" "); return (SC); } "*" { yylval.ival = TIMES; printf (" "); return (MULTOP); } %% /* my main function is in the parse.y file. */ /* my structures and enumerations are in defs.h. */ int scope = 1; int address = 1; int dim = 0; int next_instr = 2; char * op_name [] = {"add", "sub", "mult", "idiv", "neg", "less", "equ", "fadd", "fsub", "fmult", "fdiv", "fneg", "fless", "fequ", "itor", "mov", "inxld", "inxst", "movim", "movad", "movabs", "bnot", "band", "bor", "bequ", "gto", "jmp", "iread", "rread", "iwrite", "rwrite", "call", "ret", "halt"}; mem_t mem [MAXMEM]; /* main memory */ mem_t * p; /* working pointer */ struct word * word_list [211]; /* the hash table with open chaining */ struct p_struct * par_type; /* linked list of parameters */ struct v_struct * var_type; /* linked list of variables */ int offsets [10]; /* beginning address for proc and func */ /* hash word using formula in aho, sethi, and ullman. */ int hash_it (char * word) { char * p; unsigned h = 0; unsigned g; for (p = word; * p != '\0'; p = p + 1) { h = (h << 4) + (* p); if (g = h&0xf0000000) { h = h ^ (g >> 24); h = h ^ g; } } return h % 211; } /* add identifier to symbol table. */ struct word * add_symtable (char * word) { struct word * wp; int h = hash_it (word); /* word not there, allocate a new entry and link it on the list. */ wp = (struct word *) malloc (sizeof (struct word)); wp -> next = word_list [h]; /* have to copy the word itself as well. */ wp -> word_name = (char *) malloc (strlen (word) + 1); strcpy (wp -> word_name, word); word_list [h] = wp; return wp; /* it worked. */ } /* lookup identifier in symbol table, return 0 if not found, 1 if found. */ struct word * lookup_symtable (char * word) { struct word * wp; int h = hash_it (word); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, word) == 0) return wp; } return NULL; /* not found. */ } /* clean up table. */ void cleanup_symtable () { int i; struct word * wp; /* remove current scope idents. */ for (i = 0; i < 211; i++) { wp = word_list [i]; for (; wp; wp = wp -> next) { if (wp -> sc_level == scope && (wp -> type == int_t || wp -> type == real_t || wp -> type == bool_t)) strcpy (wp -> word_name, "removed "); } } } /* print identifiers in symbol table. */ void print_symtable () { struct word * wp; int h; printf ("\n\nSymbol Table\n\n"); /* print list. */ printf (" name scope type dim low"); printf (" high first return\n\n"); for (h = 0; h < 211; h++) { wp = word_list [h]; for (; wp; wp = wp -> next) { printf ("%10s %8d %8d", wp -> word_name, wp -> sc_level, wp -> type); if (wp -> type >= 1 && wp -> type <= 3) { printf ("%8d %8d %8d %8d\n", wp -> dim, wp -> low, wp -> high, wp -> first); } else if (wp -> type == 4) { printf ("%8d %26d %8d\n", wp -> dim, wp -> first, wp -> ret_type); } else if (wp -> type == 5) { printf ("%8d %26d\n", wp -> dim, wp -> first); } else printf ("\n"); if ((wp -> type == 4 || wp -> type == 5) && wp -> params != NULL) { for (; wp -> params; wp -> params = wp -> params -> next) { printf ("params, type: %d location: %d ref: %d\n", wp -> params -> type, wp -> params -> p_loc, wp -> params -> isref); } } } } printf ("\n"); } /* increment scope by 1. */ increment_scope () { scope = scope + 1; } /* decrement scope by 1. */ decrement_scope () { scope = scope - 1; } /* update program. */ void update_program (char * str) { struct word * wp; int h = hash_it (str); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, str) == 0) { wp -> sc_level = scope; wp -> type = program_t; break; } } } /* update procedure. */ void update_procedure (char * str) { struct word * wp; int h = hash_it (str); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, str) == 0) { wp -> sc_level = scope; wp -> type = proc_t; wp -> dim = dim; wp -> first = next_instr; wp -> params = par_type; break; } } } /* update procedure2. */ void update_procedure2 (char * str) { struct word * wp; int h = hash_it (str); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, str) == 0) { wp -> first = next_instr; break; } } } /* update function. */ void update_function (char * str, type_t type) { struct word * wp; int h = hash_it (str); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, str) == 0) { wp -> sc_level = scope; wp -> type = funct_t; wp -> dim = dim; wp -> ret_type = type; wp -> dim = dim; wp -> first = next_instr; wp -> params = par_type; break; } } } /* update parameters. */ void update_parameters (type_t type, int ref) { struct p_struct * pp; pp = (struct p_struct *) malloc (sizeof (struct p_struct)); pp -> next = par_type; /* have to copy it as well. */ pp -> type = type; pp -> p_loc = address; pp -> isref = ref; par_type = pp; } /* destroy parameter list. */ void destroy_paramlist () { par_type = NULL; } /* decrement address. */ void decrement_address () { address = address - 1; } /* increment_address. */ void increment_address () { address = address + 1; } /* start address at 1 or -4. */ void start_addressing (int start) { address = start; } /* start dim at 0. */ void set_dim0 () { dim = 0; } /* increment dim for procedures and functions. */ void increment_dim () { dim = dim + 1; } /* update variables. */ void update_variables (char * str, type_t type, int d, int low, int high) { struct word * wp; int h = hash_it (str); wp = word_list [h]; /* search down the list looking for the word. */ for (; wp; wp = wp -> next) { if (strcmp (wp -> word_name, str) == 0) { wp -> sc_level = scope; wp -> type = type; wp -> first = address - low; wp -> dim = d; if (wp -> dim == 1) { wp -> low = low; wp -> high = high; address = address + high - low + 1; } else if (wp -> first < 0) { decrement_address (); } else if (wp -> first >= 1) { increment_address (); } break; } } } /* update variable list. */ void update_varlist (char * str) { struct v_struct * vp; vp = (struct v_struct *) malloc (sizeof (struct v_struct)); vp -> next = var_type; /* have to copy it as well. */ vp -> name = str; var_type = vp; } /* destroy variable list. */ void destroy_varlist () { var_type = NULL; } /* update variables in symbol table. */ void update_variables2 (type_t type, int d, int low, int high) { struct v_struct * vp; vp = var_type; /* update each variable in variable list linked list to symbol table. */ for (; vp; vp = vp -> next) { update_variables (vp -> name, type, d, low, high); } } /* this simply generates the next quad and updates a global counter, which i have called "next_instr" and kept pointing to the next free mem space. */ void put_quad (op_t operator, int operand1, int operand2, int destination) { /* this generates the next quad in the array mem and increments the next_instr index, which is kept pointing to the next free space. */ mem_t *p; p = &(mem[next_instr++]); /* get address and increment index. */ p->op = operator; p->opd1 = operand1; p->opd2 = operand2; p->dest = destination; } /* this is my utility to dump the quad array (mem) to a file. it requires that you #include in order to get the definitions for the constants o_wronly, etc. this version has a default filename "hard coded", but that, of course, could be changed. */ void write_file(void) { int ofd; int n; if((ofd = open("outfile.exec", O_WRONLY | O_TRUNC |O_CREAT, 0600)) <= 0) { perror(" Can't write outfile"); exit(1); } n = write(ofd, mem, next_instr * sizeof(mem_t)); fprintf(stderr, "Wrote out %d instructions\n", n / sizeof(mem_t)); } /* this will print out a single quad. */ void print_quad(quad_t qq) { printf("(%7s, %4d, %4d, %4d)\n", op_name[qq._op], qq._opd1,qq._opd2, qq._dest); } /* this can be used to print out the quads you have generated while they are still in memory. it is what i have called at the end of my compiler in order to produce the output i have included on class handouts. */ void print_prog(void) { int n; printf("PC = %d\n", mem[0].ival); printf("SP = %d\n", mem[1].ival); for(n=2; n < next_instr; n++) { printf("%4d: ", n); print_quad(mem[n].quad); if(mem[n].op == movim) { ++n; printf("%4d: (** %8d // %e **)\n", n, mem[n].ival, mem[n].rval); } } } /* start program. */ int start_program () { address = offsets [scope - 1]; put_quad (movim, 0, 0, -1); next_instr++; /* skip the constant top and fill it in at end. */ return (next_instr - 1); } /* quit program. */ void quit_program (int top) { put_quad (halt, 0, 0, 0); PC = top - 1; SP = next_instr + 4; mem [top].ival = address; } /* handle integers. */ void handle_integers (type_t type, int value) { i.type = type; i.first = address; i.index = 0; put_quad (movim, 0, 0, address); if (type == int_t) { mem [next_instr].ival = value; } else if (type == bool_t && value == TRUE) { mem [next_instr].ival = true; } else if (type == bool_t && value == FALSE) { mem [next_instr].bval = false; } next_instr = next_instr + 1; address = address + 1; } /* handle reals. */ void handle_reals (type_t type, double value) { i.type = type; i.first = address; i.index = 0; put_quad (movim, 0, 0, address); if (type == real_t) { printf ("here it is %f", value); mem [next_instr].rval = value; } next_instr = next_instr + 1; address = address + 1; } /* handle variables. */ void handle_variables (type_t type, int first, int index) { if (index == 0) { i.type = type; i.first = first; i.index = index; } else if (index != 0) { i.type = type; i.first = address; i.index = 0; put_quad (inxld, first , index , address); address = address + 1; } } /* handle assignments. */ void handle_assignments (type_t type, int first, int index, type_t type2, int first2) { if (type == real_t && type2 == int_t) { put_quad (itor, first2, 0, address); first2 = address; type2 = real_t; address++; } if (index == 0 && type == type2) { put_quad (mov, first2, 0, first); } else if (type == type2) { put_quad (inxst, first2, index, first); } } /* handle writes. */ void handle_writes (type_t type, int first) { if (type == int_t) { put_quad (iwrite, first, 0, 0); } else if (type == real_t) { put_quad (rwrite, first, 0, 0); } } /* handle reads. */ void handle_reads (type_t type, int first, int index) { if (type == int_t && index == 0) { put_quad (iread, 0, 0, first); } else if (type == real_t && index == 0) { put_quad (rread, 0, 0, first); } else if (type == int_t && index > 0) { put_quad (iread, 0, 0, address); put_quad (inxst, address, index, first); address++; } else if (type == real_t && index > 0) { put_quad (rread, 0, 0, address); put_quad (inxst, address, index, first); address++; } } /* handle calculations. */ void handle_calculations (type_t type, int first, int sign, type_t type2, int first2) { if (type == int_t && type2 == real_t) { put_quad (itor, first, 0, address); first = address; type = real_t; address++; } else if (type == real_t && type2 == int_t) { put_quad (itor, first2, 0, address); first2 = address; type2 = real_t; address++; } else if (sign == FDIV && type == int_t && type2 == int_t) { put_quad (itor, first, 0, address); first = address; type = real_t; address++; put_quad (itor, first2, 0, address); first2 = address; type2 = real_t; address++; } if (sign == MOD && type == int_t && type2 == int_t) { int temp; put_quad (idiv, first, first2, address); temp = address; address++; put_quad (mult, temp, first2, address); temp = address; address++; put_quad (sub, first, temp, address); } else if (sign == PLUS && type == int_t && type2 == int_t) { put_quad (add, first, first2, address); } else if (sign == PLUS && type == real_t && type2 == real_t) { put_quad (fadd, first, first2, address); } else if (sign == MINUS && type == int_t && type2 == int_t) { put_quad (sub, first, first2, address); } else if (sign == MINUS && type == real_t && type2 == real_t) { put_quad (fsub, first, first2, address); } else if (sign == TIMES && type == int_t && type2 == int_t) { put_quad (mult, first, first2, address); } else if (sign == TIMES && type == real_t && type2 == real_t) { put_quad (fmult, first, first2, address); } else if ((sign == FDIV || sign == DIV) && type == int_t && type2 == int_t) { put_quad (idiv, first, first2, address); } else if (sign == FDIV && type == real_t && type2 == real_t) { put_quad (fdiv, first, first2, address); } else if (sign == MINUS && type == int_t) { put_quad (neg, first, 0, address); } else if (sign == MINUS && type == real_t) { put_quad (fneg, first, 0, address); } if ((type == type2 || type2 == 0) && (type == real_t || type == int_t)) { i.type = type; i.first = address; i.index = 0; address++; } } /* handle inequalities. */ void handle_inequalities (type_t type, int first, int sign, type_t type2, int first2) { if (type == int_t && type2 == real_t) { put_quad (itor, first, 0, address); first = address; type = real_t; address++; } else if (type == real_t && type2 == int_t) { put_quad (itor, first2, 0, address); first2 = address; type2 = real_t; address++; } if (sign == LESS && type == int_t && type2 == int_t) { put_quad (less, first, first2, address); } else if (sign == LESS && type == real_t && type2 == real_t) { put_quad (fless, first, first2, address); } else if (sign == GR && type == int_t && type2 == int_t) { put_quad (less, first2, first, address); } else if (sign == GR && type == real_t && type2 == real_t) { put_quad (fless, first2, first, address); } else if (sign == EQ && type == bool_t && type2 == bool_t) { put_quad (bequ, first, first2, address); } else if (sign == EQ && type == int_t && type2 == int_t) { put_quad (equ, first, first2, address); } else if (sign == EQ && type == real_t && type2 == real_t) { put_quad (fequ, first, first2, address); } else if (sign == NEQ && type == int_t && type2 == int_t) { int temp; put_quad (equ, first, first2, address); temp = address; address++; put_quad (bnot, temp, 0, address); } else if (sign == NEQ && type == real_t && type2 == real_t) { int temp; put_quad (fequ, first, first2, address); temp = address; address++; put_quad (bnot, temp, 0, address); } else if (sign == LEQ && type == int_t && type2 == int_t) { int temp; put_quad (less, first2, first, address); temp = address; address++; put_quad (bnot, temp, 0, address); } else if (sign == LEQ && type == real_t && type2 == real_t) { int temp; put_quad (fless, first2, first, address); temp = address; address++; put_quad (bnot, temp, 0, address); } else if (sign == GEQ && type == int_t && type2 == int_t) { int temp; put_quad (less, first, first2, address); temp = address; address++; put_quad (bnot, temp, 0, address); } else if (sign == GEQ && type == real_t && type2 == real_t) { int temp; put_quad (fless, first, first2, address); temp = address; address++; put_quad (bnot, temp, 0, address); } if (type == type2 && (type == int_t || type == real_t || type == bool_t)) { i.type = bool_t; i.first = address; i.index = 0; address++; } } /* handle boolean algebra. */ void handle_bool (type_t type, int first, int sign, type_t type2, int first2) { if (sign == AND && type == bool_t && type2 == bool_t) { put_quad (band, first, first2, address); } else if (sign == OR && type == bool_t && type2 == bool_t) { put_quad (bor, first, first2, address); } else if (sign == NOT && type == bool_t) { put_quad (bnot, first, 0, address); } if ((type == type2 || type2 == 0) && type == bool_t) { i.type = type; i.first = address; i.index = 0; address++; } } /* handle then. */ int handle_then (int first) { put_quad (bnot, first, 0, address); put_quad (jmp, address, 0, 0); address++; return next_instr - 1; } /* handle else. */ int handle_else (int instr) { int i; put_quad (gto, 0, 0, 0); mem [instr].quad._dest = next_instr; return next_instr - 1; } /* handle end. */ void handle_end (int instr) { mem [instr].quad._dest = next_instr; } /* save location of beginning while. */ int save_loc () { return next_instr; } /* start while. */ int start_while (int first) { put_quad (bnot, first, 0, address); put_quad (jmp, address, 0, 0); address++; return next_instr - 1; } /* end while. */ void end_while (int begin, int end) { put_quad (gto, 0, 0, begin); mem [end].quad._dest = next_instr; } /* handle procedures. */ void handle_procedures (int scope2, type_t type, int return_addr) { int temp; if (scope2 - scope >= 2) { /* do nothing */ } else { if (scope >= scope2) { int i; put_quad (mov, -2, 0, address); temp = address; address++; for (i = scope2; i <= scope; i++) { put_quad (inxld, -2, temp, address); put_quad (add, temp, address, temp); } put_quad (movim, 0, 0, address); mem [next_instr].ival = 4; next_instr++; put_quad (sub, temp, address, temp); put_quad (mov, -1, 0, address); } else { put_quad (mov, -1, 0, address); put_quad (neg, address, 0, address); temp = address; address++; put_quad (movim, 0, 0, address); mem [next_instr].ival = 4; next_instr++; } put_quad (sub, temp, address, temp); address++; put_quad (inxst, temp, -1, 2); put_quad (movabs, 1, 0, address); put_quad (inxst, address, -1, 4); address++; put_quad (movim, 0, 0, address); mem [next_instr].ival = next_instr + 3; next_instr++; put_quad (inxst, address, -1, 1); address++; put_quad (call, return_addr, 0, 0); if (type == funct_t) { put_quad (inxld, 0, -1, address); i.first = address; i.index = 0; address++; } } } /* start procedure. */ int start_procedure () { address = offsets [scope - 1]; put_quad (movim, 0, 0, -1); next_instr++; return (next_instr - 1); } /* end procedure. */ void end_procedure (int top) { put_quad (ret, 0, 0, 0); mem [top].ival = address; } /* handle return. */ void handle_return (int first) { put_quad (mov, first, 0, -4); } /* save offsets. */ void save_offsets () { offsets [scope - 1] = address; } /* start block. */ int start_block () { address = offsets [scope - 1]; put_quad (movim, 0, 0, -1); next_instr++; return (next_instr - 1); } /* handle blocks. */ int handle_blocks () { int temp, return_addr; put_quad (mov, -1, 0, address); put_quad (neg, address, 0, address); temp = address; address++; put_quad (movim, 0, 0, address); mem [next_instr].ival = 4; next_instr++; put_quad (sub, temp, address, temp); address++; put_quad (inxst, temp, -1, 2); put_quad (movabs, 1, 0, address); put_quad (inxst, address, -1, 4); address++; put_quad (movim, 0, 0, address); next_instr++; return_addr = next_instr - 1; put_quad (inxst, address, -1, 1); address++; offsets [scope - 1] = address; put_quad (call, next_instr + 1, 0, 0); return return_addr; } /* end block. */ void end_block (int top, int return_addr) { put_quad (ret, 0, 0, 0); mem [top].ival = address; mem [return_addr].ival = next_instr; address = offsets [scope - 1]; } /* handle scope to find non-locals. */ void handle_scope (type_t type, int first, int index, int scope2) { if ((scope - scope2) == 0) { i.type = type; i.first = first; i.index = index; } else if ((scope - scope2) == 1) { if (index != 0) { put_quad (add, index, -2, address); i.index = address; address++; } else { i.index = -2; } i.type = type; i.first = first; } else if ((scope - scope2) > 1) { int j, temp, temp2; put_quad (mov, -2, 0, address); temp = address; address++; temp2 = address; for (j = 1; j < (scope - scope2); j++) { put_quad (inxld, -2, temp, address); put_quad (add, address, temp, temp); if (index != 0) { int temp2; put_quad (add, index, temp, address); temp2 = temp; temp = address; address = temp2; } } i.type = type; i.first = first; i.index = temp; address = temp2 + 1; } } /**************************************************************************/ /* author: anthony f. ortiz */ /* program: parser.y */ /* class: cs6110-01 */ / /* date: november 23, 1998 */ /* description: this program describes and parses a grammar. */ /**************************************************************************/ %{ #include "defs.h" #include #include #include %} %token AND %token ARRAY %token BOOL /* "boolean" */ %token BREAK %token CONT /* "continue" */ %token CASE %token DECLARE %token DIV %token DO %token ELSE %token END %token FUNCTION %token IF %token INT /* "integer" */ %token MOD %token NOT %token OF %token OR %token PROCEDURE %token PROGRAM %token READ %token REAL %token REF %token RETURN %token RETURNS %token THEN %token WHILE %token WRITE %token TRUE %token FALSE %token ADDOP %token ASSGN /* ":=" */ %token BCONST /* boolean constant */ %token COL /* ":" */ %token COMMA /* "," */ %token EQ /* "=" */ %token FDIV /* "/" */ %token GEQ /* ">=" */ %token GR /* ">" */ %token IDENT /* identifier */ %token INTCONST /* integer constant */ %token LBRACK /* "[" */ %token LBRACE /* "{" */ %token LEQ /* "<=" */ %token LESS /* "<" */ %token LP /* "(" */ %token MINUS /* "-" */ %token MULTOP %token NEQ /* "!=" */ %token PLUS /* "+" */ %token RANGE /* ".." */ %token RBRACK /* "]" */ %token RBRACE /* "}" */ %token RELOP %token RP /* ")" */ %token REALCONST /* real constant */ %token SC /* ";" */ %token TIMES /* "*" */ %type simpletype %type variable %type expression %type ifstatement %type statement %type program %type procdecl %type block %type procheader /* yystype structure */ %union {int ival; float rval; bool bval; type_t tval; struct info infoval; char * cval; struct word * pval;} %left OR %left AND %nonassoc RELOP %left ADDOP %left MULTOP %right NOT %right UMINUS %% start : program; program : PROGRAM IDENT SC vardeclar procdeclist LBRACE {$$ = start_program ();} statlist RBRACE {update_program ($2 -> word_name); quit_program ($7);} ; vardeclar : {start_addressing (1);} DECLARE vardeclist END SC | {start_addressing (1); save_offsets ();} /* empty */ ; vardeclist : decl vardeclist {save_offsets ();} | /* empty */ ; decl : identlist COL simpletype SC {update_variables2 ($3, 0, 0, 0); destroy_varlist ();} | identlist COL arraytype SC {destroy_varlist ();} ; identlist : identlist COMMA IDENT {update_varlist ($3 -> word_name);} | IDENT {update_varlist ($1 -> word_name);} ; simpletype : INT {$$ = int_t;} | REAL {$$ = real_t;} | BOOL {$$ = bool_t;} ; arraytype : ARRAY LBRACK INTCONST RANGE INTCONST RBRACK OF simpletype {update_variables2 ($8, 1, $3, $5);} ; procdeclist : procdecl procdeclist | /* empty */ ; procdecl : procheader vardeclar procdeclist LBRACE {update_procedure2 ($1); $$ = start_procedure ();} statlist RBRACE {cleanup_symtable (); end_procedure ($5); decrement_scope ();} ; procheader : {increment_scope (); start_addressing (-4);} PROCEDURE IDENT params SC {update_procedure ($3 -> word_name); destroy_paramlist (); set_dim0 (); $$ = $3 -> word_name;} | {increment_scope (); start_addressing (-4);} FUNCTION IDENT params RETURNS simpletype SC {update_function ($3 -> word_name, $6); destroy_paramlist (); set_dim0 (); $$ = $3 -> word_name;} ; params : LP paramlist RP | /* empty */ ; paramlist : parameter | paramlist COMMA parameter ; parameter : IDENT COL simpletype {update_parameters ($3, 0); update_variables ($1 -> word_name, $3, 0, 0, 0); increment_dim ();} | REF IDENT COL simpletype {update_parameters ($4, 1); update_variables ($2 -> word_name, $4, 0, 0, 0); increment_dim ();} ; block : {$$ = handle_blocks (); increment_scope ();} LBRACE vardeclar {$$ = start_block ();} statlist RBRACE {decrement_scope (); end_block ($4, $1);} ; statlist : statlist statement | statement ; statement : variable ASSGN expression SC {handle_assignments ($1.type, $1.first, $1.index, $3.type, $3.first);} | ifstatement {} | WHILE {$$ = save_loc ();} expression DO {$$ = start_while ($3.first);} statlist END {end_while ($2, $5);} | CASE expression OF caselist END SC {} | RETURN expression SC {handle_return ($2.first);} | BREAK SC {} | CONT SC {} | READ variable SC {handle_reads ($2.type, $2.first, $2.index);} | WRITE expression SC {handle_writes ($2.type, $2.first);} | procedurecall SC {} | block {} | SC /* empty */ {} ; ifstatement : IF expression THEN {$$ = handle_then ($2.first);} statlist {$$ = handle_else ($4);} elsepart {handle_end ($6);} ; elsepart : ELSE statlist END SC | END SC /* empty */ ; caselist : casebranch caselist | /* empty */ ; casebranch : labellist COL statement ; labellist : INTCONST COMMA labellist | INTCONST ; procedurecall : IDENT {handle_procedures ($1 -> sc_level, $1 -> type, $1 -> first);} | callwithparameters ; callwithparameters : IDENT LP actuals RP ; actuals : actuals COMMA expression | expression ; variable : IDENT LBRACK expression RBRACK {handle_scope ($1 -> type, $1 -> first, $3.first, $1 -> sc_level); $$ = i;} | IDENT {if ($1 -> type == funct_t) { handle_procedures ($1 -> sc_level, $1 -> type, $1 -> first); $$.type = $1 -> ret_type; $$.first = i.first; $$.index = i.index; } else { handle_scope ($1 -> type, $1 -> first, $1 -> dim, $1 -> sc_level); $$ = i; } } | callwithparameters {} ; expression : expression OR expression {handle_bool ($1.type, $1.first, $2, $3.type, $3.first); $$ = i;} | expression AND expression {handle_bool ($1.type, $1.first, $2, $3.type, $3.first); $$ = i;} | expression RELOP expression {handle_inequalities ($1.type, $1.first, $2, $3.type, $3.first); $$ = i;} | expression ADDOP expression {handle_calculations ($1.type, $1.first, $2, $3.type, $3.first); $$ = i;} | expression MULTOP expression {handle_calculations ($1.type, $1.first, $2, $3.type, $3.first); $$ = i;} | ADDOP expression %prec UMINUS {handle_calculations ($2.type, $2.first, $1, 0, 0); $$ = i;} | NOT expression {handle_bool ($2.type, $2.first, $1, 0, 0); $$ = i;} | variable {handle_variables ($1.type, $1.first, $1.index); $$ = i;} | BCONST {handle_integers (bool_t, $1); $$ = i;} | INTCONST {handle_integers (int_t, $1); $$ = i;} | REALCONST {handle_reals (real_t, $1); $$ = i;} | LP expression RP {$$ = $2;} ; %% extern FILE * yyin; /* read from a file specified by the command line and parse. */ main (int argc, char ** argv) { if (argc > 1) { FILE *file; file = fopen (argv [1], "r"); if (!file) { fprintf (stderr, "could not open %s\n", argv [1]); } yyin = file; } yyparse (); print_symtable (); write_file (); } /* print a error message. */ yyerror (s) char * s; { printf ("%s\n", s); } /* filename: defs.h */ /* see program 1. */ /* data file: test1.dat */ // hello. program test; declare x, y, z : integer; u, v : real; end; { read x; read y; write x; write y; z := 5; u := (x + y)/2; v := 7.8; z := x mod y ; write z; write u; u := 0.0; if x > y then while (x > y) do u := u + -7*y; y := y + 1; end; else // One should have x <= y at this point. while x != y do if x > y div 2 then x := x + 1; y := y + 7; else // x <= y div 2 here. x := 2 * x; if x > y then x := y; else y := x; end; end; end; end; write x; write y; write z; write u; write v; } /* outfile: prog4.out */ TOKENS: < SC, > Symbol Table name scope type dim low high first return u 1 2 0 0 0 5 v 1 2 0 0 0 4 x 1 1 0 0 0 3 y 1 1 0 0 0 2 z 1 1 0 0 0 1 test 1 6 Wrote out 85 instructions Read program into 85 mem locations. 2: ( movim, 0, 0, -1) 3: (** 43 // 6.025583e-44 **) Dest_val = (*** 43: 6.025583e-44 ***) 4: ( iread, 0, 0, 3) Enter integer: 4 5: ( iread, 0, 0, 2) Enter integer: 7 6: ( iwrite, 3, 0, 0) >> 4 7: ( iwrite, 2, 0, 0) >> 7 8: ( movim, 0, 0, 6) 9: (** 5 // 7.006492e-45 **) Dest_val = (*** 5: 7.006492e-45 ***) 10: ( mov, 6, 0, 1) Dest_val = (*** 5: 7.006492e-45 ***) 11: ( add, 3, 2, 7) Dest_val = 11 12: ( movim, 0, 0, 8) 13: (** 2 // 2.802597e-45 **) Dest_val = (*** 2: 2.802597e-45 ***) 14: ( itor, 7, 0, 9) Dest_val = 1.100000e+01 15: ( itor, 8, 0, 10) Dest_val = 2.000000e+00 16: ( fdiv, 9, 10, 11) Dest_val = 5.500000e+00 17: ( mov, 11, 0, 5) Dest_val = (*** 1085276160: 5.500000e+00 ***) 18: ( movim, 0, 0, 12) 19: (** 1090099610 // 7.800000e+00 **) Dest_val = (*** 1090099610: 7.800000e+00 ***) 20: ( mov, 12, 0, 4) Dest_val = (*** 1090099610: 7.800000e+00 ***) 21: ( idiv, 3, 2, 13) Dest_val = 0 22: ( mult, 13, 2, 14) Dest_val = 0 23: ( sub, 3, 14, 15) Dest_val = 4 24: ( mov, 15, 0, 1) Dest_val = (*** 4: 5.605194e-45 ***) 25: ( iwrite, 1, 0, 0) >> 4 26: ( rwrite, 5, 0, 0) >> 5.500000e+00 27: ( movim, 0, 0, 16) 28: (** 0 // 0.000000e+00 **) Dest_val = (*** 0: 0.000000e+00 ***) 29: ( mov, 16, 0, 5) Dest_val = (*** 0: 0.000000e+00 ***) 30: ( less, 2, 3, 17) Dest_val = false 31: ( bnot, 17, 0, 18) Dest_val = true 32: ( jmp, 18, 0, 49) PC set to 49 49: ( equ, 3, 2, 28) Dest_val = false 50: ( bnot, 28, 0, 29) Dest_val = true 51: ( bnot, 29, 0, 30) Dest_val = false 52: ( jmp, 30, 0, 79) PC inc to 53 53: ( movim, 0, 0, 31) 54: (** 2 // 2.802597e-45 **) Dest_val = (*** 2: 2.802597e-45 ***) 55: ( idiv, 2, 31, 32) Dest_val = 3 56: ( less, 32, 3, 33) Dest_val = true 57: ( bnot, 33, 0, 34) Dest_val = false 58: ( jmp, 34, 0, 68) PC inc to 59 59: ( movim, 0, 0, 35) 60: (** 1 // 1.401298e-45 **) Dest_val = (*** 1: 1.401298e-45 ***) 61: ( add, 3, 35, 36) Dest_val = 5 62: ( mov, 36, 0, 3) Dest_val = (*** 5: 7.006492e-45 ***) 63: ( movim, 0, 0, 37) 64: (** 7 // 9.809089e-45 **) Dest_val = (*** 7: 9.809089e-45 ***) 65: ( add, 2, 37, 38) Dest_val = 14 66: ( mov, 38, 0, 2) Dest_val = (*** 14: 1.961818e-44 ***) 67: ( gto, 0, 0, 78) PC set to 78 78: ( gto, 0, 0, 49) PC set to 49 49: ( equ, 3, 2, 28) Dest_val = false 50: ( bnot, 28, 0, 29) Dest_val = true 51: ( bnot, 29, 0, 30) Dest_val = false 52: ( jmp, 30, 0, 79) PC inc to 53 53: ( movim, 0, 0, 31) 54: (** 2 // 2.802597e-45 **) Dest_val = (*** 2: 2.802597e-45 ***) 55: ( idiv, 2, 31, 32) Dest_val = 7 56: ( less, 32, 3, 33) Dest_val = false 57: ( bnot, 33, 0, 34) Dest_val = true 58: ( jmp, 34, 0, 68) PC set to 68 68: ( movim, 0, 0, 39) 69: (** 2 // 2.802597e-45 **) Dest_val = (*** 2: 2.802597e-45 ***) 70: ( mult, 39, 3, 40) Dest_val = 10 71: ( mov, 40, 0, 3) Dest_val = (*** 10: 1.401298e-44 ***) 72: ( less, 2, 3, 41) Dest_val = false 73: ( bnot, 41, 0, 42) Dest_val = true 74: ( jmp, 42, 0, 77) PC set to 77 77: ( mov, 3, 0, 2) Dest_val = (*** 10: 1.401298e-44 ***) 78: ( gto, 0, 0, 49) PC set to 49 49: ( equ, 3, 2, 28) Dest_val = true 50: ( bnot, 28, 0, 29) Dest_val = false 51: ( bnot, 29, 0, 30) Dest_val = true 52: ( jmp, 30, 0, 79) PC set to 79 79: ( iwrite, 3, 0, 0) >> 10 80: ( iwrite, 2, 0, 0) >> 10 81: ( iwrite, 1, 0, 0) >> 4 82: ( rwrite, 5, 0, 0) >> 0.000000e+00 83: ( rwrite, 4, 0, 0) >> 7.800000e+00 84: ( halt, 0, 0, 0) *** Execution complete ***
BACK TO CS6110 PAGE.