source: vendor/FreeBSD-yacc/current/reader.c@ 3590

Last change on this file since 3590 was 2464, checked in by bird, 20 years ago

FreeBSD CVS 2005-07-07

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