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