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