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