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