1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 /* 4 * Yacc grammar for UNIX Pascal 5 * 6 * This grammar is processed by the commands in the shell script 7 * "gram" to yield parse tables and semantic routines in the file 8 * "y.tab.c" and a header defining the lexical tokens in "yy.h". 9 * 10 * In order for the syntactic error recovery possible with this 11 * grammar to work, the grammar must be processed by a yacc which 12 * has been modified to fully enumerate possibilities in states 13 * which involve the symbol "error". 14 * The parser used for Pascal also uses a different encoding of 15 * the test entries in the action table which speeds the parse. 16 * A version of yacc which will work for Pascal is included on 17 * the distribution table as "eyacc". 18 * 19 * The "gram" script also makes the following changes to the "y.tab.c" 20 * file: 21 * 22 * 1) Causes yyval to be declared int *. 23 * 24 * 2) Loads the variable yypv into a register as yyYpv so that 25 * the arguments $1, ... are available as yyYpv[1] etc. 26 * This produces much smaller code in the semantic actions. 27 * 28 * 3) Deletes the unused array yysterm. 29 * 30 * 4) Moves the declarations up to the flag line containing 31 * '##' to the file yy.h so that the routines which use 32 * these "magic numbers" don't have to all be compiled at 33 * the same time. 34 * 35 * 5) Creates the semantic restriction checking routine yyEactr 36 * by processing action lines containing `@@'. 37 * 38 * This compiler uses a different version of the yacc parser, a 39 * different yyerror which is called yerror, and requires more 40 * lookahead sets than normally provided by yacc. 41 * 42 * Source for the yacc used with this grammar is included on 43 * distribution tapes. 44 */ 45 46 /* 47 * TERMINAL DECLARATIONS 48 * 49 * Some of the terminal declarations are out of the most natural 50 * alphabetic order because the error recovery 51 * will guess the first of equal cost non-terminals. 52 * This makes, e.g. YTO preferable to YDOWNTO. 53 */ 54 55 %term 56 YAND YARRAY YBEGIN YCASE 57 YCONST YDIV YDO YDOTDOT 58 YTO YELSE YEND YFILE 59 YFOR YFORWARD YFUNCTION YGOTO 60 YID YIF YIN YINT 61 YLABEL YMOD YNOT YNUMB 62 YOF YOR YPACKED YNIL 63 YPROCEDURE YPROG YRECORD YREPEAT 64 YSET YSTRING YTHEN YDOWNTO 65 YTYPE YUNTIL YVAR YWHILE 66 YWITH YBINT YOCT YHEX 67 YASSERT YCASELAB YILLCH YLAST 68 YEXTERN 69 70 /* 71 * PRECEDENCE DECLARATIONS 72 * 73 * Highest precedence is the unary logical NOT. 74 * Next are the multiplying operators, signified by '*'. 75 * Lower still are the binary adding operators, signified by '+'. 76 * Finally, at lowest precedence and non-associative are the relationals. 77 */ 78 79 %binary '<' '=' '>' YIN 80 %left '+' '-' YOR '|' 81 %left UNARYSIGN 82 %left '*' '/' YDIV YMOD YAND '&' 83 %left YNOT 84 85 %{ 86 /* 87 * GLOBALS FOR ACTIONS 88 */ 89 90 /* Copyright (c) 1979 Regents of the University of California */ 91 92 /* static char sccsid[] = "@(#)pas.y 1.2 08/27/80"; */ 93 94 /* 95 * The following line marks the end of the yacc 96 * Constant definitions which are removed from 97 * y.tab.c and placed in the file y.tab.h. 98 */ 99 ## 100 /* Copyright (c) 1979 Regents of the University of California */ 101 102 static char sccsid[] = "@(#)pas.y 1.2 08/27/80"; 103 104 #include "whoami.h" 105 #include "0.h" 106 #include "yy.h" 107 #include "tree.h" 108 109 #ifdef PI 110 #define lineof(l) l 111 #define line2of(l) l 112 #endif 113 114 %} 115 116 %% 117 118 /* 119 * PRODUCTIONS 120 */ 121 122 goal: 123 prog_hedr decls procs block '.' 124 = funcend($1, $4, lineof($5)); 125 | 126 decls procs 127 = segend(); 128 ; 129 130 131 prog_hedr: 132 YPROG YID '(' id_list ')' ';' 133 = $$ = funcbody(funchdr(tree5(T_PROG, lineof($1), $2, fixlist($4), NIL))); 134 | 135 YPROG error 136 = { 137 yyPerror("Malformed program statement", PPROG); 138 /* 139 * Should make a program statement 140 * with "input" and "output" here. 141 */ 142 $$ = funcbody(funchdr(tree5(T_PROG, lineof($1), NIL, NIL, NIL))); 143 } 144 ; 145 block: 146 YBEGIN stat_list YEND 147 = { 148 $$ = tree3(T_BSTL, lineof($1), fixlist($2)); 149 if ($3 < 0) 150 brerror($1, "begin"); 151 } 152 ; 153 154 155 /* 156 * DECLARATION PART 157 */ 158 decls: 159 decls decl 160 = trfree(); 161 | 162 decls error 163 = { 164 Derror: 165 constend(), typeend(), varend(), trfree(); 166 yyPerror("Malformed declaration", PDECL); 167 } 168 | 169 /* lambda */ 170 = trfree(); 171 ; 172 173 decl: 174 labels 175 | 176 const_decl 177 = constend(); 178 | 179 type_decl 180 = typeend(); 181 | 182 var_decl 183 = varend(); 184 ; 185 186 /* 187 * LABEL PART 188 */ 189 190 labels: 191 YLABEL label_decl ';' 192 = label(fixlist($2), lineof($1)); 193 ; 194 label_decl: 195 YINT 196 = $$ = newlist($1 == NIL ? NIL : *hash($1, 1)); 197 | 198 label_decl ',' YINT 199 = $$ = addlist($1, $3 == NIL ? NIL : *hash($3, 1)); 200 ; 201 202 /* 203 * CONST PART 204 */ 205 206 const_decl: 207 YCONST YID '=' const ';' 208 = constbeg($1, line2of($2)), const(lineof($3), $2, $4); 209 | 210 const_decl YID '=' const ';' 211 = const(lineof($3), $2, $4); 212 | 213 YCONST error 214 = { 215 constbeg($1, line2of($1)); 216 Cerror: 217 yyPerror("Malformed const declaration", PDECL); 218 } 219 | 220 const_decl error 221 = goto Cerror; 222 ; 223 224 /* 225 * TYPE PART 226 */ 227 228 type_decl: 229 YTYPE YID '=' type ';' 230 = typebeg($1, line2of($2)), type(lineof($3), $2, $4); 231 | 232 type_decl YID '=' type ';' 233 = type(lineof($3), $2, $4); 234 | 235 YTYPE error 236 = { 237 typebeg($1, line2of($1)); 238 Terror: 239 yyPerror("Malformed type declaration", PDECL); 240 } 241 | 242 type_decl error 243 = goto Terror; 244 ; 245 246 /* 247 * VAR PART 248 */ 249 250 var_decl: 251 YVAR id_list ':' type ';' 252 = varbeg($1, line2of($3)), var(lineof($3), fixlist($2), $4); 253 | 254 var_decl id_list ':' type ';' 255 = var(lineof($3), fixlist($2), $4); 256 | 257 YVAR error 258 = { 259 varbeg($1, line2of($1)); 260 Verror: 261 yyPerror("Malformed var declaration", PDECL); 262 } 263 | 264 var_decl error 265 = goto Verror; 266 ; 267 268 /* 269 * PROCEDURE AND FUNCTION DECLARATION PART 270 */ 271 272 procs: 273 /* lambda */ 274 | 275 procs proc 276 = trfree(); 277 ; 278 proc: 279 phead YFORWARD ';' 280 = funcfwd($1); 281 | 282 phead YEXTERN ';' 283 = funcext($1); 284 | 285 pheadres decls procs block ';' 286 = funcend($1, $4, lineof($5)); 287 ; 288 pheadres: 289 phead 290 = funcbody($1); 291 ; 292 phead: 293 porf YID params ftype ';' 294 = $$ = funchdr(tree5($1, lineof($5), $2, $3, $4)); 295 ; 296 porf: 297 YPROCEDURE 298 = $$ = T_PDEC; 299 | 300 YFUNCTION 301 = $$ = T_FDEC; 302 ; 303 params: 304 '(' param_list ')' 305 = $$ = fixlist($2); 306 | 307 /* lambda */ 308 = $$ = NIL; 309 ; 310 311 /* 312 * PARAMETERS 313 */ 314 315 param: 316 id_list ':' type 317 = $$ = tree3(T_PVAL, fixlist($1), $3); 318 | 319 YVAR id_list ':' type 320 = $$ = tree3(T_PVAR, fixlist($2), $4); 321 | 322 YFUNCTION id_list ':' type 323 = $$ = tree3(T_PFUNC, fixlist($2), $4); 324 | 325 YPROCEDURE id_list 326 = $$ = tree2(T_PPROC, fixlist($2)); 327 ; 328 ftype: 329 ':' type 330 = $$ = $2; 331 | 332 /* lambda */ 333 = $$ = NIL; 334 ; 335 param_list: 336 param 337 = $$ = newlist($1); 338 | 339 param_list ';' param 340 = $$ = addlist($1, $3); 341 ; 342 343 /* 344 * CONSTANTS 345 */ 346 347 const: 348 YSTRING 349 = $$ = tree2(T_CSTRNG, $1); 350 | 351 number 352 | 353 '+' number 354 = $$ = tree2(T_PLUSC, $2); 355 | 356 '-' number 357 = $$ = tree2(T_MINUSC, $2); 358 ; 359 number: 360 const_id 361 = $$ = tree2(T_ID, $1); 362 | 363 YINT 364 = $$ = tree2(T_CINT, $1); 365 | 366 YBINT 367 = $$ = tree2(T_CBINT, $1); 368 | 369 YNUMB 370 = $$ = tree2(T_CFINT, $1); 371 ; 372 const_list: 373 const 374 = $$ = newlist($1); 375 | 376 const_list ',' const 377 = $$ = addlist($1, $3); 378 ; 379 380 /* 381 * TYPES 382 */ 383 384 type: 385 simple_type 386 | 387 '^' YID 388 = $$ = tree3(T_TYPTR, lineof($1), tree2(T_ID, $2)); 389 | 390 struct_type 391 | 392 YPACKED struct_type 393 = $$ = tree3(T_TYPACK, lineof($1), $2); 394 ; 395 simple_type: 396 type_id 397 | 398 '(' id_list ')' 399 = $$ = tree3(T_TYSCAL, lineof($1), fixlist($2)); 400 | 401 const YDOTDOT const 402 = $$ = tree4(T_TYRANG, lineof($2), $1, $3); 403 ; 404 struct_type: 405 YARRAY '[' simple_type_list ']' YOF type 406 = $$ = tree4(T_TYARY, lineof($1), fixlist($3), $6); 407 | 408 YFILE YOF type 409 = $$ = tree3(T_TYFILE, lineof($1), $3); 410 | 411 YSET YOF simple_type 412 = $$ = tree3(T_TYSET, lineof($1), $3); 413 | 414 YRECORD field_list YEND 415 = { 416 $$ = setuptyrec( lineof( $1 ) , $2 ); 417 if ($3 < 0) 418 brerror($1, "record"); 419 } 420 ; 421 simple_type_list: 422 simple_type 423 = $$ = newlist($1); 424 | 425 simple_type_list ',' simple_type 426 = $$ = addlist($1, $3); 427 ; 428 429 /* 430 * RECORD TYPE 431 */ 432 field_list: 433 fixed_part variant_part 434 = $$ = tree4(T_FLDLST, lineof(NIL), fixlist($1), $2); 435 ; 436 fixed_part: 437 field 438 = $$ = newlist($1); 439 | 440 fixed_part ';' field 441 = $$ = addlist($1, $3); 442 | 443 fixed_part error 444 = yyPerror("Malformed record declaration", PDECL); 445 ; 446 field: 447 /* lambda */ 448 = $$ = NIL; 449 | 450 id_list ':' type 451 = $$ = tree4(T_RFIELD, lineof($2), fixlist($1), $3); 452 ; 453 454 variant_part: 455 /* lambda */ 456 = $$ = NIL; 457 | 458 YCASE type_id YOF variant_list 459 = $$ = tree5(T_TYVARPT, lineof($1), NIL, $2, fixlist($4)); 460 | 461 YCASE YID ':' type_id YOF variant_list 462 = $$ = tree5(T_TYVARPT, lineof($1), $2, $4, fixlist($6)); 463 ; 464 variant_list: 465 variant 466 = $$ = newlist($1); 467 | 468 variant_list ';' variant 469 = $$ = addlist($1, $3); 470 | 471 variant_list error 472 = yyPerror("Malformed record declaration", PDECL); 473 ; 474 variant: 475 /* lambda */ 476 = $$ = NIL; 477 | 478 const_list ':' '(' field_list ')' 479 = $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), $4); 480 | 481 const_list ':' '(' ')' 482 = $$ = tree4(T_TYVARNT, lineof($2), fixlist($1), NIL); 483 ; 484 485 /* 486 * STATEMENT LIST 487 */ 488 489 stat_list: 490 stat 491 = $$ = newlist($1); 492 | 493 stat_lsth stat 494 = { 495 if ((p = $1) != NIL && (q = p[1])[0] == T_IFX) { 496 q[0] = T_IFEL; 497 q[4] = $2; 498 } else 499 $$ = addlist($1, $2); 500 } 501 ; 502 503 stat_lsth: 504 stat_list ';' 505 = if ((q = $1) != NIL && (p = q[1]) != NIL && p[0] == T_IF) { 506 if (yychar < 0) 507 yychar = yylex(); 508 if (yyshifts >= 2 && yychar == YELSE) { 509 recovered(); 510 copy(&Y, &OY, sizeof Y); 511 yerror("Deleted ';' before keyword else"); 512 yychar = yylex(); 513 p[0] = T_IFX; 514 } 515 } 516 ; 517 518 /* 519 * CASE STATEMENT LIST 520 */ 521 522 cstat_list: 523 cstat 524 = $$ = newlist($1); 525 | 526 cstat_list ';' cstat 527 = $$ = addlist($1, $3); 528 | 529 error 530 = { 531 $$ = NIL; 532 Kerror: 533 yyPerror("Malformed statement in case", PSTAT); 534 } 535 | 536 cstat_list error 537 = goto Kerror; 538 ; 539 540 cstat: 541 const_list ':' stat 542 = $$ = tree4(T_CSTAT, lineof($2), fixlist($1), $3); 543 | 544 YCASELAB stat 545 = $$ = tree4(T_CSTAT, lineof($1), NIL, $2); 546 | 547 /* lambda */ 548 = $$ = NIL; 549 ; 550 551 /* 552 * STATEMENT 553 */ 554 555 stat: 556 /* lambda */ 557 = $$ = NIL; 558 | 559 YINT ':' stat 560 = $$ = tree4(T_LABEL, lineof($2), $1 == NIL ? NIL : *hash($1, 1), $3); 561 | 562 proc_id 563 = $$ = tree4(T_PCALL, lineof(yyline), $1, NIL); 564 | 565 proc_id '(' wexpr_list ')' 566 = $$ = tree4(T_PCALL, lineof($2), $1, fixlist($3)); 567 | 568 YID error 569 = goto NSerror; 570 | 571 assign 572 | 573 YBEGIN stat_list YEND 574 = { 575 $$ = tree3(T_BLOCK, lineof($1), fixlist($2)); 576 if ($3 < 0) 577 brerror($1, "begin"); 578 } 579 | 580 YCASE expr YOF cstat_list YEND 581 = { 582 $$ = tree4(T_CASE, lineof($1), $2, fixlist($4)); 583 if ($5 < 0) 584 brerror($1, "case"); 585 } 586 | 587 YWITH var_list YDO stat 588 = $$ = tree4(T_WITH, lineof($1), fixlist($2), $4); 589 | 590 YWHILE expr YDO stat 591 = $$ = tree4(T_WHILE, lineof($1), $2, $4); 592 | 593 YREPEAT stat_list YUNTIL expr 594 = $$ = tree4(T_REPEAT, lineof($3), fixlist($2), $4); 595 | 596 YFOR assign YTO expr YDO stat 597 = $$ = tree5(T_FORU, lineof($1), $2, $4, $6); 598 | 599 YFOR assign YDOWNTO expr YDO stat 600 = $$ = tree5(T_FORD, lineof($1), $2, $4, $6); 601 | 602 YGOTO YINT 603 = $$ = tree3(T_GOTO, lineof($1), *hash($2, 1)); 604 | 605 YIF expr YTHEN stat 606 = $$ = tree5(T_IF, lineof($1), $2, $4, NIL); 607 | 608 YIF expr YTHEN stat YELSE stat 609 = $$ = tree5(T_IFEL, lineof($1), $2, $4, $6); 610 | 611 YIF expr YTHEN stat YELSE 612 = $$ = tree5(T_IFEL, lineof($1), $2, $4, NIL); 613 | 614 YASSERT '(' expr ')' 615 = $$ = tree3(T_ASRT, lineof($1), $3); 616 | 617 error 618 = { 619 NSerror: 620 $$ = NIL; 621 Serror: 622 yyPerror("Malformed statement", PSTAT); 623 } 624 ; 625 assign: 626 variable ':' '=' expr 627 = $$ = tree4(T_ASGN, lineof($2), $1, $4); 628 ; 629 630 /* 631 * EXPRESSION 632 */ 633 634 expr: 635 error 636 = { 637 NEerror: 638 $$ = NIL; 639 Eerror: 640 yyPerror("Missing/malformed expression", PEXPR); 641 } 642 | 643 expr relop expr %prec '<' 644 = $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3); 645 | 646 '+' expr %prec UNARYSIGN 647 = $$ = tree3(T_PLUS, $2[1], $2); 648 | 649 '-' expr %prec UNARYSIGN 650 = $$ = tree3(T_MINUS, $2[1], $2); 651 | 652 expr addop expr %prec '+' 653 = $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3); 654 | 655 expr divop expr %prec '*' 656 = $$ = tree4($2, $1[1] == SAWCON ? $3[1] : $1[1], $1, $3); 657 | 658 YNIL 659 = $$ = tree2(T_NIL, NOCON); 660 | 661 YSTRING 662 = $$ = tree3(T_STRNG, SAWCON, $1); 663 | 664 YINT 665 = $$ = tree3(T_INT, NOCON, $1); 666 | 667 YBINT 668 = $$ = tree3(T_BINT, NOCON, $1); 669 | 670 YNUMB 671 = $$ = tree3(T_FINT, NOCON, $1); 672 | 673 variable 674 | 675 YID error 676 = goto NEerror; 677 | 678 func_id '(' wexpr_list ')' 679 = $$ = tree4(T_FCALL, NOCON, $1, fixlist($3)); 680 | 681 '(' expr ')' 682 = $$ = $2; 683 | 684 negop expr %prec YNOT 685 = $$ = tree3(T_NOT, NOCON, $2); 686 | 687 '[' element_list ']' 688 = $$ = tree3(T_CSET, SAWCON, fixlist($2)); 689 | 690 '[' ']' 691 = $$ = tree3(T_CSET, SAWCON, NIL); 692 ; 693 694 element_list: 695 element 696 = $$ = newlist($1); 697 | 698 element_list ',' element 699 = $$ = addlist($1, $3); 700 ; 701 element: 702 expr 703 | 704 expr YDOTDOT expr 705 = $$ = tree3(T_RANG, $1, $3); 706 ; 707 708 /* 709 * QUALIFIED VARIABLES 710 */ 711 712 variable: 713 YID 714 = { 715 @@ return (identis(var, VAR)); 716 $$ = setupvar($1, NIL); 717 } 718 | 719 qual_var 720 = $1[3] = fixlist($1[3]); 721 ; 722 qual_var: 723 array_id '[' expr_list ']' 724 = $$ = setupvar($1, tree2(T_ARY, fixlist($3))); 725 | 726 qual_var '[' expr_list ']' 727 = $1[3] = addlist($1[3], tree2(T_ARY, fixlist($3))); 728 | 729 record_id '.' field_id 730 = $$ = setupvar($1, setupfield($3, NIL)); 731 | 732 qual_var '.' field_id 733 = $1[3] = addlist($1[3], setupfield($3, NIL)); 734 | 735 ptr_id '^' 736 = $$ = setupvar($1, tree1(T_PTR)); 737 | 738 qual_var '^' 739 = $1[3] = addlist($1[3], tree1(T_PTR)); 740 ; 741 742 /* 743 * Expression with write widths 744 */ 745 wexpr: 746 expr 747 | 748 expr ':' expr 749 = $$ = tree4(T_WEXP, $1, $3, NIL); 750 | 751 expr ':' expr ':' expr 752 = $$ = tree4(T_WEXP, $1, $3, $5); 753 | 754 expr octhex 755 = $$ = tree4(T_WEXP, $1, NIL, $2); 756 | 757 expr ':' expr octhex 758 = $$ = tree4(T_WEXP, $1, $3, $4); 759 ; 760 octhex: 761 YOCT 762 = $$ = OCT; 763 | 764 YHEX 765 = $$ = HEX; 766 ; 767 768 expr_list: 769 expr 770 = $$ = newlist($1); 771 | 772 expr_list ',' expr 773 = $$ = addlist($1, $3); 774 ; 775 776 wexpr_list: 777 wexpr 778 = $$ = newlist($1); 779 | 780 wexpr_list ',' wexpr 781 = $$ = addlist($1, $3); 782 ; 783 784 /* 785 * OPERATORS 786 */ 787 788 relop: 789 '=' = $$ = T_EQ; 790 | 791 '<' = $$ = T_LT; 792 | 793 '>' = $$ = T_GT; 794 | 795 '<' '>' = $$ = T_NE; 796 | 797 '<' '=' = $$ = T_LE; 798 | 799 '>' '=' = $$ = T_GE; 800 | 801 YIN = $$ = T_IN; 802 ; 803 addop: 804 '+' = $$ = T_ADD; 805 | 806 '-' = $$ = T_SUB; 807 | 808 YOR = $$ = T_OR; 809 | 810 '|' = $$ = T_OR; 811 ; 812 divop: 813 '*' = $$ = T_MULT; 814 | 815 '/' = $$ = T_DIVD; 816 | 817 YDIV = $$ = T_DIV; 818 | 819 YMOD = $$ = T_MOD; 820 | 821 YAND = $$ = T_AND; 822 | 823 '&' = $$ = T_AND; 824 ; 825 826 negop: 827 YNOT 828 | 829 '~' 830 ; 831 832 /* 833 * LISTS 834 */ 835 836 var_list: 837 variable 838 = $$ = newlist($1); 839 | 840 var_list ',' variable 841 = $$ = addlist($1, $3); 842 ; 843 844 id_list: 845 YID 846 = $$ = newlist($1); 847 | 848 id_list ',' YID 849 = $$ = addlist($1, $3); 850 ; 851 852 /* 853 * Identifier productions with semantic restrictions 854 * 855 * For these productions, the characters @@ signify 856 * that the associated C statement is to provide 857 * the semantic restriction for this reduction. 858 * These lines are made into a procedure yyEactr, similar to 859 * yyactr, which determines whether the corresponding reduction 860 * is permitted, or whether an error is to be signaled. 861 * A zero return from yyEactr is considered an error. 862 * YyEactr is called with an argument "var" giving the string 863 * name of the variable in question, essentially $1, although 864 * $1 will not work because yyEactr is called from loccor in 865 * the recovery routines. 866 */ 867 868 const_id: 869 YID 870 = @@ return (identis(var, CONST)); 871 ; 872 type_id: 873 YID 874 = { 875 @@ return (identis(var, TYPE)); 876 $$ = tree3(T_TYID, lineof(yyline), $1); 877 } 878 ; 879 var_id: 880 YID 881 = @@ return (identis(var, VAR)); 882 ; 883 array_id: 884 YID 885 = @@ return (identis(var, ARRAY)); 886 ; 887 ptr_id: 888 YID 889 = @@ return (identis(var, PTRFILE)); 890 ; 891 record_id: 892 YID 893 = @@ return (identis(var, RECORD)); 894 ; 895 field_id: 896 YID 897 = @@ return (identis(var, FIELD)); 898 ; 899 proc_id: 900 YID 901 = @@ return (identis(var, PROC)); 902 ; 903 func_id: 904 YID 905 = @@ return (identis(var, FUNC)); 906 ; 907