parse.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- init_parse
- parse
- read_next
- module
- decl_proc
- define_glo_var
- define_proc
- define_loc_var
- comp_statement
- statement
- if_statement
- while_statement
- set_statement
- call_statement
- putchar_statement
- kakko_exp
- int_exp
- add_exp
- mul_exp
- unary_exp
- int_prim
1 #include <stddef.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4
5 #include "confdef.h"
6 #include "lang_dep.h"
7
8 #include "token.h"
9 #include "lex.h"
10 #include "name.h"
11 #include "express.h"
12 #include "codegen.h"
13 #include "labelgen.h"
14
15 #include "parse.h"
16
17 static void read_next(void);
18
19 static void module(void);
20 static void decl_proc(void);
21 static void define_glo_var(void);
22 static void define_proc(void);
23 static void define_loc_var(void);
24
25 static void statement(void);
26 static void comp_statement(void);
27 static void if_statement(void);
28 static void while_statement(void);
29 static void set_statement(void);
30 static void call_statement(void);
31 static void putchar_statement(void);
32
33 static exp_node *kakko_exp(void);
34 static exp_node *int_exp(void);
35 static exp_node *add_exp(void);
36 static exp_node *mul_exp(void);
37 static exp_node *unary_exp(void);
38 static exp_node *int_prim(void);
39
40 static token next;
41
42 static name_list *glo_name_list = 0;
43 static name_list *loc_name_list = 0;
44
45 void
46 init_parse(void)
/* [<][>][^][v][top][bottom][index][help] */
47 {
48 init_lex(stdin);
49 init_codegen(stdout);
50 }
51
52 void
53 parse(void)
/* [<][>][^][v][top][bottom][index][help] */
54 {
55 read_next(); /* まず先読み */
56 module(); /* プログラム全体は 1 個のモジュール定義 */
57 }
58
59 static void
60 read_next(void)
/* [<][>][^][v][top][bottom][index][help] */
61 {
62 next = lex();
63 }
64
65 static void
66 module(void)
/* [<][>][^][v][top][bottom][index][help] */
67 {
68 gen_verb(".globl _main\n\n");
69 for (;;)
70 {
71 switch (next.lex)
72 {
73 case LEXVAL_PROC:
74 decl_proc();
75 break;
76 case LEXVAL_WORD:
77 define_glo_var();
78 break;
79 default:
80 goto end_decl_g; /* for (;;) を抜ける */
81 }
82 }
83 end_decl_g:
84 while (next.lex == LEXVAL_DEFPROC)
85 define_proc();
86
87 if (next.lex != LEXVAL_eof)
88 {
89 EMSTOP("unknown token", get_linenum());
90 exit(1);
91 }
92 }
93
94 static void
95 decl_proc(void)
/* [<][>][^][v][top][bottom][index][help] */
96 {
97 name_info *thisname;
98
99 do
100 {
101 read_next();
102 if (next.lex != LEXVAL_name)
103 {
104 EMSTOP("proc name must be name", get_linenum());
105 exit(1);
106 }
107 if (name_find(glo_name_list, (char *)next.sem.p) != 0)
108 {
109 EMSTOP("same (proc) name used twice", get_linenum());
110 exit(1);
111 }
112 glo_name_list = name_append(glo_name_list, (char *)next.sem.p);
113 thisname = name_find(glo_name_list, (char *)next.sem.p);
114 name_set_decl(thisname);
115 name_set_proc(thisname);
116 read_next();
117 }
118 while (next.lex == ',');
119 if (next.lex != ';')
120 {
121 EMSTOP("compiler expected \';\'", get_linenum());
122 exit(1);
123 }
124 read_next();
125 }
126
127 static void
128 define_glo_var(void)
/* [<][>][^][v][top][bottom][index][help] */
129 {
130 name_info *thisname;
131
132 do
133 {
134 read_next();
135 if (next.lex != LEXVAL_name)
136 {
137 EMSTOP("global variable name must be name", get_linenum());
138 exit(1);
139 }
140 if (name_find(glo_name_list, (char *)next.sem.p) != 0)
141 {
142 EMSTOP("same (global variable) name used twice", get_linenum());
143 exit(1);
144 }
145 glo_name_list = name_append(glo_name_list, (char *)next.sem.p);
146 thisname = name_find(glo_name_list, (char *)next.sem.p);
147 name_set_def(thisname);
148 name_set_glo_var(thisname);
149 gen_verb(".lcomm ");
150 gen_verb((char *)next.sem.p);
151 gen_verb(", 4\n");
152 read_next();
153 }
154 while (next.lex == ',');
155 if (next.lex != ';')
156 {
157 EMSTOP("compiler expected \';\'", get_linenum());
158 exit(1);
159 }
160 read_next();
161 }
162
163 static void
164 define_proc(void)
/* [<][>][^][v][top][bottom][index][help] */
165 {
166 name_info *thisname;
167
168 read_next();
169 if (next.lex != LEXVAL_name)
170 {
171 EMSTOP("proc name must be name", get_linenum());
172 exit(1);
173 }
174 if ((thisname = name_find(glo_name_list, (char *)next.sem.p)) == 0)
175 {
176 EMSTOP("proc name is not declared", get_linenum());
177 exit(1);
178 }
179 if (name_get_type(thisname) != NAME_PROC)
180 {
181 EMSTOP("name is not declared for procedure", get_linenum());
182 exit(1);
183 }
184 if (name_get_stat(thisname) == NAME_DEFINED)
185 {
186 EMSTOP("same name proc defined twice", get_linenum());
187 exit(1);
188 }
189 if (name_get_stat(thisname) != NAME_DECLARED)
190 {
191 EMSTOP("name is not declared", get_linenum());
192 exit(1);
193 }
194 name_set_def(thisname);
195 gen_verb("\n.text\n\t.align 2\n\t.type\t");
196 gen_verb((char *)next.sem.p);
197 gen_verb(", @function\n");
198 gen_verb((char *)next.sem.p);
199 gen_verb(":\n\tpushl %ebp\n\tmovl %esp, %ebp\n");
200 read_next();
201 if (next.lex != ':')
202 {
203 EMSTOP("compiler expected \':\'", get_linenum());
204 exit(1);
205 }
206 read_next();
207 define_loc_var();
208 comp_statement();
209 gen_verb("\tleave\n\tret\n");
210 name_list_free(loc_name_list);
211 loc_name_list = 0;
212 }
213
214 static void
215 define_loc_var(void)
/* [<][>][^][v][top][bottom][index][help] */
216 {
217 int frame_size;
218 name_info *thisname;
219
220 frame_size = 0;
221 while (next.lex == LEXVAL_WORD)
222 {
223 do
224 {
225 read_next();
226 if (next.lex != LEXVAL_name)
227 {
228 EMSTOP("local variable name must be name", get_linenum());
229 exit(1);
230 }
231 if (name_find(loc_name_list, (char *)next.sem.p) != 0)
232 {
233 EMSTOP("same name local variable defined twice", get_linenum());
234 exit(1);
235 }
236 frame_size += ZINC_SIZEOF_WORD;
237 loc_name_list = name_append(loc_name_list, (char *)next.sem.p);
238 thisname = name_find(loc_name_list, (char *)next.sem.p);
239 name_set_def(thisname);
240 name_set_loc_var(thisname);
241 name_set_id(thisname, frame_size);
242 read_next();
243 }
244 while (next.lex == ',');
245 if (next.lex != ';')
246 {
247 EMSTOP("compiler expected \';\'", get_linenum());
248 exit(1);
249 }
250 read_next();
251 }
252 if (frame_size > 0)
253 gen_make_frame(frame_size);
254 }
255
256 static void
257 comp_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
258 {
259 if (next.lex != '{') /* このコメントは } エディタの括弧対応のためのおまじない */
260 {
261 EMSTOP("compiler expected \'{\'", get_linenum()); /* } */
262 exit(1);
263 }
264 read_next();
265 do
266 statement(); /* { */
267 while (next.lex != '}');
268 read_next();
269 }
270
271 static void
272 statement(void)
/* [<][>][^][v][top][bottom][index][help] */
273 {
274 switch (next.lex)
275 {
276 case LEXVAL_IF:
277 if_statement();
278 break;
279 case LEXVAL_WHILE:
280 while_statement();
281 break;
282 case LEXVAL_SET:
283 set_statement();
284 break;
285 case LEXVAL_CALL:
286 call_statement();
287 break;
288 case LEXVAL_PUTCHAR:
289 putchar_statement();
290 break;
291 default:
292 EMSTOP("compiler expected statement", get_linenum());
293 exit(1);
294 }
295 }
296
297 static void
298 if_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
299 {
300 int fi_label;
301
302 fi_label = getnewnum();
303 read_next();
304 gen_exp(kakko_exp());
305 gen_verb("\tandl %eax, %eax\n");
306 gen_jz(fi_label);
307 comp_statement();
308 gen_label(fi_label);
309 }
310
311 static void
312 while_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
313 {
314 int loop_label, quit_label;
315
316 loop_label = getnewnum();
317 quit_label = getnewnum();
318 read_next();
319 gen_label(loop_label);
320 gen_exp(kakko_exp());
321 gen_verb("\tandl %eax, %eax\n");
322 gen_jz(quit_label);
323 comp_statement();
324 gen_goto(loop_label);
325 gen_label(quit_label);
326 }
327
328 static void
329 set_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
330 {
331 name_info *store_to;
332
333 read_next();
334 if (next.lex != LEXVAL_name)
335 {
336 EMSTOP("left of \":=\" must be name", get_linenum());
337 exit(1);
338 }
339 store_to = name_find(loc_name_list, next.sem.p);
340 if (store_to == 0)
341 store_to = name_find(glo_name_list, next.sem.p);
342 if (store_to == 0)
343 {
344 EMSTOP("left of \":=\" is unknown name", get_linenum());
345 exit(1);
346 }
347 if (name_get_type(store_to) == NAME_PROC)
348 {
349 EMSTOP("cannot assignment for procedure", get_linenum());
350 exit(1);
351 }
352 read_next();
353 if (next.lex != LEXVAL_coloneq)
354 {
355 EMSTOP("compiler expected \":=\"", get_linenum());
356 exit(1);
357 }
358 read_next();
359 if (next.lex == LEXVAL_GETCHAR)
360 {
361 #if defined ZINC_FreeBSD
362 gen_verb("\tpushl $___sF\n\tcall _fgetc\n\taddl $4, %esp\n");
363 #else /* ZINC_FreeBSD */
364 gen_verb("\tint $192\n");
365 #endif /* ZINC_FreeBSD */
366 read_next();
367 }
368 else
369 {
370 gen_exp(int_exp());
371 }
372 gen_set(store_to);
373 if (next.lex != ';')
374 {
375 EMSTOP("compiler expected \';\'", get_linenum());
376 exit(1);
377 }
378 read_next();
379 }
380
381 static void
382 call_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
383 {
384 read_next();
385 if (next.lex != LEXVAL_name)
386 {
387 EMSTOP("to call is must be name", get_linenum());
388 exit(1);
389 }
390 gen_verb("\tcall ");
391 gen_verb(next.sem.p);
392 gen_verb("\n");
393 read_next();
394 if (next.lex != ';')
395 {
396 EMSTOP("compiler expected \';\'", get_linenum());
397 exit(1);
398 }
399 read_next();
400 }
401
402 static void
403 putchar_statement(void)
/* [<][>][^][v][top][bottom][index][help] */
404 {
405 read_next();
406 gen_exp(int_exp());
407 #if defined ZINC_FreeBSD
408 gen_verb("\tpushl $___sF+88\n\tpushl %eax\n\tcall _fputc\n\taddl $8, %esp\n");
409 #else /* ZINC_FreeBSD */
410 gen_verb("\tint $193\n");
411 #endif /* ZINC_FreeBSD */
412 if (next.lex != ';')
413 {
414 EMSTOP("compiler expected \';\'", get_linenum());
415 exit(1);
416 }
417 read_next();
418 }
419
420 static exp_node *
421 kakko_exp(void)
/* [<][>][^][v][top][bottom][index][help] */
422 {
423 exp_node *p;
424
425 if (next.lex != '(') /* このコメントは ) エディタの括弧対応のためのおまじない */
426 {
427 EMSTOP("compiler expected \'(\'", get_linenum()); /* ) */
428 exit(1);
429 }
430 read_next();
431 p = int_exp(); /* ( */
432 if (next.lex != ')')
433 {
434 EMSTOP("compiler expected \')\'", get_linenum()); /* ) */
435 exit(1);
436 }
437 read_next();
438
439 return p;
440 }
441
442 static exp_node *
443 int_exp()
/* [<][>][^][v][top][bottom][index][help] */
444 {
445 exp_node *thisexp;
446
447 thisexp = add_exp();
448 while ((next.lex == LEXVAL_eqeq)
449 || (next.lex == LEXVAL_bangeq)
450 || (next.lex == '<')
451 || (next.lex == '>')
452 || (next.lex == LEXVAL_lt_or_eq)
453 || (next.lex == LEXVAL_gt_or_eq))
454 {
455 exp_node *newexp;
456 newexp = malloc(sizeof(exp_node));
457 newexp->val._2._0 = thisexp;
458 thisexp = newexp;
459 switch (next.lex)
460 {
461 case LEXVAL_eqeq:
462 newexp->type = EXP_ISEQ;
463 break;
464 case LEXVAL_bangeq:
465 newexp->type = EXP_ISNOTEQ;
466 break;
467 case '<':
468 newexp->type = EXP_ISLT;
469 break;
470 case '>':
471 newexp->type = EXP_ISGT;
472 break;
473 case LEXVAL_lt_or_eq:
474 newexp->type = EXP_ISLTEQ;
475 break;
476 case LEXVAL_gt_or_eq:
477 newexp->type = EXP_ISGTEQ;
478 break;
479 default:
480 EMSTOP("internal conflict", get_linenum());
481 exit(1);
482 }
483 read_next();
484 newexp->val._2._1 = add_exp();
485 }
486
487 return thisexp;
488 }
489
490 static exp_node *
491 add_exp(void)
/* [<][>][^][v][top][bottom][index][help] */
492 {
493 exp_node *thisexp;
494
495 thisexp = mul_exp();
496 while ((next.lex == '+')
497 || (next.lex == '-')
498 || (next.lex == '|'))
499 {
500 exp_node *newexp;
501 newexp = malloc(sizeof(exp_node));
502 newexp->val._2._0 = thisexp;
503 thisexp = newexp;
504 switch (next.lex)
505 {
506 case '+':
507 newexp->type = EXP_ADD;
508 break;
509 case '-':
510 newexp->type = EXP_SUB;
511 break;
512 case '|':
513 newexp->type = EXP_OR;
514 break;
515 default:
516 EMSTOP("internal conflict", get_linenum());
517 exit(1);
518 }
519 read_next();
520 newexp->val._2._1 = mul_exp();
521 }
522
523 return thisexp;
524 }
525
526 static exp_node *
527 mul_exp()
/* [<][>][^][v][top][bottom][index][help] */
528 {
529 exp_node *thisexp;
530
531 thisexp = unary_exp();
532 while ((next.lex == '*')
533 || (next.lex == '/')
534 || (next.lex == '%')
535 || (next.lex == LEXVAL_lsl)
536 || (next.lex == LEXVAL_asr)
537 || (next.lex == LEXVAL_lsr)
538 || (next.lex == '&'))
539 {
540 exp_node *newexp;
541 newexp = malloc(sizeof(exp_node));
542 newexp->val._2._0 = thisexp;
543 thisexp = newexp;
544 switch (next.lex)
545 {
546 case '*':
547 newexp->type = EXP_MUL;
548 break;
549 case '/':
550 newexp->type = EXP_DIV;
551 break;
552 case '%':
553 newexp->type = EXP_MOD;
554 break;
555 case LEXVAL_lsl:
556 newexp->type = EXP_LSL;
557 break;
558 case LEXVAL_asr:
559 newexp->type = EXP_ASR;
560 break;
561 case LEXVAL_lsr:
562 newexp->type = EXP_LSR;
563 break;
564 case '&':
565 newexp->type = EXP_AND;
566 break;
567 default:
568 EMSTOP("internal conflict", get_linenum());
569 exit(1);
570 }
571 read_next();
572 newexp->val._2._1 = unary_exp();
573 }
574
575 return thisexp;
576 }
577
578 static exp_node *
579 unary_exp()
/* [<][>][^][v][top][bottom][index][help] */
580 {
581 exp_node *op, *e, *thisexp;
582
583 thisexp = 0;
584 op = 0;
585
586 while ((next.lex == '~')
587 || (next.lex == '+')
588 || (next.lex == '-'))
589 {
590 exp_node *old_op;
591 old_op = op;
592 op = malloc(sizeof(exp_node));
593 if (thisexp == 0)
594 thisexp = op;
595 switch (next.lex)
596 {
597 case '~':
598 op->type = EXP_NOT;
599 break;
600 case '+':
601 op->type = EXP_PLUS;
602 break;
603 case '-':
604 op->type = EXP_MINUS;
605 break;
606 default:
607 EMSTOP("internal conflict", get_linenum());
608 exit(1);
609 }
610 if (old_op != 0)
611 old_op->val._1._0 = op;
612 read_next();
613 }
614 e = int_prim();
615 if (thisexp == 0)
616 thisexp = e;
617 else
618 op->val._1._0 = e;
619
620 return thisexp;
621 }
622
623 static exp_node *
624 int_prim()
/* [<][>][^][v][top][bottom][index][help] */
625 {
626 exp_node *thisexp;
627 name_info *v;
628
629 switch (next.lex)
630 {
631 case '(': /* このコメントは ) エディタの括弧対応のためのおまじない */
632 read_next();
633 thisexp = int_exp(); /* ( */
634 if (next.lex != ')')
635 { /* ( */
636 EMSTOP("compiler expected \')\'", get_linenum());
637 exit(1);
638 }
639 read_next();
640 break;
641 case LEXVAL_name:
642 thisexp = malloc(sizeof(exp_node));
643 thisexp->type = EXP_VAR;
644 v = name_find(loc_name_list, next.sem.p);
645 if (v == 0)
646 v = name_find(glo_name_list, next.sem.p);
647 if (v == 0)
648 {
649 EMSTOP("unknown name", get_linenum());
650 exit(1);
651 }
652 if (name_get_type(v) == NAME_PROC)
653 {
654 EMSTOP("name of procedure cannot be refereed", get_linenum());
655 exit(1);
656 }
657 thisexp->val.var = v;
658 read_next();
659 break;
660 case LEXVAL_literal:
661 thisexp = malloc(sizeof(exp_node));
662 thisexp->type = EXP_CONST;
663 thisexp->val.constval = next.sem.w;
664 read_next();
665 break;
666 default:
667 EMSTOP("expression is not correct", get_linenum());
668 exit(1);
669 }
670
671 return thisexp;
672 }