Branch implementado!
[myPerl.git] / parser.y
blob0078282dffeffc9a736f44d62f907c8c25dc58ce
1 %{
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <getopt.h>
7 #include "symtab.h"
8 #include "heap.h"
9 #include "code.h"
10 #include "vm.h"
12 #define YYDEBUG 1
14 void yyerror(char *);
15 int yylex(void);
16 int scope = 0;
17 int breaks[16];
18 int nexts[16];
19 int bpos = 0;
20 int npos = 0;
21 extern FILE *yyin;
23 void
24 install(char *name, int dim, int size)
26 symtab_t *node;
28 node = getsym(name, scope);
29 if (! node || node->scope < scope) {
30 node = putsym(name, scope, 0, dim, size);
31 } else {
32 printf("%s jah estah definido neste escopo!\n", name);
36 void
37 install_fun(char *name, int addr)
39 symtab_t *node;
41 node = getsym(name, scope);
42 if (! node || node->scope < scope) {
43 node = putsym(name, scope, addr, 0, 0);
44 } else {
45 printf("%s jah estah definido neste escopo!\n", name);
49 void
50 context_check(int op, char *name)
52 symtab_t *id;
54 id = getsym(name, scope);
55 if (! id) {
56 printf("Simbolo nao declarado: %s\n", name);
57 } else {
58 gen_code(op, id->offset);
62 void
63 call_fun(char *name)
65 symtab_t *id;
67 id = getsym(name, scope);
68 if (! id) {
69 printf("Fuancao nao declarado: %s\n", name);
70 } else {
71 gen_code(CALL, id->addr);
77 %union {
78 int ival;
79 struct label {
80 int for_goto;
81 int for_jmp_false;
82 } label;
83 struct var {
84 char *id;
85 int dim;
86 int size;
87 int off;
88 } var;
89 struct fun {
90 char *id;
91 int nargs;
92 int addr;
93 } fun;
96 %start program
98 %token <ival> INTEGER
99 %token <fun> IDENTIFIER
100 %token <var> VARIABLE
101 %token <label> IF WHILE BREAK NEXT
102 %token ELSIF ELSE MY WRT_INT RETURN
104 %type <var> var_dec dim_dec variable pos
105 %type <fun> fun_args fun_args_
107 %right '='
108 %left '+' '-'
109 %left '*' '/' '%'
110 %left '(' ')'
114 program: statements { gen_code(HALT, 0); YYACCEPT; }
117 statements: statements statement
118 | statement
121 statement: declarations ';'
122 | variable '=' expression ';' { gen_code(LOAD_OFF, $1.off);
123 context_check(STORE, $1.id); }
124 | expression ';'
125 | WRT_INT '(' INTEGER ')' ';' { gen_code(LOAD_INT, $3);
126 gen_code(WRITE_INT, 0); }
127 | WRT_INT '(' variable ')' ';' { gen_code(LOAD_OFF, $3.off);
128 context_check(LOAD_VAR, $3.id);
129 gen_code(WRITE_INT, 0); }
130 | IF '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
131 '{' { scope++; }
132 statements '}' { scoperem(scope--);
133 back_patch($1.for_jmp_false,
134 JMP_FALSE,
135 gen_label()); }
136 | WHILE { $1.for_goto = gen_label(); }
137 '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
138 '{' { scope++; }
139 statements '}' { scoperem(scope--);
140 gen_code(GOTO, $1.for_goto);
141 back_patch($1.for_jmp_false,
142 JMP_FALSE,
143 gen_label());
144 while(npos) {
145 back_patch(nexts[--npos],
146 GOTO,
147 $1.for_goto);
149 while(bpos) {
150 back_patch(breaks[--bpos],
151 GOTO,
152 gen_label());
154 | NEXT ';' { nexts[npos++] = reserve_loc(); }
155 | BREAK ';' { breaks[bpos++] = reserve_loc(); }
156 | IDENTIFIER { $1.addr = reserve_loc();}
157 '{' { scope++; }
158 statements '}' { scoperem(scope--);
159 gen_code(RET, 0);
160 back_patch($1.addr++,
161 GOTO,
162 gen_label());
163 install_fun($1.id, $1.addr); }
166 variable: VARIABLE pos { $$ = $1;
167 $$.off = $2.off; }
170 pos: pos '[' INTEGER ']' { $1.off *= $3;
171 $$ = $1; }
172 | /* empty */ { $$.off = 1; }
174 var_dec: VARIABLE dim_dec { $$ = $1;
175 $$.dim = $2.dim;
176 $$.size = $2.size; }
179 dim_dec: dim_dec '[' INTEGER ']' { $1.dim++;
180 $1.size *= $3;
181 $$ = $1; }
182 | /* empty */ { $$.dim = 1; $$.size = 1; }
184 declarations: MY var_dec { install($2.id, $2.dim, $2.size); }
185 | MY '(' id_list ')'
188 id_list: id_list ',' var_dec { install($3.id, $3.dim, $3.size); }
189 | var_dec { install($1.id, $1.dim, $1.size); }
192 fun_args_: fun_args { $$ = $1; }
193 | /* */ { $$.nargs = 0; }
196 fun_args: fun_args ',' INTEGER { gen_code(LOAD_INT, $3);
197 $$.nargs = $1.nargs + 1; }
198 | fun_args ',' variable { gen_code(LOAD_OFF, $3.off);
199 context_check(LOAD_VAR, $3.id);
200 $$.nargs = $1.nargs + 1; }
201 | INTEGER { gen_code(LOAD_INT, $1); $$.nargs = 1; }
202 | VARIABLE { gen_code(LOAD_OFF, $1.off);
203 context_check(LOAD_VAR, $1.id); $$.nargs = 1; }
206 expression: expression '+' expression { gen_code(ADD, 0); }
207 | expression '-' expression { gen_code(SUB, 0); }
208 | expression '*' expression { gen_code(MUL, 0); }
209 | expression '/' expression { gen_code(DIV, 0); }
210 | expression '%' expression { gen_code(MOD, 0); }
211 | '(' expression ')'
212 | IDENTIFIER '(' fun_args_ ')' { gen_code(PUSH_INT, $3.nargs);
213 /* +1: after load_int, +2: after call */
214 gen_code(PUSH_INT, gen_label()+2);
215 call_fun($1.id); }
216 | variable { gen_code(LOAD_OFF, $1.off);
217 context_check(LOAD_VAR, $1.id); }
218 | INTEGER { gen_code(LOAD_INT, $1); }
219 | RETURN INTEGER { gen_code(LOAD_INT, $2);
220 gen_code(RET, 0); }
221 | RETURN variable { gen_code(LOAD_OFF, $2.off);
222 context_check(LOAD_VAR, $2.id);
223 gen_code(RET, 0); }
228 void
229 usage(char *pname)
231 fprintf(stderr, "Uso: %s [argumentos] <programa>\n", pname);
232 fprintf(stderr, "Onde argumentos pode ser:\n");
233 fprintf(stderr, "\t-o: Especifica arquivo de saida\n");
234 fprintf(stderr, "\t-d: Habilita saida de debugging do parser\n");
235 fprintf(stderr, "\t-h: Imprime essa mensagem e finaliza a execucao\n");
237 exit(0);
240 void
241 yyerror(char *err)
243 fprintf(stderr, "%s\n", err);
247 main(int argc, char **argv)
249 char *pname = argv[0];
250 char *outfile = NULL;
251 int opt, ret;
253 while ( (opt = getopt(argc, argv, "o:dh")) != -1) {
254 switch(opt) {
255 case 'd': /* enable parser debugging */
256 yydebug = 1;
257 break;
258 case 'o':
259 outfile = optarg;
260 break;
261 case 'h': /* print usage */
262 usage(pname);
263 break;
267 if (optind >= argc) { /* input file missing */
268 usage(pname);
271 yyin = fopen(argv[optind], "r");
272 if (! yyin) {
273 perror("fopen");
274 fprintf(stderr, "Erro ao abrir %s\n", argv[optind]);
275 exit(errno);
278 /* init symbol table */
279 initsym();
281 ret = yyparse();
283 if (outfile)
284 print_code(outfile);
286 vm_loop();
288 return ret;