1 /* $OpenBSD: reader.c,v 1.20 2006/04/21 07:38:16 deraadt Exp $ */ 2 /* $NetBSD: reader.c,v 1.5 1996/03/19 03:21:43 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1989 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Robert Paul Corbett. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)reader.c 5.7 (Berkeley) 1/20/91"; 39 #else 40 static char rcsid[] = "$NetBSD: reader.c,v 1.5 1996/03/19 03:21:43 jtc Exp $"; 41 #endif 42 #endif /* not lint */ 43 44 #include "defs.h" 45 46 /* The line size must be a positive integer. One hundred was chosen */ 47 /* because few lines in Yacc input grammars exceed 100 characters. */ 48 /* Note that if a line exceeds LINESIZE characters, the line buffer */ 49 /* will be expanded to accommodate it. */ 50 51 #define LINESIZE 100 52 53 char *cache; 54 int cinc, cache_size; 55 56 int ntags, tagmax; 57 char **tag_table; 58 59 char saw_eof, unionized; 60 char *cptr, *line; 61 int linesize; 62 63 bucket *goal; 64 int prec; 65 int gensym; 66 char last_was_action; 67 68 int maxitems; 69 bucket **pitem; 70 71 int maxrules; 72 bucket **plhs; 73 74 int name_pool_size; 75 char *name_pool; 76 77 void cachec(int); 78 void get_line(void); 79 char * dup_line(void); 80 void skip_comment(void); 81 int nextc(void); 82 int keyword(void); 83 void copy_ident(void); 84 void copy_text(void); 85 void copy_union(void); 86 int hexval(int); 87 bucket * get_literal(void); 88 int is_reserved(char *); 89 bucket * get_name(void); 90 int get_number(void); 91 char * get_tag(void); 92 void declare_tokens(int); 93 void declare_types(void); 94 void declare_start(void); 95 void handle_expect(void); 96 void read_declarations(void); 97 void initialize_grammar(void); 98 void expand_items(void); 99 void expand_rules(void); 100 void advance_to_start(void); 101 void start_rule(bucket *, int); 102 void end_rule(void); 103 void insert_empty_rule(void); 104 void add_symbol(void); 105 void copy_action(void); 106 int mark_symbol(void); 107 void read_grammar(void); 108 void free_tags(void); 109 void pack_names(void); 110 void check_symbols(void); 111 void pack_symbols(void); 112 void pack_grammar(void); 113 void print_grammar(void); 114 115 char line_format[] = "#line %d \"%s\"\n"; 116 117 void 118 cachec(int c) 119 { 120 assert(cinc >= 0); 121 if (cinc >= cache_size) 122 { 123 cache_size += 256; 124 cache = REALLOC(cache, cache_size); 125 if (cache == 0) no_space(); 126 } 127 cache[cinc] = c; 128 ++cinc; 129 } 130 131 132 void 133 get_line(void) 134 { 135 FILE *f = input_file; 136 int c; 137 int i; 138 139 if (saw_eof || (c = getc(f)) == EOF) 140 { 141 if (line) { FREE(line); line = 0; } 142 cptr = 0; 143 saw_eof = 1; 144 return; 145 } 146 147 if (line == 0 || linesize != (LINESIZE + 1)) 148 { 149 if (line) FREE(line); 150 linesize = LINESIZE + 1; 151 line = MALLOC(linesize); 152 if (line == 0) no_space(); 153 } 154 155 i = 0; 156 ++lineno; 157 for (;;) 158 { 159 line[i] = c; 160 if (c == '\n') { cptr = line; return; } 161 if (++i >= linesize) 162 { 163 linesize += LINESIZE; 164 line = REALLOC(line, linesize); 165 if (line == 0) no_space(); 166 } 167 c = getc(f); 168 if (c == EOF) 169 { 170 line[i] = '\n'; 171 saw_eof = 1; 172 cptr = line; 173 return; 174 } 175 } 176 } 177 178 179 char * 180 dup_line(void) 181 { 182 char *p, *s, *t; 183 184 if (line == 0) return (0); 185 s = line; 186 while (*s != '\n') ++s; 187 p = MALLOC(s - line + 1); 188 if (p == 0) no_space(); 189 190 s = line; 191 t = p; 192 while ((*t++ = *s++) != '\n') continue; 193 return (p); 194 } 195 196 197 void 198 skip_comment(void) 199 { 200 char *s; 201 202 int st_lineno = lineno; 203 char *st_line = dup_line(); 204 char *st_cptr = st_line + (cptr - line); 205 206 s = cptr + 2; 207 for (;;) 208 { 209 if (*s == '*' && s[1] == '/') 210 { 211 cptr = s + 2; 212 FREE(st_line); 213 return; 214 } 215 if (*s == '\n') 216 { 217 get_line(); 218 if (line == 0) 219 unterminated_comment(st_lineno, st_line, st_cptr); 220 s = cptr; 221 } 222 else 223 ++s; 224 } 225 } 226 227 228 int 229 nextc(void) 230 { 231 char *s; 232 233 if (line == 0) 234 { 235 get_line(); 236 if (line == 0) 237 return (EOF); 238 } 239 240 s = cptr; 241 for (;;) 242 { 243 switch (*s) 244 { 245 case '\n': 246 get_line(); 247 if (line == 0) return (EOF); 248 s = cptr; 249 break; 250 251 case ' ': 252 case '\t': 253 case '\f': 254 case '\r': 255 case '\v': 256 case ',': 257 case ';': 258 ++s; 259 break; 260 261 case '\\': 262 cptr = s; 263 return ('%'); 264 265 case '/': 266 if (s[1] == '*') 267 { 268 cptr = s; 269 skip_comment(); 270 s = cptr; 271 break; 272 } 273 else if (s[1] == '/') 274 { 275 get_line(); 276 if (line == 0) return (EOF); 277 s = cptr; 278 break; 279 } 280 /* fall through */ 281 282 default: 283 cptr = s; 284 return (*s); 285 } 286 } 287 } 288 289 290 int 291 keyword(void) 292 { 293 int c; 294 char *t_cptr = cptr; 295 296 c = *++cptr; 297 if (isalpha(c)) 298 { 299 cinc = 0; 300 for (;;) 301 { 302 if (isalpha(c)) 303 { 304 if (isupper(c)) c = tolower(c); 305 cachec(c); 306 } 307 else if (isdigit(c) || c == '_' || c == '.' || c == '$') 308 cachec(c); 309 else 310 break; 311 c = *++cptr; 312 } 313 cachec(NUL); 314 315 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0) 316 return (TOKEN); 317 if (strcmp(cache, "type") == 0) 318 return (TYPE); 319 if (strcmp(cache, "left") == 0) 320 return (LEFT); 321 if (strcmp(cache, "right") == 0) 322 return (RIGHT); 323 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0) 324 return (NONASSOC); 325 if (strcmp(cache, "start") == 0) 326 return (START); 327 if (strcmp(cache, "union") == 0) 328 return (UNION); 329 if (strcmp(cache, "ident") == 0) 330 return (IDENT); 331 if (strcmp(cache, "expect") == 0) 332 return (EXPECT); 333 } 334 else 335 { 336 ++cptr; 337 if (c == '{') 338 return (TEXT); 339 if (c == '%' || c == '\\') 340 return (MARK); 341 if (c == '<') 342 return (LEFT); 343 if (c == '>') 344 return (RIGHT); 345 if (c == '0') 346 return (TOKEN); 347 if (c == '2') 348 return (NONASSOC); 349 } 350 syntax_error(lineno, line, t_cptr); 351 /*NOTREACHED*/ 352 return (0); 353 } 354 355 356 void 357 copy_ident(void) 358 { 359 int c; 360 FILE *f = output_file; 361 362 c = nextc(); 363 if (c == EOF) unexpected_EOF(); 364 if (c != '"') syntax_error(lineno, line, cptr); 365 ++outline; 366 fprintf(f, "#ident \""); 367 for (;;) 368 { 369 c = *++cptr; 370 if (c == '\n') 371 { 372 fprintf(f, "\"\n"); 373 return; 374 } 375 putc(c, f); 376 if (c == '"') 377 { 378 putc('\n', f); 379 ++cptr; 380 return; 381 } 382 } 383 } 384 385 386 void 387 copy_text(void) 388 { 389 int c; 390 int quote; 391 FILE *f = text_file; 392 int need_newline = 0; 393 int t_lineno = lineno; 394 char *t_line = dup_line(); 395 char *t_cptr = t_line + (cptr - line - 2); 396 397 if (*cptr == '\n') 398 { 399 get_line(); 400 if (line == 0) 401 unterminated_text(t_lineno, t_line, t_cptr); 402 } 403 if (!lflag) fprintf(f, line_format, lineno, input_file_name); 404 405 loop: 406 c = *cptr++; 407 switch (c) 408 { 409 case '\n': 410 next_line: 411 putc('\n', f); 412 need_newline = 0; 413 get_line(); 414 if (line) goto loop; 415 unterminated_text(t_lineno, t_line, t_cptr); 416 417 case '\'': 418 case '"': 419 { 420 int s_lineno = lineno; 421 char *s_line = dup_line(); 422 char *s_cptr = s_line + (cptr - line - 1); 423 424 quote = c; 425 putc(c, f); 426 for (;;) 427 { 428 c = *cptr++; 429 putc(c, f); 430 if (c == quote) 431 { 432 need_newline = 1; 433 FREE(s_line); 434 goto loop; 435 } 436 if (c == '\n') 437 unterminated_string(s_lineno, s_line, s_cptr); 438 if (c == '\\') 439 { 440 c = *cptr++; 441 putc(c, f); 442 if (c == '\n') 443 { 444 get_line(); 445 if (line == 0) 446 unterminated_string(s_lineno, s_line, s_cptr); 447 } 448 } 449 } 450 } 451 452 case '/': 453 putc(c, f); 454 need_newline = 1; 455 c = *cptr; 456 if (c == '/') 457 { 458 putc('*', f); 459 while ((c = *++cptr) != '\n') 460 { 461 if (c == '*' && cptr[1] == '/') 462 fprintf(f, "* "); 463 else 464 putc(c, f); 465 } 466 fprintf(f, "*/"); 467 goto next_line; 468 } 469 if (c == '*') 470 { 471 int c_lineno = lineno; 472 char *c_line = dup_line(); 473 char *c_cptr = c_line + (cptr - line - 1); 474 475 putc('*', f); 476 ++cptr; 477 for (;;) 478 { 479 c = *cptr++; 480 putc(c, f); 481 if (c == '*' && *cptr == '/') 482 { 483 putc('/', f); 484 ++cptr; 485 FREE(c_line); 486 goto loop; 487 } 488 if (c == '\n') 489 { 490 get_line(); 491 if (line == 0) 492 unterminated_comment(c_lineno, c_line, c_cptr); 493 } 494 } 495 } 496 need_newline = 1; 497 goto loop; 498 499 case '%': 500 case '\\': 501 if (*cptr == '}') 502 { 503 if (need_newline) putc('\n', f); 504 ++cptr; 505 FREE(t_line); 506 return; 507 } 508 /* fall through */ 509 510 default: 511 putc(c, f); 512 need_newline = 1; 513 goto loop; 514 } 515 } 516 517 518 void 519 copy_union(void) 520 { 521 int c; 522 int quote; 523 int depth; 524 int u_lineno = lineno; 525 char *u_line = dup_line(); 526 char *u_cptr = u_line + (cptr - line - 6); 527 528 if (unionized) over_unionized(cptr - 6); 529 unionized = 1; 530 531 if (!lflag) 532 fprintf(text_file, line_format, lineno, input_file_name); 533 534 fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n"); 535 fprintf(text_file, "#define YYSTYPE_DEFINED\n"); 536 fprintf(text_file, "typedef union"); 537 if (dflag) fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n"); 538 if (dflag) fprintf(union_file, "#define YYSTYPE_DEFINED\n"); 539 if (dflag) fprintf(union_file, "typedef union"); 540 541 depth = 0; 542 loop: 543 c = *cptr++; 544 putc(c, text_file); 545 if (dflag) putc(c, union_file); 546 switch (c) 547 { 548 case '\n': 549 next_line: 550 get_line(); 551 if (line == 0) unterminated_union(u_lineno, u_line, u_cptr); 552 goto loop; 553 554 case '{': 555 ++depth; 556 goto loop; 557 558 case '}': 559 if (--depth == 0) 560 { 561 fprintf(text_file, " YYSTYPE;\n"); 562 fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n"); 563 FREE(u_line); 564 return; 565 } 566 goto loop; 567 568 case '\'': 569 case '"': 570 { 571 int s_lineno = lineno; 572 char *s_line = dup_line(); 573 char *s_cptr = s_line + (cptr - line - 1); 574 575 quote = c; 576 for (;;) 577 { 578 c = *cptr++; 579 putc(c, text_file); 580 if (dflag) putc(c, union_file); 581 if (c == quote) 582 { 583 FREE(s_line); 584 goto loop; 585 } 586 if (c == '\n') 587 unterminated_string(s_lineno, s_line, s_cptr); 588 if (c == '\\') 589 { 590 c = *cptr++; 591 putc(c, text_file); 592 if (dflag) putc(c, union_file); 593 if (c == '\n') 594 { 595 get_line(); 596 if (line == 0) 597 unterminated_string(s_lineno, s_line, s_cptr); 598 } 599 } 600 } 601 } 602 603 case '/': 604 c = *cptr; 605 if (c == '/') 606 { 607 putc('*', text_file); 608 if (dflag) putc('*', union_file); 609 while ((c = *++cptr) != '\n') 610 { 611 if (c == '*' && cptr[1] == '/') 612 { 613 fprintf(text_file, "* "); 614 if (dflag) fprintf(union_file, "* "); 615 } 616 else 617 { 618 putc(c, text_file); 619 if (dflag) putc(c, union_file); 620 } 621 } 622 fprintf(text_file, "*/\n"); 623 if (dflag) fprintf(union_file, "*/\n"); 624 goto next_line; 625 } 626 if (c == '*') 627 { 628 int c_lineno = lineno; 629 char *c_line = dup_line(); 630 char *c_cptr = c_line + (cptr - line - 1); 631 632 putc('*', text_file); 633 if (dflag) putc('*', union_file); 634 ++cptr; 635 for (;;) 636 { 637 c = *cptr++; 638 putc(c, text_file); 639 if (dflag) putc(c, union_file); 640 if (c == '*' && *cptr == '/') 641 { 642 putc('/', text_file); 643 if (dflag) putc('/', union_file); 644 ++cptr; 645 FREE(c_line); 646 goto loop; 647 } 648 if (c == '\n') 649 { 650 get_line(); 651 if (line == 0) 652 unterminated_comment(c_lineno, c_line, c_cptr); 653 } 654 } 655 } 656 goto loop; 657 658 default: 659 goto loop; 660 } 661 } 662 663 664 int 665 hexval(int c) 666 { 667 if (c >= '0' && c <= '9') 668 return (c - '0'); 669 if (c >= 'A' && c <= 'F') 670 return (c - 'A' + 10); 671 if (c >= 'a' && c <= 'f') 672 return (c - 'a' + 10); 673 return (-1); 674 } 675 676 677 bucket * 678 get_literal(void) 679 { 680 int c, quote; 681 int i; 682 int n; 683 char *s; 684 bucket *bp; 685 int s_lineno = lineno; 686 char *s_line = dup_line(); 687 char *s_cptr = s_line + (cptr - line); 688 689 quote = *cptr++; 690 cinc = 0; 691 for (;;) 692 { 693 c = *cptr++; 694 if (c == quote) break; 695 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); 696 if (c == '\\') 697 { 698 char *c_cptr = cptr - 1; 699 700 c = *cptr++; 701 switch (c) 702 { 703 case '\n': 704 get_line(); 705 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr); 706 continue; 707 708 case '0': case '1': case '2': case '3': 709 case '4': case '5': case '6': case '7': 710 n = c - '0'; 711 c = *cptr; 712 if (IS_OCTAL(c)) 713 { 714 n = (n << 3) + (c - '0'); 715 c = *++cptr; 716 if (IS_OCTAL(c)) 717 { 718 n = (n << 3) + (c - '0'); 719 ++cptr; 720 } 721 } 722 if (n > MAXCHAR) illegal_character(c_cptr); 723 c = n; 724 break; 725 726 case 'x': 727 c = *cptr++; 728 n = hexval(c); 729 if (n < 0 || n >= 16) 730 illegal_character(c_cptr); 731 for (;;) 732 { 733 c = *cptr; 734 i = hexval(c); 735 if (i < 0 || i >= 16) break; 736 ++cptr; 737 n = (n << 4) + i; 738 if (n > MAXCHAR) illegal_character(c_cptr); 739 } 740 c = n; 741 break; 742 743 case 'a': c = 7; break; 744 case 'b': c = '\b'; break; 745 case 'f': c = '\f'; break; 746 case 'n': c = '\n'; break; 747 case 'r': c = '\r'; break; 748 case 't': c = '\t'; break; 749 case 'v': c = '\v'; break; 750 } 751 } 752 cachec(c); 753 } 754 FREE(s_line); 755 756 n = cinc; 757 s = MALLOC(n); 758 if (s == 0) no_space(); 759 760 for (i = 0; i < n; ++i) 761 s[i] = cache[i]; 762 763 cinc = 0; 764 if (n == 1) 765 cachec('\''); 766 else 767 cachec('"'); 768 769 for (i = 0; i < n; ++i) 770 { 771 c = ((unsigned char *)s)[i]; 772 if (c == '\\' || c == cache[0]) 773 { 774 cachec('\\'); 775 cachec(c); 776 } 777 else if (isprint(c)) 778 cachec(c); 779 else 780 { 781 cachec('\\'); 782 switch (c) 783 { 784 case 7: cachec('a'); break; 785 case '\b': cachec('b'); break; 786 case '\f': cachec('f'); break; 787 case '\n': cachec('n'); break; 788 case '\r': cachec('r'); break; 789 case '\t': cachec('t'); break; 790 case '\v': cachec('v'); break; 791 default: 792 cachec(((c >> 6) & 7) + '0'); 793 cachec(((c >> 3) & 7) + '0'); 794 cachec((c & 7) + '0'); 795 break; 796 } 797 } 798 } 799 800 if (n == 1) 801 cachec('\''); 802 else 803 cachec('"'); 804 805 cachec(NUL); 806 bp = lookup(cache); 807 bp->class = TERM; 808 if (n == 1 && bp->value == UNDEFINED) 809 bp->value = *(unsigned char *)s; 810 FREE(s); 811 812 return (bp); 813 } 814 815 816 int 817 is_reserved(char *name) 818 { 819 char *s; 820 821 if (strcmp(name, ".") == 0 || 822 strcmp(name, "$accept") == 0 || 823 strcmp(name, "$end") == 0) 824 return (1); 825 826 if (name[0] == '$' && name[1] == '$' && isdigit(name[2])) 827 { 828 s = name + 3; 829 while (isdigit(*s)) ++s; 830 if (*s == NUL) return (1); 831 } 832 833 return (0); 834 } 835 836 837 bucket * 838 get_name(void) 839 { 840 int c; 841 842 cinc = 0; 843 for (c = *cptr; IS_IDENT(c); c = *++cptr) 844 cachec(c); 845 cachec(NUL); 846 847 if (is_reserved(cache)) used_reserved(cache); 848 849 return (lookup(cache)); 850 } 851 852 853 int 854 get_number(void) 855 { 856 int c; 857 int n; 858 859 n = 0; 860 for (c = *cptr; isdigit(c); c = *++cptr) 861 n = 10*n + (c - '0'); 862 863 return (n); 864 } 865 866 867 char * 868 get_tag(void) 869 { 870 int c; 871 int i; 872 char *s; 873 int t_lineno = lineno; 874 char *t_line = dup_line(); 875 char *t_cptr = t_line + (cptr - line); 876 877 ++cptr; 878 c = nextc(); 879 if (c == EOF) unexpected_EOF(); 880 if (!isalpha(c) && c != '_' && c != '$') 881 illegal_tag(t_lineno, t_line, t_cptr); 882 883 cinc = 0; 884 do { cachec(c); c = *++cptr; } while (IS_IDENT(c)); 885 cachec(NUL); 886 887 c = nextc(); 888 if (c == EOF) unexpected_EOF(); 889 if (c != '>') 890 illegal_tag(t_lineno, t_line, t_cptr); 891 FREE(t_line); 892 ++cptr; 893 894 for (i = 0; i < ntags; ++i) 895 { 896 if (strcmp(cache, tag_table[i]) == 0) 897 return (tag_table[i]); 898 } 899 900 if (ntags >= tagmax) 901 { 902 tagmax += 16; 903 tag_table = (char **) 904 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *)) 905 : MALLOC(tagmax*sizeof(char *))); 906 if (tag_table == 0) no_space(); 907 } 908 909 s = MALLOC(cinc); 910 if (s == 0) no_space(); 911 strlcpy(s, cache, cinc); 912 tag_table[ntags] = s; 913 ++ntags; 914 return (s); 915 } 916 917 918 void 919 declare_tokens(int assoc) 920 { 921 int c; 922 bucket *bp; 923 int value; 924 char *tag = 0; 925 926 if (assoc != TOKEN) ++prec; 927 928 c = nextc(); 929 if (c == EOF) unexpected_EOF(); 930 if (c == '<') 931 { 932 tag = get_tag(); 933 c = nextc(); 934 if (c == EOF) unexpected_EOF(); 935 } 936 937 for (;;) 938 { 939 if (isalpha(c) || c == '_' || c == '.' || c == '$') 940 bp = get_name(); 941 else if (c == '\'' || c == '"') 942 bp = get_literal(); 943 else 944 return; 945 946 if (bp == goal) tokenized_start(bp->name); 947 bp->class = TERM; 948 949 if (tag) 950 { 951 if (bp->tag && tag != bp->tag) 952 retyped_warning(bp->name); 953 bp->tag = tag; 954 } 955 956 if (assoc != TOKEN) 957 { 958 if (bp->prec && prec != bp->prec) 959 reprec_warning(bp->name); 960 bp->assoc = assoc; 961 bp->prec = prec; 962 } 963 964 c = nextc(); 965 if (c == EOF) unexpected_EOF(); 966 value = UNDEFINED; 967 if (isdigit(c)) 968 { 969 value = get_number(); 970 if (bp->value != UNDEFINED && value != bp->value) 971 revalued_warning(bp->name); 972 bp->value = value; 973 c = nextc(); 974 if (c == EOF) unexpected_EOF(); 975 } 976 } 977 } 978 979 980 /* 981 * %expect requires special handling 982 * as it really isn't part of the yacc 983 * grammar only a flag for yacc proper. 984 */ 985 void 986 declare_expect(int assoc) 987 { 988 int c; 989 990 if (assoc != EXPECT) ++prec; 991 992 /* 993 * Stay away from nextc - doesn't 994 * detect EOL and will read to EOF. 995 */ 996 c = *++cptr; 997 if (c == EOF) unexpected_EOF(); 998 999 for(;;) 1000 { 1001 if (isdigit(c)) 1002 { 1003 SRexpect = get_number(); 1004 break; 1005 } 1006 /* 1007 * Looking for number before EOL. 1008 * Spaces, tabs, and numbers are ok, 1009 * words, punc., etc. are syntax errors. 1010 */ 1011 else if (c == '\n' || isalpha(c) || !isspace(c)) 1012 { 1013 syntax_error(lineno, line, cptr); 1014 } 1015 else 1016 { 1017 c = *++cptr; 1018 if (c == EOF) unexpected_EOF(); 1019 } 1020 } 1021 } 1022 1023 1024 void 1025 declare_types(void) 1026 { 1027 int c; 1028 bucket *bp; 1029 char *tag; 1030 1031 c = nextc(); 1032 if (c == EOF) unexpected_EOF(); 1033 if (c != '<') syntax_error(lineno, line, cptr); 1034 tag = get_tag(); 1035 1036 for (;;) 1037 { 1038 c = nextc(); 1039 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1040 bp = get_name(); 1041 else if (c == '\'' || c == '"') 1042 bp = get_literal(); 1043 else 1044 return; 1045 1046 if (bp->tag && tag != bp->tag) 1047 retyped_warning(bp->name); 1048 bp->tag = tag; 1049 } 1050 } 1051 1052 1053 void 1054 declare_start(void) 1055 { 1056 int c; 1057 bucket *bp; 1058 1059 c = nextc(); 1060 if (c == EOF) unexpected_EOF(); 1061 if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1062 syntax_error(lineno, line, cptr); 1063 bp = get_name(); 1064 if (bp->class == TERM) 1065 terminal_start(bp->name); 1066 if (goal && goal != bp) 1067 restarted_warning(); 1068 goal = bp; 1069 } 1070 1071 1072 void 1073 read_declarations(void) 1074 { 1075 int c, k; 1076 1077 cache_size = 256; 1078 cache = MALLOC(cache_size); 1079 if (cache == 0) no_space(); 1080 1081 for (;;) 1082 { 1083 c = nextc(); 1084 if (c == EOF) unexpected_EOF(); 1085 if (c != '%') syntax_error(lineno, line, cptr); 1086 switch (k = keyword()) 1087 { 1088 case MARK: 1089 return; 1090 1091 case IDENT: 1092 copy_ident(); 1093 break; 1094 1095 case TEXT: 1096 copy_text(); 1097 break; 1098 1099 case UNION: 1100 copy_union(); 1101 break; 1102 1103 case TOKEN: 1104 case LEFT: 1105 case RIGHT: 1106 case NONASSOC: 1107 declare_tokens(k); 1108 break; 1109 1110 case EXPECT: 1111 declare_expect(k); 1112 break; 1113 1114 case TYPE: 1115 declare_types(); 1116 break; 1117 1118 case START: 1119 declare_start(); 1120 break; 1121 } 1122 } 1123 } 1124 1125 1126 void 1127 initialize_grammar(void) 1128 { 1129 nitems = 4; 1130 maxitems = 300; 1131 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *)); 1132 if (pitem == 0) no_space(); 1133 pitem[0] = 0; 1134 pitem[1] = 0; 1135 pitem[2] = 0; 1136 pitem[3] = 0; 1137 1138 nrules = 3; 1139 maxrules = 100; 1140 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *)); 1141 if (plhs == 0) no_space(); 1142 plhs[0] = 0; 1143 plhs[1] = 0; 1144 plhs[2] = 0; 1145 rprec = (short *) MALLOC(maxrules*sizeof(short)); 1146 if (rprec == 0) no_space(); 1147 rprec[0] = 0; 1148 rprec[1] = 0; 1149 rprec[2] = 0; 1150 rassoc = (char *) MALLOC(maxrules*sizeof(char)); 1151 if (rassoc == 0) no_space(); 1152 rassoc[0] = TOKEN; 1153 rassoc[1] = TOKEN; 1154 rassoc[2] = TOKEN; 1155 } 1156 1157 1158 void 1159 expand_items(void) 1160 { 1161 maxitems += 300; 1162 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *)); 1163 if (pitem == 0) no_space(); 1164 } 1165 1166 1167 void 1168 expand_rules(void) 1169 { 1170 maxrules += 100; 1171 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *)); 1172 if (plhs == 0) no_space(); 1173 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short)); 1174 if (rprec == 0) no_space(); 1175 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char)); 1176 if (rassoc == 0) no_space(); 1177 } 1178 1179 1180 void 1181 advance_to_start(void) 1182 { 1183 int c; 1184 bucket *bp; 1185 char *s_cptr; 1186 int s_lineno; 1187 1188 for (;;) 1189 { 1190 c = nextc(); 1191 if (c != '%') break; 1192 s_cptr = cptr; 1193 switch (keyword()) 1194 { 1195 case MARK: 1196 no_grammar(); 1197 1198 case TEXT: 1199 copy_text(); 1200 break; 1201 1202 case START: 1203 declare_start(); 1204 break; 1205 1206 default: 1207 syntax_error(lineno, line, s_cptr); 1208 } 1209 } 1210 1211 c = nextc(); 1212 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1213 syntax_error(lineno, line, cptr); 1214 bp = get_name(); 1215 if (goal == 0) 1216 { 1217 if (bp->class == TERM) 1218 terminal_start(bp->name); 1219 goal = bp; 1220 } 1221 1222 s_lineno = lineno; 1223 c = nextc(); 1224 if (c == EOF) unexpected_EOF(); 1225 if (c != ':') syntax_error(lineno, line, cptr); 1226 start_rule(bp, s_lineno); 1227 ++cptr; 1228 } 1229 1230 1231 void 1232 start_rule(bucket *bp, int s_lineno) 1233 { 1234 if (bp->class == TERM) 1235 terminal_lhs(s_lineno); 1236 bp->class = NONTERM; 1237 if (nrules >= maxrules) 1238 expand_rules(); 1239 plhs[nrules] = bp; 1240 rprec[nrules] = UNDEFINED; 1241 rassoc[nrules] = TOKEN; 1242 } 1243 1244 1245 void 1246 end_rule(void) 1247 { 1248 int i; 1249 1250 if (!last_was_action && plhs[nrules]->tag) 1251 { 1252 for (i = nitems - 1; pitem[i]; --i) continue; 1253 if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag) 1254 default_action_warning(); 1255 } 1256 1257 last_was_action = 0; 1258 if (nitems >= maxitems) expand_items(); 1259 pitem[nitems] = 0; 1260 ++nitems; 1261 ++nrules; 1262 } 1263 1264 1265 void 1266 insert_empty_rule(void) 1267 { 1268 bucket *bp, **bpp; 1269 1270 assert(cache); 1271 snprintf(cache, cache_size, "$$%d", ++gensym); 1272 bp = make_bucket(cache); 1273 last_symbol->next = bp; 1274 last_symbol = bp; 1275 bp->tag = plhs[nrules]->tag; 1276 bp->class = NONTERM; 1277 1278 if ((nitems += 2) > maxitems) 1279 expand_items(); 1280 bpp = pitem + nitems - 1; 1281 *bpp-- = bp; 1282 while ((bpp[0] = bpp[-1])) --bpp; 1283 1284 if (++nrules >= maxrules) 1285 expand_rules(); 1286 plhs[nrules] = plhs[nrules-1]; 1287 plhs[nrules-1] = bp; 1288 rprec[nrules] = rprec[nrules-1]; 1289 rprec[nrules-1] = 0; 1290 rassoc[nrules] = rassoc[nrules-1]; 1291 rassoc[nrules-1] = TOKEN; 1292 } 1293 1294 1295 void 1296 add_symbol(void) 1297 { 1298 int c; 1299 bucket *bp; 1300 int s_lineno = lineno; 1301 1302 c = *cptr; 1303 if (c == '\'' || c == '"') 1304 bp = get_literal(); 1305 else 1306 bp = get_name(); 1307 1308 c = nextc(); 1309 if (c == ':') 1310 { 1311 end_rule(); 1312 start_rule(bp, s_lineno); 1313 ++cptr; 1314 return; 1315 } 1316 1317 if (last_was_action) 1318 insert_empty_rule(); 1319 last_was_action = 0; 1320 1321 if (++nitems > maxitems) 1322 expand_items(); 1323 pitem[nitems-1] = bp; 1324 } 1325 1326 1327 void 1328 copy_action(void) 1329 { 1330 int c; 1331 int i, n; 1332 int depth; 1333 int quote; 1334 char *tag; 1335 FILE *f = action_file; 1336 int a_lineno = lineno; 1337 char *a_line = dup_line(); 1338 char *a_cptr = a_line + (cptr - line); 1339 1340 if (last_was_action) 1341 insert_empty_rule(); 1342 last_was_action = 1; 1343 1344 fprintf(f, "case %d:\n", nrules - 2); 1345 if (!lflag) 1346 fprintf(f, line_format, lineno, input_file_name); 1347 if (*cptr == '=') ++cptr; 1348 1349 n = 0; 1350 for (i = nitems - 1; pitem[i]; --i) ++n; 1351 1352 depth = 0; 1353 loop: 1354 c = *cptr; 1355 if (c == '$') 1356 { 1357 if (cptr[1] == '<') 1358 { 1359 int d_lineno = lineno; 1360 char *d_line = dup_line(); 1361 char *d_cptr = d_line + (cptr - line); 1362 1363 ++cptr; 1364 tag = get_tag(); 1365 c = *cptr; 1366 if (c == '$') 1367 { 1368 fprintf(f, "yyval.%s", tag); 1369 ++cptr; 1370 FREE(d_line); 1371 goto loop; 1372 } 1373 else if (isdigit(c)) 1374 { 1375 i = get_number(); 1376 if (i > n) dollar_warning(d_lineno, i); 1377 fprintf(f, "yyvsp[%d].%s", i - n, tag); 1378 FREE(d_line); 1379 goto loop; 1380 } 1381 else if (c == '-' && isdigit(cptr[1])) 1382 { 1383 ++cptr; 1384 i = -get_number() - n; 1385 fprintf(f, "yyvsp[%d].%s", i, tag); 1386 FREE(d_line); 1387 goto loop; 1388 } 1389 else 1390 dollar_error(d_lineno, d_line, d_cptr); 1391 } 1392 else if (cptr[1] == '$') 1393 { 1394 if (ntags) 1395 { 1396 tag = plhs[nrules]->tag; 1397 if (tag == 0) untyped_lhs(); 1398 fprintf(f, "yyval.%s", tag); 1399 } 1400 else 1401 fprintf(f, "yyval"); 1402 cptr += 2; 1403 goto loop; 1404 } 1405 else if (isdigit(cptr[1])) 1406 { 1407 ++cptr; 1408 i = get_number(); 1409 if (ntags) 1410 { 1411 if (i <= 0 || i > n) 1412 unknown_rhs(i); 1413 tag = pitem[nitems + i - n - 1]->tag; 1414 if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1415 fprintf(f, "yyvsp[%d].%s", i - n, tag); 1416 } 1417 else 1418 { 1419 if (i > n) 1420 dollar_warning(lineno, i); 1421 fprintf(f, "yyvsp[%d]", i - n); 1422 } 1423 goto loop; 1424 } 1425 else if (cptr[1] == '-') 1426 { 1427 cptr += 2; 1428 i = get_number(); 1429 if (ntags) 1430 unknown_rhs(-i); 1431 fprintf(f, "yyvsp[%d]", -i - n); 1432 goto loop; 1433 } 1434 } 1435 if (isalpha(c) || c == '_' || c == '$') 1436 { 1437 do 1438 { 1439 putc(c, f); 1440 c = *++cptr; 1441 } while (isalnum(c) || c == '_' || c == '$'); 1442 goto loop; 1443 } 1444 putc(c, f); 1445 ++cptr; 1446 switch (c) 1447 { 1448 case '\n': 1449 next_line: 1450 get_line(); 1451 if (line) goto loop; 1452 unterminated_action(a_lineno, a_line, a_cptr); 1453 1454 case ';': 1455 if (depth > 0) goto loop; 1456 fprintf(f, "\nbreak;\n"); 1457 FREE(a_line); 1458 return; 1459 1460 case '{': 1461 ++depth; 1462 goto loop; 1463 1464 case '}': 1465 if (--depth > 0) goto loop; 1466 fprintf(f, "\nbreak;\n"); 1467 FREE(a_line); 1468 return; 1469 1470 case '\'': 1471 case '"': 1472 { 1473 int s_lineno = lineno; 1474 char *s_line = dup_line(); 1475 char *s_cptr = s_line + (cptr - line - 1); 1476 1477 quote = c; 1478 for (;;) 1479 { 1480 c = *cptr++; 1481 putc(c, f); 1482 if (c == quote) 1483 { 1484 FREE(s_line); 1485 goto loop; 1486 } 1487 if (c == '\n') 1488 unterminated_string(s_lineno, s_line, s_cptr); 1489 if (c == '\\') 1490 { 1491 c = *cptr++; 1492 putc(c, f); 1493 if (c == '\n') 1494 { 1495 get_line(); 1496 if (line == 0) 1497 unterminated_string(s_lineno, s_line, s_cptr); 1498 } 1499 } 1500 } 1501 } 1502 1503 case '/': 1504 c = *cptr; 1505 if (c == '/') 1506 { 1507 putc('*', f); 1508 while ((c = *++cptr) != '\n') 1509 { 1510 if (c == '*' && cptr[1] == '/') 1511 fprintf(f, "* "); 1512 else 1513 putc(c, f); 1514 } 1515 fprintf(f, "*/\n"); 1516 goto next_line; 1517 } 1518 if (c == '*') 1519 { 1520 int c_lineno = lineno; 1521 char *c_line = dup_line(); 1522 char *c_cptr = c_line + (cptr - line - 1); 1523 1524 putc('*', f); 1525 ++cptr; 1526 for (;;) 1527 { 1528 c = *cptr++; 1529 putc(c, f); 1530 if (c == '*' && *cptr == '/') 1531 { 1532 putc('/', f); 1533 ++cptr; 1534 FREE(c_line); 1535 goto loop; 1536 } 1537 if (c == '\n') 1538 { 1539 get_line(); 1540 if (line == 0) 1541 unterminated_comment(c_lineno, c_line, c_cptr); 1542 } 1543 } 1544 } 1545 goto loop; 1546 1547 default: 1548 goto loop; 1549 } 1550 } 1551 1552 1553 int 1554 mark_symbol(void) 1555 { 1556 int c; 1557 bucket *bp = NULL; 1558 1559 c = cptr[1]; 1560 if (c == '%' || c == '\\') 1561 { 1562 cptr += 2; 1563 return (1); 1564 } 1565 1566 if (c == '=') 1567 cptr += 2; 1568 else if ((c == 'p' || c == 'P') && 1569 ((c = cptr[2]) == 'r' || c == 'R') && 1570 ((c = cptr[3]) == 'e' || c == 'E') && 1571 ((c = cptr[4]) == 'c' || c == 'C') && 1572 ((c = cptr[5], !IS_IDENT(c)))) 1573 cptr += 5; 1574 else 1575 syntax_error(lineno, line, cptr); 1576 1577 c = nextc(); 1578 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1579 bp = get_name(); 1580 else if (c == '\'' || c == '"') 1581 bp = get_literal(); 1582 else 1583 { 1584 syntax_error(lineno, line, cptr); 1585 /*NOTREACHED*/ 1586 } 1587 1588 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1589 prec_redeclared(); 1590 1591 rprec[nrules] = bp->prec; 1592 rassoc[nrules] = bp->assoc; 1593 return (0); 1594 } 1595 1596 1597 void 1598 read_grammar(void) 1599 { 1600 int c; 1601 1602 initialize_grammar(); 1603 advance_to_start(); 1604 1605 for (;;) 1606 { 1607 c = nextc(); 1608 if (c == EOF) break; 1609 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || 1610 c == '"') 1611 add_symbol(); 1612 else if (c == '{' || c == '=') 1613 copy_action(); 1614 else if (c == '|') 1615 { 1616 end_rule(); 1617 start_rule(plhs[nrules-1], 0); 1618 ++cptr; 1619 } 1620 else if (c == '%') 1621 { 1622 if (mark_symbol()) break; 1623 } 1624 else 1625 syntax_error(lineno, line, cptr); 1626 } 1627 end_rule(); 1628 } 1629 1630 1631 void 1632 free_tags(void) 1633 { 1634 int i; 1635 1636 if (tag_table == 0) return; 1637 1638 for (i = 0; i < ntags; ++i) 1639 { 1640 assert(tag_table[i]); 1641 FREE(tag_table[i]); 1642 } 1643 FREE(tag_table); 1644 } 1645 1646 1647 void 1648 pack_names(void) 1649 { 1650 bucket *bp; 1651 char *p, *s, *t; 1652 1653 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1654 for (bp = first_symbol; bp; bp = bp->next) 1655 name_pool_size += strlen(bp->name) + 1; 1656 name_pool = MALLOC(name_pool_size); 1657 if (name_pool == 0) no_space(); 1658 1659 strlcpy(name_pool, "$accept", name_pool_size); 1660 strlcpy(name_pool+8, "$end", name_pool_size - 8); 1661 t = name_pool + 13; 1662 for (bp = first_symbol; bp; bp = bp->next) 1663 { 1664 p = t; 1665 s = bp->name; 1666 while ((*t++ = *s++)) continue; 1667 FREE(bp->name); 1668 bp->name = p; 1669 } 1670 } 1671 1672 1673 void 1674 check_symbols(void) 1675 { 1676 bucket *bp; 1677 1678 if (goal->class == UNKNOWN) 1679 undefined_goal(goal->name); 1680 1681 for (bp = first_symbol; bp; bp = bp->next) 1682 { 1683 if (bp->class == UNKNOWN) 1684 { 1685 undefined_symbol_warning(bp->name); 1686 bp->class = TERM; 1687 } 1688 } 1689 } 1690 1691 1692 void 1693 pack_symbols(void) 1694 { 1695 bucket *bp; 1696 bucket **v; 1697 int i, j, k, n; 1698 1699 nsyms = 2; 1700 ntokens = 1; 1701 for (bp = first_symbol; bp; bp = bp->next) 1702 { 1703 ++nsyms; 1704 if (bp->class == TERM) ++ntokens; 1705 } 1706 start_symbol = ntokens; 1707 nvars = nsyms - ntokens; 1708 1709 symbol_name = (char **) MALLOC(nsyms*sizeof(char *)); 1710 if (symbol_name == 0) no_space(); 1711 symbol_value = (short *) MALLOC(nsyms*sizeof(short)); 1712 if (symbol_value == 0) no_space(); 1713 symbol_prec = (short *) MALLOC(nsyms*sizeof(short)); 1714 if (symbol_prec == 0) no_space(); 1715 symbol_assoc = MALLOC(nsyms); 1716 if (symbol_assoc == 0) no_space(); 1717 1718 v = (bucket **) MALLOC(nsyms*sizeof(bucket *)); 1719 if (v == 0) no_space(); 1720 1721 v[0] = 0; 1722 v[start_symbol] = 0; 1723 1724 i = 1; 1725 j = start_symbol + 1; 1726 for (bp = first_symbol; bp; bp = bp->next) 1727 { 1728 if (bp->class == TERM) 1729 v[i++] = bp; 1730 else 1731 v[j++] = bp; 1732 } 1733 assert(i == ntokens && j == nsyms); 1734 1735 for (i = 1; i < ntokens; ++i) 1736 v[i]->index = i; 1737 1738 goal->index = start_symbol + 1; 1739 k = start_symbol + 2; 1740 while (++i < nsyms) 1741 if (v[i] != goal) 1742 { 1743 v[i]->index = k; 1744 ++k; 1745 } 1746 1747 goal->value = 0; 1748 k = 1; 1749 for (i = start_symbol + 1; i < nsyms; ++i) 1750 { 1751 if (v[i] != goal) 1752 { 1753 v[i]->value = k; 1754 ++k; 1755 } 1756 } 1757 1758 k = 0; 1759 for (i = 1; i < ntokens; ++i) 1760 { 1761 n = v[i]->value; 1762 if (n > 256) 1763 { 1764 for (j = k++; j > 0 && symbol_value[j-1] > n; --j) 1765 symbol_value[j] = symbol_value[j-1]; 1766 symbol_value[j] = n; 1767 } 1768 } 1769 1770 if (v[1]->value == UNDEFINED) 1771 v[1]->value = 256; 1772 1773 j = 0; 1774 n = 257; 1775 for (i = 2; i < ntokens; ++i) 1776 { 1777 if (v[i]->value == UNDEFINED) 1778 { 1779 while (j < k && n == symbol_value[j]) 1780 { 1781 while (++j < k && n == symbol_value[j]) continue; 1782 ++n; 1783 } 1784 v[i]->value = n; 1785 ++n; 1786 } 1787 } 1788 1789 symbol_name[0] = name_pool + 8; 1790 symbol_value[0] = 0; 1791 symbol_prec[0] = 0; 1792 symbol_assoc[0] = TOKEN; 1793 for (i = 1; i < ntokens; ++i) 1794 { 1795 symbol_name[i] = v[i]->name; 1796 symbol_value[i] = v[i]->value; 1797 symbol_prec[i] = v[i]->prec; 1798 symbol_assoc[i] = v[i]->assoc; 1799 } 1800 symbol_name[start_symbol] = name_pool; 1801 symbol_value[start_symbol] = -1; 1802 symbol_prec[start_symbol] = 0; 1803 symbol_assoc[start_symbol] = TOKEN; 1804 for (++i; i < nsyms; ++i) 1805 { 1806 k = v[i]->index; 1807 symbol_name[k] = v[i]->name; 1808 symbol_value[k] = v[i]->value; 1809 symbol_prec[k] = v[i]->prec; 1810 symbol_assoc[k] = v[i]->assoc; 1811 } 1812 1813 FREE(v); 1814 } 1815 1816 1817 void 1818 pack_grammar(void) 1819 { 1820 int i, j; 1821 int assoc, prec; 1822 1823 ritem = (short *) MALLOC(nitems*sizeof(short)); 1824 if (ritem == 0) no_space(); 1825 rlhs = (short *) MALLOC(nrules*sizeof(short)); 1826 if (rlhs == 0) no_space(); 1827 rrhs = (short *) MALLOC((nrules+1)*sizeof(short)); 1828 if (rrhs == 0) no_space(); 1829 rprec = (short *) REALLOC(rprec, nrules*sizeof(short)); 1830 if (rprec == 0) no_space(); 1831 rassoc = REALLOC(rassoc, nrules); 1832 if (rassoc == 0) no_space(); 1833 1834 ritem[0] = -1; 1835 ritem[1] = goal->index; 1836 ritem[2] = 0; 1837 ritem[3] = -2; 1838 rlhs[0] = 0; 1839 rlhs[1] = 0; 1840 rlhs[2] = start_symbol; 1841 rrhs[0] = 0; 1842 rrhs[1] = 0; 1843 rrhs[2] = 1; 1844 1845 j = 4; 1846 for (i = 3; i < nrules; ++i) 1847 { 1848 rlhs[i] = plhs[i]->index; 1849 rrhs[i] = j; 1850 assoc = TOKEN; 1851 prec = 0; 1852 while (pitem[j]) 1853 { 1854 ritem[j] = pitem[j]->index; 1855 if (pitem[j]->class == TERM) 1856 { 1857 prec = pitem[j]->prec; 1858 assoc = pitem[j]->assoc; 1859 } 1860 ++j; 1861 } 1862 ritem[j] = -i; 1863 ++j; 1864 if (rprec[i] == UNDEFINED) 1865 { 1866 rprec[i] = prec; 1867 rassoc[i] = assoc; 1868 } 1869 } 1870 rrhs[i] = j; 1871 1872 FREE(plhs); 1873 FREE(pitem); 1874 } 1875 1876 1877 void 1878 print_grammar(void) 1879 { 1880 int i, j, k; 1881 int spacing = 0; 1882 FILE *f = verbose_file; 1883 1884 if (!vflag) return; 1885 1886 k = 1; 1887 for (i = 2; i < nrules; ++i) 1888 { 1889 if (rlhs[i] != rlhs[i-1]) 1890 { 1891 if (i != 2) fprintf(f, "\n"); 1892 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 1893 spacing = strlen(symbol_name[rlhs[i]]) + 1; 1894 } 1895 else 1896 { 1897 fprintf(f, "%4d ", i - 2); 1898 j = spacing; 1899 while (--j >= 0) putc(' ', f); 1900 putc('|', f); 1901 } 1902 1903 while (ritem[k] >= 0) 1904 { 1905 fprintf(f, " %s", symbol_name[ritem[k]]); 1906 ++k; 1907 } 1908 ++k; 1909 putc('\n', f); 1910 } 1911 } 1912 1913 1914 void 1915 reader(void) 1916 { 1917 write_section(banner); 1918 create_symbol_table(); 1919 read_declarations(); 1920 read_grammar(); 1921 free_symbol_table(); 1922 free_tags(); 1923 pack_names(); 1924 check_symbols(); 1925 pack_symbols(); 1926 pack_grammar(); 1927 free_symbols(); 1928 print_grammar(); 1929 } 1930