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