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