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