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