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