Atualizado docs. Implementado ops logicos.
[myPerl.git] / parser.y
blob86c5422120e5822c91c9171cc942c18fc14e2f69
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 int for_else;
83 } label;
84 struct var {
85 char *id;
86 int dim;
87 int size;
88 int off;
89 } var;
90 struct fun {
91 char *id;
92 int nargs;
93 int addr;
94 } fun;
97 %start program
99 %token <ival> INTEGER
100 %token <fun> IDENTIFIER
101 %token <var> VARIABLE
102 %token <label> IF WHILE BREAK NEXT
103 %token ELSIF ELSE MY WRT_INT RETURN EQL
104 %token NE GEQL LEQL GT LT SHFT OR AND NOT
106 %type <var> var_dec dim_dec variable pos
107 %type <fun> fun_args fun_args_
109 %right '='
110 %left EQL NE GEQL LEQL GT LT
111 %left '+' '-'
112 %left '*' '/' '%'
113 %left '(' ')'
114 %left "!"
115 %left AND OR
119 program: statements { gen_code(HALT, 0); YYACCEPT; }
122 statements: statements statement
123 | statement
126 statement: declarations ';'
127 | variable '=' expression ';' { gen_code(LOAD_OFF, $1.off);
128 context_check(STORE, $1.id); }
129 | expression ';'
130 | WRT_INT '(' INTEGER ')' ';' { gen_code(LOAD_INT, $3);
131 gen_code(WRITE_INT, 0); }
132 | WRT_INT '(' variable ')' ';' { gen_code(LOAD_OFF, $3.off);
133 context_check(LOAD_VAR, $3.id);
134 gen_code(WRITE_INT, 0); }
135 | IF '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
136 '{' { scope++; }
137 statements '}' { $1.for_else = reserve_loc();
138 back_patch($1.for_jmp_false,
139 JMP_FALSE,
140 gen_label());
141 scoperem(scope--); }
142 else { back_patch($1.for_else,
143 JMP_FALSE,
144 gen_label()); }
145 | WHILE { $1.for_goto = gen_label(); }
146 '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
147 '{' { scope++; }
148 statements '}' { scoperem(scope--);
149 gen_code(GOTO, $1.for_goto);
150 back_patch($1.for_jmp_false,
151 JMP_FALSE,
152 gen_label());
153 while(npos) {
154 back_patch(nexts[--npos],
155 GOTO,
156 $1.for_goto);
158 while(bpos) {
159 back_patch(breaks[--bpos],
160 GOTO,
161 gen_label());
163 | NEXT ';' { nexts[npos++] = reserve_loc(); }
164 | BREAK ';' { breaks[bpos++] = reserve_loc(); }
165 | IDENTIFIER { $1.addr = reserve_loc();}
166 '{' { scope++; }
167 statements '}' { scoperem(scope--);
168 gen_code(RET, 0);
169 back_patch($1.addr++,
170 GOTO,
171 gen_label());
172 install_fun($1.id, $1.addr); }
175 else: ELSE '{' { scope++; }
176 statements '}' { scoperem(scope--); }
177 | /* */
180 variable: VARIABLE pos { $$ = $1;
181 $$.off = $2.off; }
184 pos: pos '[' INTEGER ']' { $1.off *= $3;
185 $$ = $1; }
186 | /* empty */ { $$.off = 1; }
188 var_dec: VARIABLE dim_dec { $$ = $1;
189 $$.dim = $2.dim;
190 $$.size = $2.size; }
193 dim_dec: dim_dec '[' INTEGER ']' { $1.dim++;
194 $1.size *= $3;
195 $$ = $1; }
196 | /* empty */ { $$.dim = 1; $$.size = 1; }
198 declarations: MY var_dec { install($2.id, $2.dim, $2.size); }
199 | MY '(' id_list ')'
202 id_list: id_list ',' var_dec { install($3.id, $3.dim, $3.size); }
203 | var_dec { install($1.id, $1.dim, $1.size); }
206 fun_args_: fun_args { $$ = $1; }
207 | /* */ { $$.nargs = 0; }
210 fun_args: fun_args ',' INTEGER { gen_code(LOAD_INT, $3);
211 $$.nargs = $1.nargs + 1; }
212 | fun_args ',' variable { gen_code(LOAD_OFF, $3.off);
213 context_check(LOAD_VAR, $3.id);
214 $$.nargs = $1.nargs + 1; }
215 | INTEGER { gen_code(LOAD_INT, $1); $$.nargs = 1; }
216 | VARIABLE { gen_code(LOAD_OFF, $1.off);
217 context_check(LOAD_VAR, $1.id); $$.nargs = 1; }
220 expression: expression '+' expression { gen_code(ADD, 0); }
221 | expression '-' expression { gen_code(SUB, 0); }
222 | expression '*' expression { gen_code(MUL, 0); }
223 | expression '/' expression { gen_code(DIV, 0); }
224 | expression '%' expression { gen_code(MOD, 0); }
225 | expression EQL expression { gen_code(CMP_EQL, 0); }
226 | expression NE expression { gen_code(CMP_NE, 0); }
227 | expression GEQL expression { gen_code(CMP_GEQL, 0); }
228 | expression LEQL expression { gen_code(CMP_LEQL, 0); }
229 | expression GT expression { gen_code(CMP_GT, 0); }
230 | expression LT expression { gen_code(CMP_LT, 0); }
231 | '(' expression ')'
232 | expression OR expression { gen_code(CMP_OR, 0); }
233 | expression AND expression { gen_code(CMP_AND, 0); }
234 | NOT expression { gen_code(CMP_NOT, 0); }
235 | IDENTIFIER '(' fun_args_ ')' { gen_code(PUSH_INT, $3.nargs);
236 /* +1: after load_int, +2: after call */
237 gen_code(PUSH_INT, gen_label()+2);
238 call_fun($1.id); }
239 | variable { gen_code(LOAD_OFF, $1.off);
240 context_check(LOAD_VAR, $1.id); }
241 | INTEGER { gen_code(LOAD_INT, $1); }
242 | RETURN INTEGER { gen_code(LOAD_INT, $2);
243 gen_code(RET, 0); }
244 | RETURN variable { gen_code(LOAD_OFF, $2.off);
245 context_check(LOAD_VAR, $2.id);
246 gen_code(RET, 0); }
247 | SHFT { gen_code(SHIFT, 0); }
252 void
253 usage(char *pname)
255 fprintf(stderr, "Uso: %s [argumentos] <programa>\n", pname);
256 fprintf(stderr, "Onde argumentos pode ser:\n");
257 fprintf(stderr, "\t-o: Especifica arquivo de saida\n");
258 fprintf(stderr, "\t-d: Habilita saida de debugging do parser\n");
259 fprintf(stderr, "\t-h: Imprime essa mensagem e finaliza a execucao\n");
261 exit(0);
264 void
265 yyerror(char *err)
267 fprintf(stderr, "%s\n", err);
271 main(int argc, char **argv)
273 char *pname = argv[0];
274 char *outfile = NULL;
275 int opt, ret;
277 while ( (opt = getopt(argc, argv, "o:dh")) != -1) {
278 switch(opt) {
279 case 'd': /* enable parser debugging */
280 yydebug = 1;
281 break;
282 case 'o':
283 outfile = optarg;
284 break;
285 case 'h': /* print usage */
286 usage(pname);
287 break;
291 if (optind >= argc) { /* input file missing */
292 usage(pname);
295 yyin = fopen(argv[optind], "r");
296 if (! yyin) {
297 perror("fopen");
298 fprintf(stderr, "Erro ao abrir %s\n", argv[optind]);
299 exit(errno);
302 /* init symbol table */
303 initsym();
305 ret = yyparse();
307 if (outfile)
308 print_code(outfile);
310 vm_loop();
312 return ret;