parse.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. init_parse
  2. parse
  3. read_next
  4. module
  5. decl_proc
  6. define_glo_var
  7. define_proc
  8. define_loc_var
  9. comp_statement
  10. statement
  11. if_statement
  12. while_statement
  13. set_statement
  14. call_statement
  15. putchar_statement
  16. kakko_exp
  17. int_exp
  18. add_exp
  19. mul_exp
  20. unary_exp
  21. 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 }

/* [<][>][^][v][top][bottom][index][help] */