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