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