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