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