Comecando a ficar mais com a cara de Yacc.
[myPerl.git] / parser.y
blob440869bc0a568445e78a30a9fda11eff6f57c5fc
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 extern FILE *yyin;
19 void
20 install(char *name)
22 symtab_t *node;
24 node = getsym(name, scope);
25 if (! node || node->scope < scope) {
26 node = putsym(name, scope, 0);
27 } else {
28 printf("%s jah estah definido neste escopo!\n", name);
32 void
33 install_fun(char *name, int addr)
35 symtab_t *node;
37 node = getsym(name, scope);
38 if (! node || node->scope < scope) {
39 node = putsym(name, scope, addr);
40 } else {
41 printf("%s jah estah definido neste escopo!\n", name);
45 void
46 context_check(int op, char *name)
48 symtab_t *id;
50 id = getsym(name, scope);
51 if (! id) {
52 printf("Simbolo nao declarado: %s\n", name);
53 } else {
54 gen_code(op, id->offset);
58 void
59 call_fun(char *name)
61 symtab_t *id;
63 id = getsym(name, scope);
64 if (! id) {
65 printf("Fuancao nao declarado: %s\n", name);
66 } else {
67 gen_code(CALL, id->addr);
73 %union {
74 int ival;
75 struct label {
76 int for_goto;
77 int for_jmp_false;
78 } label;
79 struct var {
80 char *id;
81 } var;
82 struct fun {
83 char *id;
84 int nargs;
85 int addr;
86 } fun;
89 %start program
91 %token <ival> INTEGER
92 %token <fun> IDENTIFIER
93 %token <var> VARIABLE
94 %token <label> IF WHILE BREAK CONTINUE
95 %token ELSIF ELSE MY WRT_INT RETURN
97 %type <fun> fun_args fun_args_
99 %right '='
100 %left '+' '-'
101 %left '*' '/' '%'
102 %left '(' ')'
106 program: statements { gen_code(HALT, 0); YYACCEPT; }
109 statements: statements statement
110 | statement
113 statement: declarations ';'
114 | VARIABLE '=' expression ';' { context_check(STORE, $1.id); }
115 | expression ';'
116 | WRT_INT '(' INTEGER ')' ';' { gen_code(LOAD_INT, $3);
117 gen_code(WRITE_INT, 0); }
118 | WRT_INT '(' VARIABLE ')' ';' { context_check(LOAD_VAR, $3.id);
119 gen_code(WRITE_INT, 0); }
120 | IF '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
121 '{' { scope++; }
122 statements '}' { scoperem(scope--);
123 back_patch($1.for_jmp_false,
124 JMP_FALSE,
125 gen_label()); }
126 | WHILE { $1.for_goto = gen_label(); }
127 '(' expression ')' { $1.for_jmp_false = reserve_loc(); }
128 '{' { scope++; }
129 statements '}' { scoperem(scope--);
130 gen_code(GOTO, $1.for_goto);
131 back_patch($1.for_jmp_false,
132 JMP_FALSE,
133 gen_label()); }
134 | IDENTIFIER { $1.addr = reserve_loc();}
135 '{' { scope++; }
136 statements '}' { scoperem(scope--);
137 gen_code(RET, 0);
138 back_patch($1.addr++,
139 GOTO,
140 gen_label());
141 install_fun($1.id, $1.addr); }
144 declarations: MY VARIABLE { install($2.id); }
145 | MY '(' id_list ')'
148 id_list: id_list ',' VARIABLE { install($3.id); }
149 | VARIABLE { install($1.id); }
152 fun_args_: fun_args { $$ = $1; }
153 | /* */ { $$.nargs = 0; }
156 fun_args: fun_args ',' INTEGER { gen_code(LOAD_INT, $3);
157 $$.nargs = $1.nargs + 1; }
158 | fun_args ',' VARIABLE { context_check(LOAD_VAR, $3.id);
159 $$.nargs = $1.nargs + 1; }
160 | INTEGER { gen_code(LOAD_INT, $1); $$.nargs = 1; }
161 | VARIABLE { context_check(LOAD_VAR, $1.id); $$.nargs = 1; }
164 expression: expression '+' expression { gen_code(ADD, 0); }
165 | expression '-' expression { gen_code(SUB, 0); }
166 | expression '*' expression { gen_code(MUL, 0); }
167 | expression '/' expression { gen_code(DIV, 0); }
168 | expression '%' expression { gen_code(MOD, 0); }
169 | '(' expression ')'
170 | IDENTIFIER '(' fun_args_ ')' { gen_code(PUSH_INT, $3.nargs);
171 /* +1: after load_int, +2: after call */
172 gen_code(PUSH_INT, gen_label()+2);
173 call_fun($1.id); }
174 | VARIABLE { context_check(LOAD_VAR, $1.id); }
175 | INTEGER { gen_code(LOAD_INT, $1); }
176 | RETURN INTEGER { gen_code(LOAD_INT, $2);
177 gen_code(RET, 0); }
178 | RETURN VARIABLE { context_check(LOAD_VAR, $2.id);
179 gen_code(RET, 0); }
184 void
185 usage(char *pname)
187 fprintf(stderr, "Uso: %s [argumentos] <programa>\n", pname);
188 fprintf(stderr, "Onde argumentos pode ser:\n");
189 fprintf(stderr, "\t-o: Especifica arquivo de saida\n");
190 fprintf(stderr, "\t-d: Habilita saida de debugging do parser\n");
191 fprintf(stderr, "\t-h: Imprime essa mensagem e finaliza a execucao\n");
193 exit(0);
196 void
197 yyerror(char *err)
199 fprintf(stderr, "%s\n", err);
203 main(int argc, char **argv)
205 char *pname = argv[0];
206 char *outfile = NULL;
207 int opt, ret;
209 while ( (opt = getopt(argc, argv, "o:dh")) != -1) {
210 switch(opt) {
211 case 'd': /* enable parser debugging */
212 yydebug = 1;
213 break;
214 case 'o':
215 outfile = optarg;
216 break;
217 case 'h': /* print usage */
218 usage(pname);
219 break;
223 if (optind >= argc) { /* input file missing */
224 usage(pname);
227 yyin = fopen(argv[optind], "r");
228 if (! yyin) {
229 perror("fopen");
230 fprintf(stderr, "Erro ao abrir %s\n", argv[optind]);
231 exit(errno);
234 /* init symbol table */
235 initsym();
237 ret = yyparse();
239 if (outfile)
240 print_code(outfile);
242 vm_loop();
244 return ret;