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