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