Funcoes implementado. Ultima hora, cheio de variaveis globais.
[myPerl.git] / parser.y
blobcb7b01e43d2033f604f3400d1a00e54072e8dae2
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 struct label {
15 char *id;
16 int for_goto;
17 int for_jmp_false;
20 void yyerror(char *);
21 int yylex(void);
22 int scope = 0;
23 int nargs = 0;
24 int fun_begin = 0;
25 extern FILE *yyin;
27 struct label *
28 alloc_label(void)
30 return calloc(1, sizeof(struct label));
33 void
34 install(char *name)
36 symtab_t *node;
38 node = getsym(name, scope);
39 if (! node || node->scope < scope) {
40 node = putsym(name, scope, gen_label());
41 } else {
42 printf("%s jah estah definido neste escopo!\n", name);
46 void
47 context_check(int op, char *name)
49 symtab_t *id;
51 id = getsym(name, scope);
52 if (! id) {
53 printf("Simbolo nao declarado: %s\n", name);
54 } else {
55 gen_code(op, id->offset);
59 void
60 call_fun(char *name)
62 symtab_t *id;
64 id = getsym(name, scope);
65 if (! id) {
66 printf("Fuancao nao declarado: %s\n", name);
67 } else {
68 /* id->addr points to the GOTO instruction */
69 gen_code(CALL, id->addr+1);
75 %union {
76 char *id;
77 int ival;
78 struct label *label;
81 %start program
83 %token <ival> INTEGER
84 %token <id> VARIABLE IDENTIFIER
85 %token <label> IF WHILE BREAK CONTINUE
86 %token ELSIF ELSE MY WRT_INT RETURN
88 %right '='
89 %left '+' '-'
90 %left '*' '/' '%'
91 %left '(' ')'
95 program: statements { gen_code(HALT, 0); YYACCEPT; }
98 statements: statements statement
99 | statement
102 statement: declarations ';'
103 | VARIABLE '=' expression ';' { context_check(STORE, $1); }
104 | expression ';'
105 | WRT_INT '(' INTEGER ')' ';' { gen_code(LOAD_INT, $3);
106 gen_code(WRITE_INT, 0); }
107 | WRT_INT '(' VARIABLE ')' ';' { context_check(LOAD_VAR, $3);
108 gen_code(WRITE_INT, 0); }
109 | IF '(' expression ')' { $1 = alloc_label();
110 $1->for_jmp_false = reserve_loc(); }
111 '{' { scope++; }
112 statements '}' { scoperem(scope--);
113 back_patch($1->for_jmp_false,
114 JMP_FALSE,
115 gen_label()); }
116 | WHILE { $1 = alloc_label();
117 $1->for_goto = gen_label(); }
118 '(' expression ')' { $1->for_jmp_false = reserve_loc(); }
119 '{' { scope++; }
120 statements '}' { scoperem(scope--);
121 gen_code(GOTO, $1->for_goto);
122 back_patch($1->for_jmp_false,
123 JMP_FALSE,
124 gen_label()); }
125 | IDENTIFIER { install($1);
126 fun_begin = reserve_loc();}
127 '{' { scope++; }
128 statements '}' { scoperem(scope--);
129 gen_code(RET, 0);
130 back_patch(fun_begin,
131 GOTO,
132 gen_label()); }
135 declarations: MY VARIABLE { install($2); }
136 | MY '(' id_list ')'
139 id_list: id_list ',' VARIABLE { install($3); }
140 | VARIABLE { install($1); }
143 fun_args_: fun_args | /* */ ;
145 fun_args: fun_args ',' INTEGER { gen_code(LOAD_INT, $3); nargs++; }
146 | fun_args ',' VARIABLE { context_check(LOAD_VAR, $3); nargs++; }
147 | INTEGER { gen_code(LOAD_INT, $1); nargs++; }
148 | VARIABLE { context_check(LOAD_VAR, $1); nargs++; }
151 expression: expression '+' expression { gen_code(ADD, 0); }
152 | expression '-' expression { gen_code(SUB, 0); }
153 | expression '*' expression { gen_code(MUL, 0); }
154 | expression '/' expression { gen_code(DIV, 0); }
155 | expression '%' expression { gen_code(MOD, 0); }
156 | '(' expression ')'
157 | IDENTIFIER '(' fun_args_ ')' { gen_code(PUSH_INT, nargs);
158 /* +1: after load_int, +2: after call */
159 gen_code(PUSH_INT, gen_label()+2);
160 nargs = 0;
161 call_fun($1); }
162 | VARIABLE { context_check(LOAD_VAR, $1); }
163 | INTEGER { gen_code(LOAD_INT, $1); }
164 | RETURN INTEGER { gen_code(LOAD_INT, $2);
165 gen_code(RET, 0); }
166 | RETURN VARIABLE { context_check(LOAD_VAR, $2);
167 gen_code(RET, 0); }
172 void
173 usage(char *pname)
175 fprintf(stderr, "Uso: %s [argumentos] <programa>\n", pname);
176 fprintf(stderr, "Onde argumentos pode ser:\n");
177 fprintf(stderr, "\t-o: Especifica arquivo de saida\n");
178 fprintf(stderr, "\t-d: Habilita saida de debugging do parser\n");
179 fprintf(stderr, "\t-h: Imprime essa mensagem e finaliza a execucao\n");
181 exit(0);
184 void
185 yyerror(char *err)
187 fprintf(stderr, "%s\n", err);
191 main(int argc, char **argv)
193 char *pname = argv[0];
194 char *outfile = NULL;
195 int opt, ret;
197 while ( (opt = getopt(argc, argv, "o:dh")) != -1) {
198 switch(opt) {
199 case 'd': /* enable parser debugging */
200 yydebug = 1;
201 break;
202 case 'o':
203 outfile = optarg;
204 break;
205 case 'h': /* print usage */
206 usage(pname);
207 break;
211 if (optind >= argc) { /* input file missing */
212 usage(pname);
215 yyin = fopen(argv[optind], "r");
216 if (! yyin) {
217 perror("fopen");
218 fprintf(stderr, "Erro ao abrir %s\n", argv[optind]);
219 exit(errno);
222 /* init symbol table */
223 initsym();
225 ret = yyparse();
227 if (outfile)
228 print_code(outfile);
230 vm_loop();
232 return ret;