COP3402Fall2011: KoolRefParser.c

File KoolRefParser.c, 10.5 KB (added by steven.zittrower, 12 years ago)

Partial Pseudocode of Final Project

Line 
1#include "KoolRefCommon.h"
2#include "KoolRefParser.h"
3
4/**
5 * Basic initialization of all variables and data structures.
6 */
7void basicinit(void) {
8   symtab[0].nesting=NONE;                                              /* fake to not match current level */
9   nesting = GLOBAL;                                                    /* nesting of global declarations is global */
10   
11   /* Enter main slot for pseudo class that encompasses main body of code and global declarations */
12   strcpy(symtab[MAINSLOT].name, "*MAIN*");
13   symtab[MAINSLOT].nesting = nesting;                  /* global */
14   symtab[MAINSLOT].type = CLASS_TYPE;                  /* main entry is pseudo class */
15   symtab[MAINSLOT].cls = MAINSLOT;                             /* class of main slot is self */
16   symtab[MAINSLOT].sym.clazz.num_args = 0;             /* no arguments to main body */
17   symtab[MAINSLOT].sym.clazz.base = 1;                 /* class of main slot is self */
18   
19   /* Enter int slot for pseudo class used presently by all varaibles */
20   strcpy(symtab[INTSLOT].name, "INT"); 
21   symtab[INTSLOT].nesting = nesting;                   /* global */
22   symtab[INTSLOT].type = CLASS_TYPE;                   /* int entry is pseudo class */
23   symtab[INTSLOT].cls = INTSLOT;                               /* INT class is self */
24   symtab[INTSLOT].sym.clazz.num_args = 0;              /* no arguments; actually no method */
25   symtab[INTSLOT].sym.clazz.base = 1;
26   
27   symsize = INTSLOT;                                                   /* Index of last symbol table slot (some reserved) */
28   code[0].opcode[0] = '\0';                                    /* null entry for first triple */
29   showStart = 2;                                                               /* Index of next code slot that has yet to be dumped */
30   triple = 1;                                                                  /* Index of first available code slot */
31   constSize = 0;                                                               /* index of next available constant pool slot */
32   decl_size = 0;                                                               /* space for variable section */
33   errorNo = 0;                                                                 /* Number of errors detected */
34   warnNo = 0;                                                                  /* Number of warnings given */
35}
36
37
38/**
39 * Enter new identifier into symbol table (can be of any type).
40 */
41void enter(void) {
42   if (++symsize < SYM_MAX) {
43      strcpy(symtab[symsize].name, idname); 
44      symtab[symsize].nesting = nesting;
45      symtab[symsize].cls = INTSLOT;
46      yylval.ival = symsize;
47   }
48   else fatal("Symbol table overflow");
49}
50
51
52/**
53 * Store class in symbol table.
54 */
55void store_class(void) {
56   enter();
57   symtab[symsize].type = CLASS_TYPE;
58   symtab[symsize].cls = symsize;
59   symtab[symsize].sym.clazz.num_args = 0;
60   symtab[symsize].sym.clazz.base = triple;
61   currclass = symsize;
62   decl_size = 0;
63}
64
65/**
66 * Store variable in symbol table.
67 */
68
69void store_var(int size) {
70   enter();
71   symtab[symsize].type = VAR_TYPE;
72   symtab[symsize].nesting = nesting;
73   symtab[symsize].sym.var.base = ++decl_size;
74   symtab[symsize].sym.var.size = size;
75   if (size>1) decl_size += size-1;
76}
77
78
79/**
80 * Store formal parameter in symbol table.
81 */
82void store_formal(void) {
83   enter();
84   symtab[symsize].type = FORMAL_TYPE;
85   symtab[symsize].cls = INTSLOT;
86   symtab[currclass].sym.clazz.num_args++;
87   symtab[symsize].sym.var.base = ++decl_size;
88   symtab[symsize].sym.var.size = 0;
89}
90
91
92/**
93 * Backpatch second operand of triple stored in code table.
94 * This would be used to modify jump instructions for while/for/if constructs.
95 *
96 * @param triple Triple location in code table that should be modified.
97 * @param val New value for second operand.
98 */
99 void backpatch(int trip, int val) {
100  code[trip].second = val;
101}
102
103
104/**
105 * Backpatch first operand of triple stored in code table.
106 * This is used for jump statements in else case.
107 *
108 * @param triple Triple location in code table that should be modified.
109 * @param val New value for first operand.
110 */
111 void backpatch1(int trip, int val) { /* for backpatch the first field */
112  code[trip].first = val;
113}
114
115/**
116 * Check if triple is already available (for code optimization).
117 *
118 * @param opcode Triple operation mnemonic.
119 * @param first First operand.
120 * @param second Second operand.
121 * @return 0 if new triple, otherwise location of existing triple in code table.
122 */
123int redundant(char *opcode, int first, int second) { /* checks if triple already available */
124   int i;
125   if (strcmp(opcode, "CON") == 0) { /* just doing CON as an example */
126      for (i=0; i<constSize; i++)
127         if (first == const_pool[i].value) return(const_pool[i].triple);
128
129      if (constSize<CONST_MAX) {
130         const_pool[constSize].value = first;
131         const_pool[constSize].triple = triple;
132         constSize++;
133      }
134      return(0);
135   }
136   return(0);
137}
138
139
140/**
141 * Generates code and handles variable read/write reference count.
142 *
143 * @param opcode Triple operation mnemonic.
144 * @param prefix1 Memory('M') or Stack('S') location of first operand.
145 * @param first First operand.
146 * @param prefix2 Memory('M') or Stack('S') location of second operand.
147 * @param second Second operand.
148 * @return 0 if code table is full, otherwise the location of generated code triple.
149 */
150 int emit(char *opcode, char prefix1, int first, char prefix2, int second) { /* generates code and handles var count */
151   int old_triple;
152   old_triple = redundant(opcode, first, second); 
153   if (old_triple>0) return(old_triple);
154   if (triple<CODE_MAX) {
155      code[triple].prefix1 = prefix1;
156      code[triple].first = first;
157      code[triple].prefix2 = prefix2;
158      code[triple].second = second;
159      strcpy(code[triple].opcode, opcode);
160      return(triple++);
161   }
162   else {
163      fatal("code table is too large\n");
164      return(NONE);
165   }
166}
167
168
169void ok(int extra) {
170   while ((nextToken!=WHILE) && (nextToken!=FOR) && 
171                  (nextToken!=IF) && (nextToken!=SEMICOLON) && 
172                  (nextToken!=extra) && (nextToken!=ENDOFFILE) ) nextToken = yylex();
173}
174
175
176/**
177 * Print symbol table.
178 */
179 void dump_sym(void) {
180   int i;
181   printf("\n\nSYMBOL TABLE (size = %d)", symsize);
182   for(i=1; i<=symsize;i++) {
183      printf("\n%3d: ", i);
184      printf("\t%8s",symtab[i].name);
185      printf("\t%s ",type_names[symtab[i].type]);
186      printf("\t%s ",nest_names[symtab[i].nesting]);
187      if (symtab[i].type == NONE)
188         printf("\t\tBase=%d", symtab[i].sym.clazz.base);       
189      else if (symtab[i].type == CLASS_TYPE) { 
190                 printf("\t\tBase=%d", symtab[i].sym.clazz.base);
191                 printf(", Args=%d", symtab[i].sym.clazz.num_args);
192                 printf(", Locals=%d", symtab[i].sym.clazz.local_space);
193      }
194      else { /* var or parm */
195         printf("\tClass=%s",symtab[symtab[i].cls].name);
196         printf("\tBase=%d",symtab[i].sym.var.base);
197         printf(", Size=%d",symtab[i].sym.var.size);
198      }
199   }
200   printf("\n\n");
201}
202
203
204/**
205 * Print code table.
206 * @param final If set, this means to produc output file for interpreter
207 */
208 void dumpcode(int final) {
209  int i, p1, p2;
210  final = final && (interp != NULL);
211  /* header record is first instruction, number of instructions, size of globals, size of stack */
212  if (final) 
213    fprintf(interp, "%d %d %d %d\n", symtab[MAINSLOT].sym.clazz.base, triple-1, globals, DEFAULT_STACK); 
214  printf("\n");
215  for (i=showStart;i<triple;i++) {
216    printf("%4d: %-8s %c%-3d %c%-3d\n",i,code[i].opcode,p1=code[i].prefix1,code[i].first,p2=code[i].prefix2,code[i].second);
217    if (final) 
218      fprintf(interp, "%-8s %c%-3d %c%-3d\n",code[i].opcode,p1==' ' ? '#':p1,code[i].first,p2==' ' ? '#':p2,code[i].second);
219  }
220  showStart = triple;
221}
222
223
224/**
225 * Some fatal error occured (when data structures are full).
226 * @param s String describing fatal error.
227 */
228 void fatal(char const *s) {
229  printf("nFatal Error: %s\n",s);
230  dumpcode(0);
231}
232
233
234
235 /**
236 * Some error occured.
237 * @param s String describing error.
238 */
239 void error(char const *s) {
240  printf("\nError: %s\n", s);
241  errorNo++; 
242}
243
244
245/**
246 * Some warning occured.
247 * @param s String describing warning.
248 */
249 void warning(char const *s) {
250  printf("\nWarning: %s\n", s);
251  warnNo++; 
252}
253
254
255/**
256 * Bison error function. Simply prints error message.
257 * @param s Error string to print.
258 */
259 void yyerror(char const *s) {
260  printf("%s\n", s);
261}
262
263/**
264 * Main function of your recursive descent parser.
265 *
266 * Read token by token here and implement a recursive-descent parser based on that information.
267 * In essence, you should have one function per non-terminal and parse the input token by token.
268 * Based on the currently applied grammar production rule, match the input and call the appropriate
269 * functions if non-terminals are encountered.
270 * This function only reads token-by-token from the lexical analyzer and prints it right now. You have
271 * to write the rest of the parsing algorithm.
272 *
273 * @param argc Number of command-line parameters.
274 * @param argv Command-line arguments as strings.
275 */
276int main(int argc, char **argv ) 
277{
278        ++argv, --argc; /* skip over program name */
279
280        /* This should be the code you use when you actually write a parser
281        if ( argc > 0 ) {
282                yyin = fopen(argv[0], "r"); interp = fopen(strcat(argv[0],".interp"), "w");
283        } else {
284                yyin = stdin; interp = fopen("kbinput.interp", "w");
285        }
286        yyparse();
287        */
288        if ( argc > 0 ) 
289                yyin = fopen( argv[0], "r" );
290        else 
291                yyin = stdin;
292
293        /* Simply read token-by-token and print it out */
294        program ();
295        /*
296        while(nextToken = yylex()) {
297                printf(" {%s", yytokenstring[nextToken]);
298                if (nextToken == NUMBER)
299                        printf(" = %d", yylval.ival);
300                else if (nextToken == IDENT)
301                        printf(" = %s", idname);
302                printf("}");
303        }
304        */
305
306        system("pause()");
307        return(0);
308}
309
310int accept (int symbol) {
311        if (nextToken == symbol) {
312                nextToken = yylex ();
313                return 1;
314        }
315        return 0;
316}
317
318int expect (int symbol) {
319        if (accept (symbol)) return 1;
320        error ("expect: unexpected symbol");
321        return 0;
322}
323
324void program (void) {
325        startup ();
326        declsection ();
327        classes ();
328        expect (LBRACE);
329        statementlist ();
330        expect (RBRACE);
331}
332
333void startup (void) {
334        basicinit ();
335}
336
337void declsection (void) {
338        if (nextToken == INT || nextToken == error) {
339                decl ();
340                declsection ();
341        }
342}
343
344void decl (void) {
345        var_start = symsize + 1;
346        if (nextToken == INT) {
347                type ();
348                varlist ();
349                expect (SEMICOLON);
350                for (int i = var_start; i <= symsize; i++) {
351                        /* update symbol table with value */
352                }
353        } else {
354                error ("Message");
355        }
356}
357
358void type (void) {
359        if (accept (INT)) {
360                /* set cval */
361        }
362        else {
363                error ("Message");
364        }
365}
366
367void varlist (void) {
368        vardef ();
369        if (accept (COMMA)) {
370                varlist ();
371        }
372}
373
374void vardef (void) {
375        if (accept (IDENT)) {
376                if (accept (LBRACK)) {
377                        expect (NUMBER);
378                        expect (RBRACK);
379                        /* Update symbol table and store var number */
380                } else if (accept (IDENT)) {
381                        /* update symbol table */
382                } else {
383                        error ("Message");
384                }
385        }
386}
387
388void classes (void) {
389        if (nextToken == CLASS) {
390                classdef ();
391                classes ();
392        }
393}
394
395void classdef (void) {
396        if (nextToken == CLASS) {
397                classheader ();
398                expect (LBRACE);
399                methodsection ();
400                expect (RBRACE);
401        } else {
402                error ("Message");
403                expect (RBRACE);
404        }
405}
406
407void classheader (void) {
408        expect (CLASS);
409        expect (IDENT);
410        /* update nesting and tables */
411}