Adicionado operadores relacionais.
[myPerl.git] / parser.y
blob54ac3307bbfc9b9b891b7a5c413a6ccc7863ab7c
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 NE GEQL LEQL GT LT
105 %type <var> var_dec dim_dec variable pos
106 %type <fun> fun_args fun_args_
108 %right '='
109 %left EQL NE GEQL LEQL GT LT
110 %left '+' '-'
111 %left '*' '/' '%'
112 %left '(' ')'
116 program: statements { gen_code(HALT, 0); YYACCEPT; }
119 statements: statements statement
120 | statement
123 statement: declarations ';'
124 | variable '=' expression ';' { gen_code(LOAD_OFF, $1.off);
125 context_check(STORE, $1.id); }
126 | expression ';'
127 | WRT_INT '(' INTEGER ')' ';' { gen_code(LOAD_INT, $3);
128 gen_code(WRITE_INT, 0); }
129 | WRT_INT '(' variable ')' ';' { gen_code(LOAD_OFF, $3.off);
130 context_check(LOAD_VAR, $3.id);
131 gen_code(WRITE_INT, 0); }
132 | IF '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
133 '{' { scope++; }
134 statements '}' { $1.for_else = reserve_loc();
135 back_patch($1.for_jmp_false,
136 JMP_FALSE,
137 gen_label());
138 scoperem(scope--); }
139 else { back_patch($1.for_else,
140 JMP_FALSE,
141 gen_label()); }
142 | WHILE { $1.for_goto = gen_label(); }
143 '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
144 '{' { scope++; }
145 statements '}' { scoperem(scope--);
146 gen_code(GOTO, $1.for_goto);
147 back_patch($1.for_jmp_false,
148 JMP_FALSE,
149 gen_label());
150 while(npos) {
151 back_patch(nexts[--npos],
152 GOTO,
153 $1.for_goto);
155 while(bpos) {
156 back_patch(breaks[--bpos],
157 GOTO,
158 gen_label());
160 | NEXT ';' { nexts[npos++] = reserve_loc(); }
161 | BREAK ';' { breaks[bpos++] = reserve_loc(); }
162 | IDENTIFIER { $1.addr = reserve_loc();}
163 '{' { scope++; }
164 statements '}' { scoperem(scope--);
165 gen_code(RET, 0);
166 back_patch($1.addr++,
167 GOTO,
168 gen_label());
169 install_fun($1.id, $1.addr); }
172 else: ELSE '{' { scope++; }
173 statements '}' { scoperem(scope--); }
174 | /* */
177 variable: VARIABLE pos { $$ = $1;
178 $$.off = $2.off; }
181 pos: pos '[' INTEGER ']' { $1.off *= $3;
182 $$ = $1; }
183 | /* empty */ { $$.off = 1; }
185 var_dec: VARIABLE dim_dec { $$ = $1;
186 $$.dim = $2.dim;
187 $$.size = $2.size; }
190 dim_dec: dim_dec '[' INTEGER ']' { $1.dim++;
191 $1.size *= $3;
192 $$ = $1; }
193 | /* empty */ { $$.dim = 1; $$.size = 1; }
195 declarations: MY var_dec { install($2.id, $2.dim, $2.size); }
196 | MY '(' id_list ')'
199 id_list: id_list ',' var_dec { install($3.id, $3.dim, $3.size); }
200 | var_dec { install($1.id, $1.dim, $1.size); }
203 fun_args_: fun_args { $$ = $1; }
204 | /* */ { $$.nargs = 0; }
207 fun_args: fun_args ',' INTEGER { gen_code(LOAD_INT, $3);
208 $$.nargs = $1.nargs + 1; }
209 | fun_args ',' variable { gen_code(LOAD_OFF, $3.off);
210 context_check(LOAD_VAR, $3.id);
211 $$.nargs = $1.nargs + 1; }
212 | INTEGER { gen_code(LOAD_INT, $1); $$.nargs = 1; }
213 | VARIABLE { gen_code(LOAD_OFF, $1.off);
214 context_check(LOAD_VAR, $1.id); $$.nargs = 1; }
217 expression: expression '+' expression { gen_code(ADD, 0); }
218 | expression '-' expression { gen_code(SUB, 0); }
219 | expression '*' expression { gen_code(MUL, 0); }
220 | expression '/' expression { gen_code(DIV, 0); }
221 | expression '%' expression { gen_code(MOD, 0); }
222 | expression EQL expression { gen_code(CMP_EQL, 0); }
223 | expression NE expression { gen_code(CMP_NE, 0); }
224 | expression GEQL expression { gen_code(CMP_GEQL, 0); }
225 | expression LEQL expression { gen_code(CMP_LEQL, 0); }
226 | expression GT expression { gen_code(CMP_GT, 0); }
227 | expression LT expression { gen_code(CMP_LT, 0); }
228 | '(' expression ')'
229 | IDENTIFIER '(' fun_args_ ')' { gen_code(PUSH_INT, $3.nargs);
230 /* +1: after load_int, +2: after call */
231 gen_code(PUSH_INT, gen_label()+2);
232 call_fun($1.id); }
233 | variable { gen_code(LOAD_OFF, $1.off);
234 context_check(LOAD_VAR, $1.id); }
235 | INTEGER { gen_code(LOAD_INT, $1); }
236 | RETURN INTEGER { gen_code(LOAD_INT, $2);
237 gen_code(RET, 0); }
238 | RETURN variable { gen_code(LOAD_OFF, $2.off);
239 context_check(LOAD_VAR, $2.id);
240 gen_code(RET, 0); }
245 void
246 usage(char *pname)
248 fprintf(stderr, "Uso: %s [argumentos] <programa>\n", pname);
249 fprintf(stderr, "Onde argumentos pode ser:\n");
250 fprintf(stderr, "\t-o: Especifica arquivo de saida\n");
251 fprintf(stderr, "\t-d: Habilita saida de debugging do parser\n");
252 fprintf(stderr, "\t-h: Imprime essa mensagem e finaliza a execucao\n");
254 exit(0);
257 void
258 yyerror(char *err)
260 fprintf(stderr, "%s\n", err);
264 main(int argc, char **argv)
266 char *pname = argv[0];
267 char *outfile = NULL;
268 int opt, ret;
270 while ( (opt = getopt(argc, argv, "o:dh")) != -1) {
271 switch(opt) {
272 case 'd': /* enable parser debugging */
273 yydebug = 1;
274 break;
275 case 'o':
276 outfile = optarg;
277 break;
278 case 'h': /* print usage */
279 usage(pname);
280 break;
284 if (optind >= argc) { /* input file missing */
285 usage(pname);
288 yyin = fopen(argv[optind], "r");
289 if (! yyin) {
290 perror("fopen");
291 fprintf(stderr, "Erro ao abrir %s\n", argv[optind]);
292 exit(errno);
295 /* init symbol table */
296 initsym();
298 ret = yyparse();
300 if (outfile)
301 print_code(outfile);
303 vm_loop();
305 return ret;