1 /* $OpenBSD: reader.c,v 1.15 2003/06/19 16:34:53 pvalchev 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, "typedef union"); 535 if (dflag) fprintf(union_file, "typedef union"); 536 537 depth = 0; 538 loop: 539 c = *cptr++; 540 putc(c, text_file); 541 if (dflag) putc(c, union_file); 542 switch (c) 543 { 544 case '\n': 545 next_line: 546 get_line(); 547 if (line == 0) unterminated_union(u_lineno, u_line, u_cptr); 548 goto loop; 549 550 case '{': 551 ++depth; 552 goto loop; 553 554 case '}': 555 if (--depth == 0) 556 { 557 fprintf(text_file, " YYSTYPE;\n"); 558 FREE(u_line); 559 return; 560 } 561 goto loop; 562 563 case '\'': 564 case '"': 565 { 566 int s_lineno = lineno; 567 char *s_line = dup_line(); 568 char *s_cptr = s_line + (cptr - line - 1); 569 570 quote = c; 571 for (;;) 572 { 573 c = *cptr++; 574 putc(c, text_file); 575 if (dflag) putc(c, union_file); 576 if (c == quote) 577 { 578 FREE(s_line); 579 goto loop; 580 } 581 if (c == '\n') 582 unterminated_string(s_lineno, s_line, s_cptr); 583 if (c == '\\') 584 { 585 c = *cptr++; 586 putc(c, text_file); 587 if (dflag) putc(c, union_file); 588 if (c == '\n') 589 { 590 get_line(); 591 if (line == 0) 592 unterminated_string(s_lineno, s_line, s_cptr); 593 } 594 } 595 } 596 } 597 598 case '/': 599 c = *cptr; 600 if (c == '/') 601 { 602 putc('*', text_file); 603 if (dflag) putc('*', union_file); 604 while ((c = *++cptr) != '\n') 605 { 606 if (c == '*' && cptr[1] == '/') 607 { 608 fprintf(text_file, "* "); 609 if (dflag) fprintf(union_file, "* "); 610 } 611 else 612 { 613 putc(c, text_file); 614 if (dflag) putc(c, union_file); 615 } 616 } 617 fprintf(text_file, "*/\n"); 618 if (dflag) fprintf(union_file, "*/\n"); 619 goto next_line; 620 } 621 if (c == '*') 622 { 623 int c_lineno = lineno; 624 char *c_line = dup_line(); 625 char *c_cptr = c_line + (cptr - line - 1); 626 627 putc('*', text_file); 628 if (dflag) putc('*', union_file); 629 ++cptr; 630 for (;;) 631 { 632 c = *cptr++; 633 putc(c, text_file); 634 if (dflag) putc(c, union_file); 635 if (c == '*' && *cptr == '/') 636 { 637 putc('/', text_file); 638 if (dflag) putc('/', union_file); 639 ++cptr; 640 FREE(c_line); 641 goto loop; 642 } 643 if (c == '\n') 644 { 645 get_line(); 646 if (line == 0) 647 unterminated_comment(c_lineno, c_line, c_cptr); 648 } 649 } 650 } 651 goto loop; 652 653 default: 654 goto loop; 655 } 656 } 657 658 659 int 660 hexval(int c) 661 { 662 if (c >= '0' && c <= '9') 663 return (c - '0'); 664 if (c >= 'A' && c <= 'F') 665 return (c - 'A' + 10); 666 if (c >= 'a' && c <= 'f') 667 return (c - 'a' + 10); 668 return (-1); 669 } 670 671 672 bucket * 673 get_literal(void) 674 { 675 int c, quote; 676 int i; 677 int n; 678 char *s; 679 bucket *bp; 680 int s_lineno = lineno; 681 char *s_line = dup_line(); 682 char *s_cptr = s_line + (cptr - line); 683 684 quote = *cptr++; 685 cinc = 0; 686 for (;;) 687 { 688 c = *cptr++; 689 if (c == quote) break; 690 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); 691 if (c == '\\') 692 { 693 char *c_cptr = cptr - 1; 694 695 c = *cptr++; 696 switch (c) 697 { 698 case '\n': 699 get_line(); 700 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr); 701 continue; 702 703 case '0': case '1': case '2': case '3': 704 case '4': case '5': case '6': case '7': 705 n = c - '0'; 706 c = *cptr; 707 if (IS_OCTAL(c)) 708 { 709 n = (n << 3) + (c - '0'); 710 c = *++cptr; 711 if (IS_OCTAL(c)) 712 { 713 n = (n << 3) + (c - '0'); 714 ++cptr; 715 } 716 } 717 if (n > MAXCHAR) illegal_character(c_cptr); 718 c = n; 719 break; 720 721 case 'x': 722 c = *cptr++; 723 n = hexval(c); 724 if (n < 0 || n >= 16) 725 illegal_character(c_cptr); 726 for (;;) 727 { 728 c = *cptr; 729 i = hexval(c); 730 if (i < 0 || i >= 16) break; 731 ++cptr; 732 n = (n << 4) + i; 733 if (n > MAXCHAR) illegal_character(c_cptr); 734 } 735 c = n; 736 break; 737 738 case 'a': c = 7; break; 739 case 'b': c = '\b'; break; 740 case 'f': c = '\f'; break; 741 case 'n': c = '\n'; break; 742 case 'r': c = '\r'; break; 743 case 't': c = '\t'; break; 744 case 'v': c = '\v'; break; 745 } 746 } 747 cachec(c); 748 } 749 FREE(s_line); 750 751 n = cinc; 752 s = MALLOC(n); 753 if (s == 0) no_space(); 754 755 for (i = 0; i < n; ++i) 756 s[i] = cache[i]; 757 758 cinc = 0; 759 if (n == 1) 760 cachec('\''); 761 else 762 cachec('"'); 763 764 for (i = 0; i < n; ++i) 765 { 766 c = ((unsigned char *)s)[i]; 767 if (c == '\\' || c == cache[0]) 768 { 769 cachec('\\'); 770 cachec(c); 771 } 772 else if (isprint(c)) 773 cachec(c); 774 else 775 { 776 cachec('\\'); 777 switch (c) 778 { 779 case 7: cachec('a'); break; 780 case '\b': cachec('b'); break; 781 case '\f': cachec('f'); break; 782 case '\n': cachec('n'); break; 783 case '\r': cachec('r'); break; 784 case '\t': cachec('t'); break; 785 case '\v': cachec('v'); break; 786 default: 787 cachec(((c >> 6) & 7) + '0'); 788 cachec(((c >> 3) & 7) + '0'); 789 cachec((c & 7) + '0'); 790 break; 791 } 792 } 793 } 794 795 if (n == 1) 796 cachec('\''); 797 else 798 cachec('"'); 799 800 cachec(NUL); 801 bp = lookup(cache); 802 bp->class = TERM; 803 if (n == 1 && bp->value == UNDEFINED) 804 bp->value = *(unsigned char *)s; 805 FREE(s); 806 807 return (bp); 808 } 809 810 811 int 812 is_reserved(char *name) 813 { 814 char *s; 815 816 if (strcmp(name, ".") == 0 || 817 strcmp(name, "$accept") == 0 || 818 strcmp(name, "$end") == 0) 819 return (1); 820 821 if (name[0] == '$' && name[1] == '$' && isdigit(name[2])) 822 { 823 s = name + 3; 824 while (isdigit(*s)) ++s; 825 if (*s == NUL) return (1); 826 } 827 828 return (0); 829 } 830 831 832 bucket * 833 get_name(void) 834 { 835 int c; 836 837 cinc = 0; 838 for (c = *cptr; IS_IDENT(c); c = *++cptr) 839 cachec(c); 840 cachec(NUL); 841 842 if (is_reserved(cache)) used_reserved(cache); 843 844 return (lookup(cache)); 845 } 846 847 848 int 849 get_number(void) 850 { 851 int c; 852 int n; 853 854 n = 0; 855 for (c = *cptr; isdigit(c); c = *++cptr) 856 n = 10*n + (c - '0'); 857 858 return (n); 859 } 860 861 862 char * 863 get_tag(void) 864 { 865 int c; 866 int i; 867 char *s; 868 int t_lineno = lineno; 869 char *t_line = dup_line(); 870 char *t_cptr = t_line + (cptr - line); 871 872 ++cptr; 873 c = nextc(); 874 if (c == EOF) unexpected_EOF(); 875 if (!isalpha(c) && c != '_' && c != '$') 876 illegal_tag(t_lineno, t_line, t_cptr); 877 878 cinc = 0; 879 do { cachec(c); c = *++cptr; } while (IS_IDENT(c)); 880 cachec(NUL); 881 882 c = nextc(); 883 if (c == EOF) unexpected_EOF(); 884 if (c != '>') 885 illegal_tag(t_lineno, t_line, t_cptr); 886 FREE(t_line); 887 ++cptr; 888 889 for (i = 0; i < ntags; ++i) 890 { 891 if (strcmp(cache, tag_table[i]) == 0) 892 return (tag_table[i]); 893 } 894 895 if (ntags >= tagmax) 896 { 897 tagmax += 16; 898 tag_table = (char **) 899 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *)) 900 : MALLOC(tagmax*sizeof(char *))); 901 if (tag_table == 0) no_space(); 902 } 903 904 s = MALLOC(cinc); 905 if (s == 0) no_space(); 906 strlcpy(s, cache, cinc); 907 tag_table[ntags] = s; 908 ++ntags; 909 return (s); 910 } 911 912 913 void 914 declare_tokens(int assoc) 915 { 916 int c; 917 bucket *bp; 918 int value; 919 char *tag = 0; 920 921 if (assoc != TOKEN) ++prec; 922 923 c = nextc(); 924 if (c == EOF) unexpected_EOF(); 925 if (c == '<') 926 { 927 tag = get_tag(); 928 c = nextc(); 929 if (c == EOF) unexpected_EOF(); 930 } 931 932 for (;;) 933 { 934 if (isalpha(c) || c == '_' || c == '.' || c == '$') 935 bp = get_name(); 936 else if (c == '\'' || c == '"') 937 bp = get_literal(); 938 else 939 return; 940 941 if (bp == goal) tokenized_start(bp->name); 942 bp->class = TERM; 943 944 if (tag) 945 { 946 if (bp->tag && tag != bp->tag) 947 retyped_warning(bp->name); 948 bp->tag = tag; 949 } 950 951 if (assoc != TOKEN) 952 { 953 if (bp->prec && prec != bp->prec) 954 reprec_warning(bp->name); 955 bp->assoc = assoc; 956 bp->prec = prec; 957 } 958 959 c = nextc(); 960 if (c == EOF) unexpected_EOF(); 961 value = UNDEFINED; 962 if (isdigit(c)) 963 { 964 value = get_number(); 965 if (bp->value != UNDEFINED && value != bp->value) 966 revalued_warning(bp->name); 967 bp->value = value; 968 c = nextc(); 969 if (c == EOF) unexpected_EOF(); 970 } 971 } 972 } 973 974 975 /* 976 * %expect requires special handling 977 * as it really isn't part of the yacc 978 * grammar only a flag for yacc proper. 979 */ 980 void 981 declare_expect(int assoc) 982 { 983 int c; 984 985 if (assoc != EXPECT) ++prec; 986 987 /* 988 * Stay away from nextc - doesn't 989 * detect EOL and will read to EOF. 990 */ 991 c = *++cptr; 992 if (c == EOF) unexpected_EOF(); 993 994 for(;;) 995 { 996 if (isdigit(c)) 997 { 998 SRexpect = get_number(); 999 break; 1000 } 1001 /* 1002 * Looking for number before EOL. 1003 * Spaces, tabs, and numbers are ok, 1004 * words, punc., etc. are syntax errors. 1005 */ 1006 else if (c == '\n' || isalpha(c) || !isspace(c)) 1007 { 1008 syntax_error(lineno, line, cptr); 1009 } 1010 else 1011 { 1012 c = *++cptr; 1013 if (c == EOF) unexpected_EOF(); 1014 } 1015 } 1016 } 1017 1018 1019 void 1020 declare_types(void) 1021 { 1022 int c; 1023 bucket *bp; 1024 char *tag; 1025 1026 c = nextc(); 1027 if (c == EOF) unexpected_EOF(); 1028 if (c != '<') syntax_error(lineno, line, cptr); 1029 tag = get_tag(); 1030 1031 for (;;) 1032 { 1033 c = nextc(); 1034 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1035 bp = get_name(); 1036 else if (c == '\'' || c == '"') 1037 bp = get_literal(); 1038 else 1039 return; 1040 1041 if (bp->tag && tag != bp->tag) 1042 retyped_warning(bp->name); 1043 bp->tag = tag; 1044 } 1045 } 1046 1047 1048 void 1049 declare_start(void) 1050 { 1051 int c; 1052 bucket *bp; 1053 1054 c = nextc(); 1055 if (c == EOF) unexpected_EOF(); 1056 if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1057 syntax_error(lineno, line, cptr); 1058 bp = get_name(); 1059 if (bp->class == TERM) 1060 terminal_start(bp->name); 1061 if (goal && goal != bp) 1062 restarted_warning(); 1063 goal = bp; 1064 } 1065 1066 1067 void 1068 read_declarations(void) 1069 { 1070 int c, k; 1071 1072 cache_size = 256; 1073 cache = MALLOC(cache_size); 1074 if (cache == 0) no_space(); 1075 1076 for (;;) 1077 { 1078 c = nextc(); 1079 if (c == EOF) unexpected_EOF(); 1080 if (c != '%') syntax_error(lineno, line, cptr); 1081 switch (k = keyword()) 1082 { 1083 case MARK: 1084 return; 1085 1086 case IDENT: 1087 copy_ident(); 1088 break; 1089 1090 case TEXT: 1091 copy_text(); 1092 break; 1093 1094 case UNION: 1095 copy_union(); 1096 break; 1097 1098 case TOKEN: 1099 case LEFT: 1100 case RIGHT: 1101 case NONASSOC: 1102 declare_tokens(k); 1103 break; 1104 1105 case EXPECT: 1106 declare_expect(k); 1107 break; 1108 1109 case TYPE: 1110 declare_types(); 1111 break; 1112 1113 case START: 1114 declare_start(); 1115 break; 1116 } 1117 } 1118 } 1119 1120 1121 void 1122 initialize_grammar(void) 1123 { 1124 nitems = 4; 1125 maxitems = 300; 1126 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *)); 1127 if (pitem == 0) no_space(); 1128 pitem[0] = 0; 1129 pitem[1] = 0; 1130 pitem[2] = 0; 1131 pitem[3] = 0; 1132 1133 nrules = 3; 1134 maxrules = 100; 1135 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *)); 1136 if (plhs == 0) no_space(); 1137 plhs[0] = 0; 1138 plhs[1] = 0; 1139 plhs[2] = 0; 1140 rprec = (short *) MALLOC(maxrules*sizeof(short)); 1141 if (rprec == 0) no_space(); 1142 rprec[0] = 0; 1143 rprec[1] = 0; 1144 rprec[2] = 0; 1145 rassoc = (char *) MALLOC(maxrules*sizeof(char)); 1146 if (rassoc == 0) no_space(); 1147 rassoc[0] = TOKEN; 1148 rassoc[1] = TOKEN; 1149 rassoc[2] = TOKEN; 1150 } 1151 1152 1153 void 1154 expand_items(void) 1155 { 1156 maxitems += 300; 1157 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *)); 1158 if (pitem == 0) no_space(); 1159 } 1160 1161 1162 void 1163 expand_rules(void) 1164 { 1165 maxrules += 100; 1166 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *)); 1167 if (plhs == 0) no_space(); 1168 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short)); 1169 if (rprec == 0) no_space(); 1170 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char)); 1171 if (rassoc == 0) no_space(); 1172 } 1173 1174 1175 void 1176 advance_to_start(void) 1177 { 1178 int c; 1179 bucket *bp; 1180 char *s_cptr; 1181 int s_lineno; 1182 1183 for (;;) 1184 { 1185 c = nextc(); 1186 if (c != '%') break; 1187 s_cptr = cptr; 1188 switch (keyword()) 1189 { 1190 case MARK: 1191 no_grammar(); 1192 1193 case TEXT: 1194 copy_text(); 1195 break; 1196 1197 case START: 1198 declare_start(); 1199 break; 1200 1201 default: 1202 syntax_error(lineno, line, s_cptr); 1203 } 1204 } 1205 1206 c = nextc(); 1207 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1208 syntax_error(lineno, line, cptr); 1209 bp = get_name(); 1210 if (goal == 0) 1211 { 1212 if (bp->class == TERM) 1213 terminal_start(bp->name); 1214 goal = bp; 1215 } 1216 1217 s_lineno = lineno; 1218 c = nextc(); 1219 if (c == EOF) unexpected_EOF(); 1220 if (c != ':') syntax_error(lineno, line, cptr); 1221 start_rule(bp, s_lineno); 1222 ++cptr; 1223 } 1224 1225 1226 void 1227 start_rule(bucket *bp, int s_lineno) 1228 { 1229 if (bp->class == TERM) 1230 terminal_lhs(s_lineno); 1231 bp->class = NONTERM; 1232 if (nrules >= maxrules) 1233 expand_rules(); 1234 plhs[nrules] = bp; 1235 rprec[nrules] = UNDEFINED; 1236 rassoc[nrules] = TOKEN; 1237 } 1238 1239 1240 void 1241 end_rule(void) 1242 { 1243 int i; 1244 1245 if (!last_was_action && plhs[nrules]->tag) 1246 { 1247 for (i = nitems - 1; pitem[i]; --i) continue; 1248 if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag) 1249 default_action_warning(); 1250 } 1251 1252 last_was_action = 0; 1253 if (nitems >= maxitems) expand_items(); 1254 pitem[nitems] = 0; 1255 ++nitems; 1256 ++nrules; 1257 } 1258 1259 1260 void 1261 insert_empty_rule(void) 1262 { 1263 bucket *bp, **bpp; 1264 1265 assert(cache); 1266 snprintf(cache, cache_size, "$$%d", ++gensym); 1267 bp = make_bucket(cache); 1268 last_symbol->next = bp; 1269 last_symbol = bp; 1270 bp->tag = plhs[nrules]->tag; 1271 bp->class = NONTERM; 1272 1273 if ((nitems += 2) > maxitems) 1274 expand_items(); 1275 bpp = pitem + nitems - 1; 1276 *bpp-- = bp; 1277 while ((bpp[0] = bpp[-1])) --bpp; 1278 1279 if (++nrules >= maxrules) 1280 expand_rules(); 1281 plhs[nrules] = plhs[nrules-1]; 1282 plhs[nrules-1] = bp; 1283 rprec[nrules] = rprec[nrules-1]; 1284 rprec[nrules-1] = 0; 1285 rassoc[nrules] = rassoc[nrules-1]; 1286 rassoc[nrules-1] = TOKEN; 1287 } 1288 1289 1290 void 1291 add_symbol(void) 1292 { 1293 int c; 1294 bucket *bp; 1295 int s_lineno = lineno; 1296 1297 c = *cptr; 1298 if (c == '\'' || c == '"') 1299 bp = get_literal(); 1300 else 1301 bp = get_name(); 1302 1303 c = nextc(); 1304 if (c == ':') 1305 { 1306 end_rule(); 1307 start_rule(bp, s_lineno); 1308 ++cptr; 1309 return; 1310 } 1311 1312 if (last_was_action) 1313 insert_empty_rule(); 1314 last_was_action = 0; 1315 1316 if (++nitems > maxitems) 1317 expand_items(); 1318 pitem[nitems-1] = bp; 1319 } 1320 1321 1322 void 1323 copy_action(void) 1324 { 1325 int c; 1326 int i, n; 1327 int depth; 1328 int quote; 1329 char *tag; 1330 FILE *f = action_file; 1331 int a_lineno = lineno; 1332 char *a_line = dup_line(); 1333 char *a_cptr = a_line + (cptr - line); 1334 1335 if (last_was_action) 1336 insert_empty_rule(); 1337 last_was_action = 1; 1338 1339 fprintf(f, "case %d:\n", nrules - 2); 1340 if (!lflag) 1341 fprintf(f, line_format, lineno, input_file_name); 1342 if (*cptr == '=') ++cptr; 1343 1344 n = 0; 1345 for (i = nitems - 1; pitem[i]; --i) ++n; 1346 1347 depth = 0; 1348 loop: 1349 c = *cptr; 1350 if (c == '$') 1351 { 1352 if (cptr[1] == '<') 1353 { 1354 int d_lineno = lineno; 1355 char *d_line = dup_line(); 1356 char *d_cptr = d_line + (cptr - line); 1357 1358 ++cptr; 1359 tag = get_tag(); 1360 c = *cptr; 1361 if (c == '$') 1362 { 1363 fprintf(f, "yyval.%s", tag); 1364 ++cptr; 1365 FREE(d_line); 1366 goto loop; 1367 } 1368 else if (isdigit(c)) 1369 { 1370 i = get_number(); 1371 if (i > n) dollar_warning(d_lineno, i); 1372 fprintf(f, "yyvsp[%d].%s", i - n, tag); 1373 FREE(d_line); 1374 goto loop; 1375 } 1376 else if (c == '-' && isdigit(cptr[1])) 1377 { 1378 ++cptr; 1379 i = -get_number() - n; 1380 fprintf(f, "yyvsp[%d].%s", i, tag); 1381 FREE(d_line); 1382 goto loop; 1383 } 1384 else 1385 dollar_error(d_lineno, d_line, d_cptr); 1386 } 1387 else if (cptr[1] == '$') 1388 { 1389 if (ntags) 1390 { 1391 tag = plhs[nrules]->tag; 1392 if (tag == 0) untyped_lhs(); 1393 fprintf(f, "yyval.%s", tag); 1394 } 1395 else 1396 fprintf(f, "yyval"); 1397 cptr += 2; 1398 goto loop; 1399 } 1400 else if (isdigit(cptr[1])) 1401 { 1402 ++cptr; 1403 i = get_number(); 1404 if (ntags) 1405 { 1406 if (i <= 0 || i > n) 1407 unknown_rhs(i); 1408 tag = pitem[nitems + i - n - 1]->tag; 1409 if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1410 fprintf(f, "yyvsp[%d].%s", i - n, tag); 1411 } 1412 else 1413 { 1414 if (i > n) 1415 dollar_warning(lineno, i); 1416 fprintf(f, "yyvsp[%d]", i - n); 1417 } 1418 goto loop; 1419 } 1420 else if (cptr[1] == '-') 1421 { 1422 cptr += 2; 1423 i = get_number(); 1424 if (ntags) 1425 unknown_rhs(-i); 1426 fprintf(f, "yyvsp[%d]", -i - n); 1427 goto loop; 1428 } 1429 } 1430 if (isalpha(c) || c == '_' || c == '$') 1431 { 1432 do 1433 { 1434 putc(c, f); 1435 c = *++cptr; 1436 } while (isalnum(c) || c == '_' || c == '$'); 1437 goto loop; 1438 } 1439 putc(c, f); 1440 ++cptr; 1441 switch (c) 1442 { 1443 case '\n': 1444 next_line: 1445 get_line(); 1446 if (line) goto loop; 1447 unterminated_action(a_lineno, a_line, a_cptr); 1448 1449 case ';': 1450 if (depth > 0) goto loop; 1451 fprintf(f, "\nbreak;\n"); 1452 FREE(a_line); 1453 return; 1454 1455 case '{': 1456 ++depth; 1457 goto loop; 1458 1459 case '}': 1460 if (--depth > 0) goto loop; 1461 fprintf(f, "\nbreak;\n"); 1462 FREE(a_line); 1463 return; 1464 1465 case '\'': 1466 case '"': 1467 { 1468 int s_lineno = lineno; 1469 char *s_line = dup_line(); 1470 char *s_cptr = s_line + (cptr - line - 1); 1471 1472 quote = c; 1473 for (;;) 1474 { 1475 c = *cptr++; 1476 putc(c, f); 1477 if (c == quote) 1478 { 1479 FREE(s_line); 1480 goto loop; 1481 } 1482 if (c == '\n') 1483 unterminated_string(s_lineno, s_line, s_cptr); 1484 if (c == '\\') 1485 { 1486 c = *cptr++; 1487 putc(c, f); 1488 if (c == '\n') 1489 { 1490 get_line(); 1491 if (line == 0) 1492 unterminated_string(s_lineno, s_line, s_cptr); 1493 } 1494 } 1495 } 1496 } 1497 1498 case '/': 1499 c = *cptr; 1500 if (c == '/') 1501 { 1502 putc('*', f); 1503 while ((c = *++cptr) != '\n') 1504 { 1505 if (c == '*' && cptr[1] == '/') 1506 fprintf(f, "* "); 1507 else 1508 putc(c, f); 1509 } 1510 fprintf(f, "*/\n"); 1511 goto next_line; 1512 } 1513 if (c == '*') 1514 { 1515 int c_lineno = lineno; 1516 char *c_line = dup_line(); 1517 char *c_cptr = c_line + (cptr - line - 1); 1518 1519 putc('*', f); 1520 ++cptr; 1521 for (;;) 1522 { 1523 c = *cptr++; 1524 putc(c, f); 1525 if (c == '*' && *cptr == '/') 1526 { 1527 putc('/', f); 1528 ++cptr; 1529 FREE(c_line); 1530 goto loop; 1531 } 1532 if (c == '\n') 1533 { 1534 get_line(); 1535 if (line == 0) 1536 unterminated_comment(c_lineno, c_line, c_cptr); 1537 } 1538 } 1539 } 1540 goto loop; 1541 1542 default: 1543 goto loop; 1544 } 1545 } 1546 1547 1548 int 1549 mark_symbol(void) 1550 { 1551 int c; 1552 bucket *bp; 1553 1554 c = cptr[1]; 1555 if (c == '%' || c == '\\') 1556 { 1557 cptr += 2; 1558 return (1); 1559 } 1560 1561 if (c == '=') 1562 cptr += 2; 1563 else if ((c == 'p' || c == 'P') && 1564 ((c = cptr[2]) == 'r' || c == 'R') && 1565 ((c = cptr[3]) == 'e' || c == 'E') && 1566 ((c = cptr[4]) == 'c' || c == 'C') && 1567 ((c = cptr[5], !IS_IDENT(c)))) 1568 cptr += 5; 1569 else 1570 syntax_error(lineno, line, cptr); 1571 1572 c = nextc(); 1573 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1574 bp = get_name(); 1575 else if (c == '\'' || c == '"') 1576 bp = get_literal(); 1577 else 1578 { 1579 syntax_error(lineno, line, cptr); 1580 /*NOTREACHED*/ 1581 } 1582 1583 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1584 prec_redeclared(); 1585 1586 rprec[nrules] = bp->prec; 1587 rassoc[nrules] = bp->assoc; 1588 return (0); 1589 } 1590 1591 1592 void 1593 read_grammar(void) 1594 { 1595 int c; 1596 1597 initialize_grammar(); 1598 advance_to_start(); 1599 1600 for (;;) 1601 { 1602 c = nextc(); 1603 if (c == EOF) break; 1604 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' || 1605 c == '"') 1606 add_symbol(); 1607 else if (c == '{' || c == '=') 1608 copy_action(); 1609 else if (c == '|') 1610 { 1611 end_rule(); 1612 start_rule(plhs[nrules-1], 0); 1613 ++cptr; 1614 } 1615 else if (c == '%') 1616 { 1617 if (mark_symbol()) break; 1618 } 1619 else 1620 syntax_error(lineno, line, cptr); 1621 } 1622 end_rule(); 1623 } 1624 1625 1626 void 1627 free_tags(void) 1628 { 1629 int i; 1630 1631 if (tag_table == 0) return; 1632 1633 for (i = 0; i < ntags; ++i) 1634 { 1635 assert(tag_table[i]); 1636 FREE(tag_table[i]); 1637 } 1638 FREE(tag_table); 1639 } 1640 1641 1642 void 1643 pack_names(void) 1644 { 1645 bucket *bp; 1646 char *p, *s, *t; 1647 1648 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1649 for (bp = first_symbol; bp; bp = bp->next) 1650 name_pool_size += strlen(bp->name) + 1; 1651 name_pool = MALLOC(name_pool_size); 1652 if (name_pool == 0) no_space(); 1653 1654 strlcpy(name_pool, "$accept", name_pool_size); 1655 strlcpy(name_pool+8, "$end", name_pool_size - 8); 1656 t = name_pool + 13; 1657 for (bp = first_symbol; bp; bp = bp->next) 1658 { 1659 p = t; 1660 s = bp->name; 1661 while ((*t++ = *s++)) continue; 1662 FREE(bp->name); 1663 bp->name = p; 1664 } 1665 } 1666 1667 1668 void 1669 check_symbols(void) 1670 { 1671 bucket *bp; 1672 1673 if (goal->class == UNKNOWN) 1674 undefined_goal(goal->name); 1675 1676 for (bp = first_symbol; bp; bp = bp->next) 1677 { 1678 if (bp->class == UNKNOWN) 1679 { 1680 undefined_symbol_warning(bp->name); 1681 bp->class = TERM; 1682 } 1683 } 1684 } 1685 1686 1687 void 1688 pack_symbols(void) 1689 { 1690 bucket *bp; 1691 bucket **v; 1692 int i, j, k, n; 1693 1694 nsyms = 2; 1695 ntokens = 1; 1696 for (bp = first_symbol; bp; bp = bp->next) 1697 { 1698 ++nsyms; 1699 if (bp->class == TERM) ++ntokens; 1700 } 1701 start_symbol = ntokens; 1702 nvars = nsyms - ntokens; 1703 1704 symbol_name = (char **) MALLOC(nsyms*sizeof(char *)); 1705 if (symbol_name == 0) no_space(); 1706 symbol_value = (short *) MALLOC(nsyms*sizeof(short)); 1707 if (symbol_value == 0) no_space(); 1708 symbol_prec = (short *) MALLOC(nsyms*sizeof(short)); 1709 if (symbol_prec == 0) no_space(); 1710 symbol_assoc = MALLOC(nsyms); 1711 if (symbol_assoc == 0) no_space(); 1712 1713 v = (bucket **) MALLOC(nsyms*sizeof(bucket *)); 1714 if (v == 0) no_space(); 1715 1716 v[0] = 0; 1717 v[start_symbol] = 0; 1718 1719 i = 1; 1720 j = start_symbol + 1; 1721 for (bp = first_symbol; bp; bp = bp->next) 1722 { 1723 if (bp->class == TERM) 1724 v[i++] = bp; 1725 else 1726 v[j++] = bp; 1727 } 1728 assert(i == ntokens && j == nsyms); 1729 1730 for (i = 1; i < ntokens; ++i) 1731 v[i]->index = i; 1732 1733 goal->index = start_symbol + 1; 1734 k = start_symbol + 2; 1735 while (++i < nsyms) 1736 if (v[i] != goal) 1737 { 1738 v[i]->index = k; 1739 ++k; 1740 } 1741 1742 goal->value = 0; 1743 k = 1; 1744 for (i = start_symbol + 1; i < nsyms; ++i) 1745 { 1746 if (v[i] != goal) 1747 { 1748 v[i]->value = k; 1749 ++k; 1750 } 1751 } 1752 1753 k = 0; 1754 for (i = 1; i < ntokens; ++i) 1755 { 1756 n = v[i]->value; 1757 if (n > 256) 1758 { 1759 for (j = k++; j > 0 && symbol_value[j-1] > n; --j) 1760 symbol_value[j] = symbol_value[j-1]; 1761 symbol_value[j] = n; 1762 } 1763 } 1764 1765 if (v[1]->value == UNDEFINED) 1766 v[1]->value = 256; 1767 1768 j = 0; 1769 n = 257; 1770 for (i = 2; i < ntokens; ++i) 1771 { 1772 if (v[i]->value == UNDEFINED) 1773 { 1774 while (j < k && n == symbol_value[j]) 1775 { 1776 while (++j < k && n == symbol_value[j]) continue; 1777 ++n; 1778 } 1779 v[i]->value = n; 1780 ++n; 1781 } 1782 } 1783 1784 symbol_name[0] = name_pool + 8; 1785 symbol_value[0] = 0; 1786 symbol_prec[0] = 0; 1787 symbol_assoc[0] = TOKEN; 1788 for (i = 1; i < ntokens; ++i) 1789 { 1790 symbol_name[i] = v[i]->name; 1791 symbol_value[i] = v[i]->value; 1792 symbol_prec[i] = v[i]->prec; 1793 symbol_assoc[i] = v[i]->assoc; 1794 } 1795 symbol_name[start_symbol] = name_pool; 1796 symbol_value[start_symbol] = -1; 1797 symbol_prec[start_symbol] = 0; 1798 symbol_assoc[start_symbol] = TOKEN; 1799 for (++i; i < nsyms; ++i) 1800 { 1801 k = v[i]->index; 1802 symbol_name[k] = v[i]->name; 1803 symbol_value[k] = v[i]->value; 1804 symbol_prec[k] = v[i]->prec; 1805 symbol_assoc[k] = v[i]->assoc; 1806 } 1807 1808 FREE(v); 1809 } 1810 1811 1812 void 1813 pack_grammar(void) 1814 { 1815 int i, j; 1816 int assoc, prec; 1817 1818 ritem = (short *) MALLOC(nitems*sizeof(short)); 1819 if (ritem == 0) no_space(); 1820 rlhs = (short *) MALLOC(nrules*sizeof(short)); 1821 if (rlhs == 0) no_space(); 1822 rrhs = (short *) MALLOC((nrules+1)*sizeof(short)); 1823 if (rrhs == 0) no_space(); 1824 rprec = (short *) REALLOC(rprec, nrules*sizeof(short)); 1825 if (rprec == 0) no_space(); 1826 rassoc = REALLOC(rassoc, nrules); 1827 if (rassoc == 0) no_space(); 1828 1829 ritem[0] = -1; 1830 ritem[1] = goal->index; 1831 ritem[2] = 0; 1832 ritem[3] = -2; 1833 rlhs[0] = 0; 1834 rlhs[1] = 0; 1835 rlhs[2] = start_symbol; 1836 rrhs[0] = 0; 1837 rrhs[1] = 0; 1838 rrhs[2] = 1; 1839 1840 j = 4; 1841 for (i = 3; i < nrules; ++i) 1842 { 1843 rlhs[i] = plhs[i]->index; 1844 rrhs[i] = j; 1845 assoc = TOKEN; 1846 prec = 0; 1847 while (pitem[j]) 1848 { 1849 ritem[j] = pitem[j]->index; 1850 if (pitem[j]->class == TERM) 1851 { 1852 prec = pitem[j]->prec; 1853 assoc = pitem[j]->assoc; 1854 } 1855 ++j; 1856 } 1857 ritem[j] = -i; 1858 ++j; 1859 if (rprec[i] == UNDEFINED) 1860 { 1861 rprec[i] = prec; 1862 rassoc[i] = assoc; 1863 } 1864 } 1865 rrhs[i] = j; 1866 1867 FREE(plhs); 1868 FREE(pitem); 1869 } 1870 1871 1872 void 1873 print_grammar(void) 1874 { 1875 int i, j, k; 1876 int spacing; 1877 FILE *f = verbose_file; 1878 1879 if (!vflag) return; 1880 1881 k = 1; 1882 for (i = 2; i < nrules; ++i) 1883 { 1884 if (rlhs[i] != rlhs[i-1]) 1885 { 1886 if (i != 2) fprintf(f, "\n"); 1887 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 1888 spacing = strlen(symbol_name[rlhs[i]]) + 1; 1889 } 1890 else 1891 { 1892 fprintf(f, "%4d ", i - 2); 1893 j = spacing; 1894 while (--j >= 0) putc(' ', f); 1895 putc('|', f); 1896 } 1897 1898 while (ritem[k] >= 0) 1899 { 1900 fprintf(f, " %s", symbol_name[ritem[k]]); 1901 ++k; 1902 } 1903 ++k; 1904 putc('\n', f); 1905 } 1906 } 1907 1908 1909 void 1910 reader(void) 1911 { 1912 write_section(banner); 1913 create_symbol_table(); 1914 read_declarations(); 1915 read_grammar(); 1916 free_symbol_table(); 1917 free_tags(); 1918 pack_names(); 1919 check_symbols(); 1920 pack_symbols(); 1921 pack_grammar(); 1922 free_symbols(); 1923 print_grammar(); 1924 } 1925