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