Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / byacc / dist / reader.c
blob1465685bc4481ce4b350d74a0437561f2bd40fce
1 /* $NetBSD: reader.c,v 1.2 2009/10/29 00:56:20 christos Exp $ */
2 /* Id: reader.c,v 1.18 2009/10/27 09:04:07 tom Exp */
4 #include "defs.h"
6 #include <sys/cdefs.h>
7 __RCSID("$NetBSD: reader.c,v 1.2 2009/10/29 00:56:20 christos Exp $");
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. */
14 #define LINESIZE 100
16 #define L_CURL '{'
17 #define R_CURL '}'
19 static void start_rule(bucket *bp, int s_lineno);
21 static char *cache;
22 static int cinc, cache_size;
24 int ntags;
25 static int tagmax;
26 static char **tag_table;
28 static char saw_eof;
29 char unionized;
30 char *cptr, *line;
31 static int linesize;
33 static bucket *goal;
34 static Value_t prec;
35 static int gensym;
36 static char last_was_action;
38 static int maxitems;
39 static bucket **pitem;
41 static int maxrules;
42 static bucket **plhs;
44 static size_t name_pool_size;
45 static char *name_pool;
47 char line_format[] = "#line %d \"%s\"\n";
48 int pure_parser;
50 static void
51 cachec(int c)
53 assert(cinc >= 0);
54 if (cinc >= cache_size)
56 cache_size += 256;
57 cache = REALLOC(cache, cache_size);
58 if (cache == 0)
59 no_space();
61 cache[cinc] = (char)c;
62 ++cinc;
65 static void
66 get_line(void)
68 FILE *f = input_file;
69 int c;
70 int i;
72 if (saw_eof || (c = getc(f)) == EOF)
74 if (line)
76 FREE(line);
77 line = 0;
79 cptr = 0;
80 saw_eof = 1;
81 return;
84 if (line == 0 || linesize != (LINESIZE + 1))
86 if (line)
87 FREE(line);
88 linesize = LINESIZE + 1;
89 line = MALLOC(linesize);
90 if (line == 0)
91 no_space();
94 i = 0;
95 ++lineno;
96 for (;;)
98 line[i] = (char)c;
99 if (c == '\n')
101 cptr = line;
102 return;
104 if (++i >= linesize)
106 linesize += LINESIZE;
107 line = REALLOC(line, linesize);
108 if (line == 0)
109 no_space();
111 c = getc(f);
112 if (c == EOF)
114 line[i] = '\n';
115 saw_eof = 1;
116 cptr = line;
117 return;
122 static char *
123 dup_line(void)
125 char *p, *s, *t;
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();
136 s = line;
137 t = p;
138 while ((*t++ = *s++) != '\n')
139 continue;
140 return (p);
143 static void
144 skip_comment(void)
146 char *s;
148 int st_lineno = lineno;
149 char *st_line = dup_line();
150 char *st_cptr = st_line + (cptr - line);
152 s = cptr + 2;
153 for (;;)
155 if (*s == '*' && s[1] == '/')
157 cptr = s + 2;
158 FREE(st_line);
159 return;
161 if (*s == '\n')
163 get_line();
164 if (line == 0)
165 unterminated_comment(st_lineno, st_line, st_cptr);
166 s = cptr;
168 else
169 ++s;
173 static int
174 nextc(void)
176 char *s;
178 if (line == 0)
180 get_line();
181 if (line == 0)
182 return (EOF);
185 s = cptr;
186 for (;;)
188 switch (*s)
190 case '\n':
191 get_line();
192 if (line == 0)
193 return (EOF);
194 s = cptr;
195 break;
197 case ' ':
198 case '\t':
199 case '\f':
200 case '\r':
201 case '\v':
202 case ',':
203 case ';':
204 ++s;
205 break;
207 case '\\':
208 cptr = s;
209 return ('%');
211 case '/':
212 if (s[1] == '*')
214 cptr = s;
215 skip_comment();
216 s = cptr;
217 break;
219 else if (s[1] == '/')
221 get_line();
222 if (line == 0)
223 return (EOF);
224 s = cptr;
225 break;
227 /* FALLTHRU */
229 default:
230 cptr = s;
231 return (*s);
236 static int
237 keyword(void)
239 int c;
240 char *t_cptr = cptr;
242 c = *++cptr;
243 if (isalpha(c))
245 cinc = 0;
246 for (;;)
248 if (isalpha(c))
250 if (isupper(c))
251 c = tolower(c);
252 cachec(c);
254 else if (isdigit(c) || c == '-' || c == '_' || c == '.' || c == '$')
255 cachec(c);
256 else
257 break;
258 c = *++cptr;
260 cachec(NUL);
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);
289 else
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);
305 syntax_error(lineno, line, t_cptr);
306 /*NOTREACHED */
309 struct param *lex_param;
310 struct param *parse_param;
313 * Keep a linked list of parameters
315 static void
316 copy_param(int k)
318 char *buf;
319 int c;
320 param *head, *p;
321 int i;
323 c = nextc();
324 if (c == EOF)
325 unexpected_EOF();
326 if (c != '{')
327 goto out;
328 cptr++;
330 c = nextc();
331 if (c == EOF)
332 unexpected_EOF();
333 if (c == '}')
334 goto out;
336 buf = MALLOC(linesize);
337 if (buf == NULL)
338 goto nospace;
340 for (i = 0; (c = *cptr++) != '}'; i++) {
341 if (c == EOF)
342 unexpected_EOF();
343 buf[i] = c;
346 if (i == 0)
347 goto out;
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--;
355 if (!isspace((unsigned char)buf[i]) && buf[i] != '*')
356 goto out;
358 p = MALLOC(sizeof(*p));
359 if (p == NULL)
360 goto nospace;
362 p->name = strdup(buf + i + 1);
363 if (p->name == NULL)
364 goto nospace;
366 buf[i + 1] = '\0';
367 p->type = buf;
369 if (k == LEX_PARAM)
370 head = lex_param;
371 else
372 head = parse_param;
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;
384 p->next = NULL;
385 return;
387 out:
388 syntax_error(lineno, line, cptr);
389 nospace:
390 no_space();
393 static void
394 copy_ident(void)
396 int c;
397 FILE *f = output_file;
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 (;;)
408 c = *++cptr;
409 if (c == '\n')
411 fprintf(f, "\"\n");
412 return;
414 putc(c, f);
415 if (c == '"')
417 putc('\n', f);
418 ++cptr;
419 return;
424 static void
425 copy_text(void)
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);
435 if (*cptr == '\n')
437 get_line();
438 if (line == 0)
439 unterminated_text(t_lineno, t_line, t_cptr);
441 if (!lflag)
442 fprintf(f, line_format, lineno, input_file_name);
444 loop:
445 c = *cptr++;
446 switch (c)
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);
457 case '\'':
458 case '"':
460 int s_lineno = lineno;
461 char *s_line = dup_line();
462 char *s_cptr = s_line + (cptr - line - 1);
464 quote = c;
465 putc(c, f);
466 for (;;)
468 c = *cptr++;
469 putc(c, f);
470 if (c == quote)
472 need_newline = 1;
473 FREE(s_line);
474 goto loop;
476 if (c == '\n')
477 unterminated_string(s_lineno, s_line, s_cptr);
478 if (c == '\\')
480 c = *cptr++;
481 putc(c, f);
482 if (c == '\n')
484 get_line();
485 if (line == 0)
486 unterminated_string(s_lineno, s_line, s_cptr);
492 case '/':
493 putc(c, f);
494 need_newline = 1;
495 c = *cptr;
496 if (c == '/')
498 putc('*', f);
499 while ((c = *++cptr) != '\n')
501 if (c == '*' && cptr[1] == '/')
502 fprintf(f, "* ");
503 else
504 putc(c, f);
506 fprintf(f, "*/");
507 goto next_line;
509 if (c == '*')
511 int c_lineno = lineno;
512 char *c_line = dup_line();
513 char *c_cptr = c_line + (cptr - line - 1);
515 putc('*', f);
516 ++cptr;
517 for (;;)
519 c = *cptr++;
520 putc(c, f);
521 if (c == '*' && *cptr == '/')
523 putc('/', f);
524 ++cptr;
525 FREE(c_line);
526 goto loop;
528 if (c == '\n')
530 get_line();
531 if (line == 0)
532 unterminated_comment(c_lineno, c_line, c_cptr);
536 need_newline = 1;
537 goto loop;
539 case '%':
540 case '\\':
541 if (*cptr == R_CURL)
543 if (need_newline)
544 putc('\n', f);
545 ++cptr;
546 FREE(t_line);
547 return;
549 /* FALLTHRU */
551 default:
552 putc(c, f);
553 need_newline = 1;
554 goto loop;
558 static void
559 copy_union(void)
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);
568 if (unionized)
569 over_unionized(cptr - 6);
570 unionized = 1;
572 if (!lflag)
573 fprintf(text_file, line_format, lineno, input_file_name);
575 fprintf(text_file, "typedef union YYSTYPE");
576 if (dflag)
577 fprintf(union_file, "typedef union YYSTYPE");
579 depth = 0;
580 loop:
581 c = *cptr++;
582 putc(c, text_file);
583 if (dflag)
584 putc(c, union_file);
585 switch (c)
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;
594 case L_CURL:
595 ++depth;
596 goto loop;
598 case R_CURL:
599 if (--depth == 0)
601 fprintf(text_file, " YYSTYPE;\n");
602 FREE(u_line);
603 return;
605 goto loop;
607 case '\'':
608 case '"':
610 int s_lineno = lineno;
611 char *s_line = dup_line();
612 char *s_cptr = s_line + (cptr - line - 1);
614 quote = c;
615 for (;;)
617 c = *cptr++;
618 putc(c, text_file);
619 if (dflag)
620 putc(c, union_file);
621 if (c == quote)
623 FREE(s_line);
624 goto loop;
626 if (c == '\n')
627 unterminated_string(s_lineno, s_line, s_cptr);
628 if (c == '\\')
630 c = *cptr++;
631 putc(c, text_file);
632 if (dflag)
633 putc(c, union_file);
634 if (c == '\n')
636 get_line();
637 if (line == 0)
638 unterminated_string(s_lineno, s_line, s_cptr);
644 case '/':
645 c = *cptr;
646 if (c == '/')
648 putc('*', text_file);
649 if (dflag)
650 putc('*', union_file);
651 while ((c = *++cptr) != '\n')
653 if (c == '*' && cptr[1] == '/')
655 fprintf(text_file, "* ");
656 if (dflag)
657 fprintf(union_file, "* ");
659 else
661 putc(c, text_file);
662 if (dflag)
663 putc(c, union_file);
666 fprintf(text_file, "*/\n");
667 if (dflag)
668 fprintf(union_file, "*/\n");
669 goto next_line;
671 if (c == '*')
673 int c_lineno = lineno;
674 char *c_line = dup_line();
675 char *c_cptr = c_line + (cptr - line - 1);
677 putc('*', text_file);
678 if (dflag)
679 putc('*', union_file);
680 ++cptr;
681 for (;;)
683 c = *cptr++;
684 putc(c, text_file);
685 if (dflag)
686 putc(c, union_file);
687 if (c == '*' && *cptr == '/')
689 putc('/', text_file);
690 if (dflag)
691 putc('/', union_file);
692 ++cptr;
693 FREE(c_line);
694 goto loop;
696 if (c == '\n')
698 get_line();
699 if (line == 0)
700 unterminated_comment(c_lineno, c_line, c_cptr);
704 goto loop;
706 default:
707 goto loop;
711 static int
712 hexval(int c)
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);
723 static bucket *
724 get_literal(void)
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);
735 quote = *cptr++;
736 cinc = 0;
737 for (;;)
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 == '\\')
746 char *c_cptr = cptr - 1;
748 c = *cptr++;
749 switch (c)
751 case '\n':
752 get_line();
753 if (line == 0)
754 unterminated_string(s_lineno, s_line, s_cptr);
755 continue;
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))
769 n = (n << 3) + (c - '0');
770 c = *++cptr;
771 if (IS_OCTAL(c))
773 n = (n << 3) + (c - '0');
774 ++cptr;
777 if (n > MAXCHAR)
778 illegal_character(c_cptr);
779 c = n;
780 break;
782 case 'x':
783 c = *cptr++;
784 n = hexval(c);
785 if (n < 0 || n >= 16)
786 illegal_character(c_cptr);
787 for (;;)
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);
798 c = n;
799 break;
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;
824 cachec(c);
826 FREE(s_line);
828 n = cinc;
829 s = MALLOC(n);
830 if (s == 0)
831 no_space();
833 for (i = 0; i < n; ++i)
834 s[i] = cache[i];
836 cinc = 0;
837 if (n == 1)
838 cachec('\'');
839 else
840 cachec('"');
842 for (i = 0; i < n; ++i)
844 c = ((unsigned char *)s)[i];
845 if (c == '\\' || c == cache[0])
847 cachec('\\');
848 cachec(c);
850 else if (isprint(c))
851 cachec(c);
852 else
854 cachec('\\');
855 switch (c)
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;
887 if (n == 1)
888 cachec('\'');
889 else
890 cachec('"');
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);
899 return (bp);
902 static int
903 is_reserved(char *name)
905 char *s;
907 if (strcmp(name, ".") == 0 ||
908 strcmp(name, "$accept") == 0 ||
909 strcmp(name, "$end") == 0)
910 return (1);
912 if (name[0] == '$' && name[1] == '$' && isdigit((unsigned char)name[2]))
914 s = name + 3;
915 while (isdigit((unsigned char)*s))
916 ++s;
917 if (*s == NUL)
918 return (1);
921 return (0);
924 static bucket *
925 get_name(void)
927 int c;
929 cinc = 0;
930 for (c = *cptr; IS_IDENT(c); c = *++cptr)
931 cachec(c);
932 cachec(NUL);
934 if (is_reserved(cache))
935 used_reserved(cache);
937 return (lookup(cache));
940 static Value_t
941 get_number(void)
943 int c;
944 Value_t n;
946 n = 0;
947 for (c = *cptr; isdigit(c); c = *++cptr)
948 n = (Value_t) (10 * n + (c - '0'));
950 return (n);
953 static char *
954 get_tag(void)
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);
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);
970 cinc = 0;
973 cachec(c);
974 c = *++cptr;
976 while (IS_IDENT(c));
977 cachec(NUL);
979 c = nextc();
980 if (c == EOF)
981 unexpected_EOF();
982 if (c != '>')
983 illegal_tag(t_lineno, t_line, t_cptr);
984 ++cptr;
986 for (i = 0; i < ntags; ++i)
988 if (strcmp(cache, tag_table[i]) == 0)
990 FREE(t_line);
991 return (tag_table[i]);
995 if (ntags >= tagmax)
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();
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);
1016 static void
1017 declare_tokens(int assoc)
1019 int c;
1020 bucket *bp;
1021 Value_t value;
1022 char *tag = 0;
1024 if (assoc != TOKEN)
1025 ++prec;
1027 c = nextc();
1028 if (c == EOF)
1029 unexpected_EOF();
1030 if (c == '<')
1032 tag = get_tag();
1033 c = nextc();
1034 if (c == EOF)
1035 unexpected_EOF();
1038 for (;;)
1040 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1041 bp = get_name();
1042 else if (c == '\'' || c == '"')
1043 bp = get_literal();
1044 else
1045 return;
1047 if (bp == goal)
1048 tokenized_start(bp->name);
1049 bp->class = TERM;
1051 if (tag)
1053 if (bp->tag && tag != bp->tag)
1054 retyped_warning(bp->name);
1055 bp->tag = tag;
1058 if (assoc != TOKEN)
1060 if (bp->prec && prec != bp->prec)
1061 reprec_warning(bp->name);
1062 bp->assoc = (Assoc_t) assoc;
1063 bp->prec = prec;
1066 c = nextc();
1067 if (c == EOF)
1068 unexpected_EOF();
1069 value = UNDEFINED;
1070 if (isdigit(c))
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();
1084 * %expect requires special handling
1085 * as it really isn't part of the yacc
1086 * grammar only a flag for yacc proper.
1088 static void
1089 declare_expect(int assoc)
1091 int c;
1093 if (assoc != EXPECT && assoc != EXPECT_RR)
1094 ++prec;
1097 * Stay away from nextc - doesn't
1098 * detect EOL and will read to EOF.
1100 c = *++cptr;
1101 if (c == EOF)
1102 unexpected_EOF();
1104 for (;;)
1106 if (isdigit(c))
1108 if (assoc == EXPECT)
1109 SRexpect = get_number();
1110 else
1111 RRexpect = get_number();
1112 break;
1115 * Looking for number before EOL.
1116 * Spaces, tabs, and numbers are ok,
1117 * words, punc., etc. are syntax errors.
1119 else if (c == '\n' || isalpha(c) || !isspace(c))
1121 syntax_error(lineno, line, cptr);
1123 else
1125 c = *++cptr;
1126 if (c == EOF)
1127 unexpected_EOF();
1132 static void
1133 declare_types(void)
1135 int c;
1136 bucket *bp;
1137 char *tag;
1139 c = nextc();
1140 if (c == EOF)
1141 unexpected_EOF();
1142 if (c != '<')
1143 syntax_error(lineno, line, cptr);
1144 tag = get_tag();
1146 for (;;)
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;
1156 if (bp->tag && tag != bp->tag)
1157 retyped_warning(bp->name);
1158 bp->tag = tag;
1162 static void
1163 declare_start(void)
1165 int c;
1166 bucket *bp;
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;
1181 static void
1182 read_declarations(void)
1184 int c, k;
1186 cache_size = 256;
1187 cache = MALLOC(cache_size);
1188 if (cache == 0)
1189 no_space();
1191 for (;;)
1193 c = nextc();
1194 if (c == EOF)
1195 unexpected_EOF();
1196 if (c != '%')
1197 syntax_error(lineno, line, cptr);
1198 switch (k = keyword())
1200 case MARK:
1201 return;
1203 case IDENT:
1204 copy_ident();
1205 break;
1207 case TEXT:
1208 copy_text();
1209 break;
1211 case UNION:
1212 copy_union();
1213 break;
1215 case PURE_PARSER:
1216 pure_parser = 1;
1217 break;
1219 case LEX_PARAM:
1220 case PARSE_PARAM:
1221 copy_param(k);
1222 break;
1224 case TOKEN:
1225 case LEFT:
1226 case RIGHT:
1227 case NONASSOC:
1228 declare_tokens(k);
1229 break;
1231 case EXPECT:
1232 case EXPECT_RR:
1233 declare_expect(k);
1234 break;
1236 case TYPE:
1237 declare_types();
1238 break;
1240 case START:
1241 declare_start();
1242 break;
1247 static void
1248 initialize_grammar(void)
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;
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;
1282 static void
1283 expand_items(void)
1285 maxitems += 300;
1286 pitem = (bucket **)REALLOC(pitem, (unsigned)maxitems * sizeof(bucket *));
1287 if (pitem == 0)
1288 no_space();
1291 static void
1292 expand_rules(void)
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();
1306 static void
1307 advance_to_start(void)
1309 int c;
1310 bucket *bp;
1311 char *s_cptr;
1312 int s_lineno;
1314 for (;;)
1316 c = nextc();
1317 if (c != '%')
1318 break;
1319 s_cptr = cptr;
1320 switch (keyword())
1322 case MARK:
1323 no_grammar();
1325 case TEXT:
1326 copy_text();
1327 break;
1329 case START:
1330 declare_start();
1331 break;
1333 default:
1334 syntax_error(lineno, line, s_cptr);
1338 c = nextc();
1339 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1340 syntax_error(lineno, line, cptr);
1341 bp = get_name();
1342 if (goal == 0)
1344 if (bp->class == TERM)
1345 terminal_start(bp->name);
1346 goal = bp;
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;
1359 static void
1360 start_rule(bucket *bp, int s_lineno)
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;
1372 static void
1373 end_rule(void)
1375 int i;
1377 if (!last_was_action && plhs[nrules]->tag)
1379 if (pitem[nitems - 1])
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();
1388 last_was_action = 0;
1389 if (nitems >= maxitems)
1390 expand_items();
1391 pitem[nitems] = 0;
1392 ++nitems;
1393 ++nrules;
1396 static void
1397 insert_empty_rule(void)
1399 bucket *bp, **bpp;
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;
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;
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;
1426 static void
1427 add_symbol(void)
1429 int c;
1430 bucket *bp;
1431 int s_lineno = lineno;
1433 c = *cptr;
1434 if (c == '\'' || c == '"')
1435 bp = get_literal();
1436 else
1437 bp = get_name();
1439 c = nextc();
1440 if (c == ':')
1442 end_rule();
1443 start_rule(bp, s_lineno);
1444 ++cptr;
1445 return;
1448 if (last_was_action)
1449 insert_empty_rule();
1450 last_was_action = 0;
1452 if (++nitems > maxitems)
1453 expand_items();
1454 pitem[nitems - 1] = bp;
1457 static char *
1458 after_blanks(char *s)
1460 while (*s != '\0' && isspace((unsigned char)*s))
1461 ++s;
1462 return s;
1465 static void
1466 copy_action(void)
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);
1478 if (last_was_action)
1479 insert_empty_rule();
1480 last_was_action = 1;
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;
1488 /* avoid putting curly-braces in first column, to ease editing */
1489 if (*after_blanks(cptr) == L_CURL)
1491 putc('\t', f);
1492 cptr = after_blanks(cptr);
1495 n = 0;
1496 for (i = nitems - 1; pitem[i]; --i)
1497 ++n;
1499 depth = 0;
1500 loop:
1501 c = *cptr;
1502 if (c == '$')
1504 if (cptr[1] == '<')
1506 int d_lineno = lineno;
1507 char *d_line = dup_line();
1508 char *d_cptr = d_line + (cptr - line);
1510 ++cptr;
1511 tag = get_tag();
1512 c = *cptr;
1513 if (c == '$')
1515 fprintf(f, "yyval.%s", tag);
1516 ++cptr;
1517 FREE(d_line);
1518 goto loop;
1520 else if (isdigit(c))
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;
1529 else if (c == '-' && isdigit((unsigned char)cptr[1]))
1531 ++cptr;
1532 i = -get_number() - n;
1533 fprintf(f, "yyvsp[%d].%s", i, tag);
1534 FREE(d_line);
1535 goto loop;
1537 else
1538 dollar_error(d_lineno, d_line, d_cptr);
1540 else if (cptr[1] == '$')
1542 if (ntags)
1544 tag = plhs[nrules]->tag;
1545 if (tag == 0)
1546 untyped_lhs();
1547 fprintf(f, "yyval.%s", tag);
1549 else
1550 fprintf(f, "yyval");
1551 cptr += 2;
1552 goto loop;
1554 else if (isdigit((unsigned char)cptr[1]))
1556 ++cptr;
1557 i = get_number();
1558 if (ntags)
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);
1567 else
1569 if (i > n)
1570 dollar_warning(lineno, i);
1571 fprintf(f, "yyvsp[%d]", i - n);
1573 goto loop;
1575 else if (cptr[1] == '-')
1577 cptr += 2;
1578 i = get_number();
1579 if (ntags)
1580 unknown_rhs(-i);
1581 fprintf(f, "yyvsp[%d]", -i - n);
1582 goto loop;
1585 if (isalpha(c) || c == '_' || c == '$')
1589 putc(c, f);
1590 c = *++cptr;
1592 while (isalnum(c) || c == '_' || c == '$');
1593 goto loop;
1595 putc(c, f);
1596 ++cptr;
1597 switch (c)
1599 case '\n':
1600 next_line:
1601 get_line();
1602 if (line)
1603 goto loop;
1604 unterminated_action(a_lineno, a_line, a_cptr);
1606 case ';':
1607 if (depth > 0)
1608 goto loop;
1609 fprintf(f, "\nbreak;\n");
1610 free(a_line);
1611 return;
1613 case L_CURL:
1614 ++depth;
1615 goto loop;
1617 case R_CURL:
1618 if (--depth > 0)
1619 goto loop;
1620 fprintf(f, "\nbreak;\n");
1621 free(a_line);
1622 return;
1624 case '\'':
1625 case '"':
1627 int s_lineno = lineno;
1628 char *s_line = dup_line();
1629 char *s_cptr = s_line + (cptr - line - 1);
1631 quote = c;
1632 for (;;)
1634 c = *cptr++;
1635 putc(c, f);
1636 if (c == quote)
1638 FREE(s_line);
1639 goto loop;
1641 if (c == '\n')
1642 unterminated_string(s_lineno, s_line, s_cptr);
1643 if (c == '\\')
1645 c = *cptr++;
1646 putc(c, f);
1647 if (c == '\n')
1649 get_line();
1650 if (line == 0)
1651 unterminated_string(s_lineno, s_line, s_cptr);
1657 case '/':
1658 c = *cptr;
1659 if (c == '/')
1661 putc('*', f);
1662 while ((c = *++cptr) != '\n')
1664 if (c == '*' && cptr[1] == '/')
1665 fprintf(f, "* ");
1666 else
1667 putc(c, f);
1669 fprintf(f, "*/\n");
1670 goto next_line;
1672 if (c == '*')
1674 int c_lineno = lineno;
1675 char *c_line = dup_line();
1676 char *c_cptr = c_line + (cptr - line - 1);
1678 putc('*', f);
1679 ++cptr;
1680 for (;;)
1682 c = *cptr++;
1683 putc(c, f);
1684 if (c == '*' && *cptr == '/')
1686 putc('/', f);
1687 ++cptr;
1688 FREE(c_line);
1689 goto loop;
1691 if (c == '\n')
1693 get_line();
1694 if (line == 0)
1695 unterminated_comment(c_lineno, c_line, c_cptr);
1699 goto loop;
1701 default:
1702 goto loop;
1706 static int
1707 mark_symbol(void)
1709 int c;
1710 bucket *bp;
1712 c = cptr[1];
1713 if (c == '%' || c == '\\')
1715 cptr += 2;
1716 return (1);
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);
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
1737 syntax_error(lineno, line, cptr);
1738 /*NOTREACHED */
1741 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1742 prec_redeclared();
1744 rprec[nrules] = bp->prec;
1745 rassoc[nrules] = bp->assoc;
1746 return (0);
1749 static void
1750 read_grammar(void)
1752 int c;
1754 initialize_grammar();
1755 advance_to_start();
1757 for (;;)
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 == '|')
1773 end_rule();
1774 start_rule(plhs[nrules - 1], 0);
1775 ++cptr;
1777 else if (c == '%')
1779 if (mark_symbol())
1780 break;
1782 else
1783 syntax_error(lineno, line, cptr);
1785 end_rule();
1788 static void
1789 free_tags(void)
1791 int i;
1793 if (tag_table == 0)
1794 return;
1796 for (i = 0; i < ntags; ++i)
1798 assert(tag_table[i]);
1799 FREE(tag_table[i]);
1801 FREE(tag_table);
1804 static void
1805 pack_names(void)
1807 bucket *bp;
1808 char *p, *s, *t;
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();
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)
1822 p = t;
1823 s = bp->name;
1824 while ((*t++ = *s++) != 0)
1825 continue;
1826 FREE(bp->name);
1827 bp->name = p;
1831 static void
1832 check_symbols(void)
1834 bucket *bp;
1836 if (goal->class == UNKNOWN)
1837 undefined_goal(goal->name);
1839 for (bp = first_symbol; bp; bp = bp->next)
1841 if (bp->class == UNKNOWN)
1843 undefined_symbol_warning(bp->name);
1844 bp->class = TERM;
1849 static void
1850 protect_string(char *src, char **des)
1852 unsigned len;
1853 char *s;
1854 char *d;
1856 *des = src;
1857 if (src)
1859 len = 1;
1860 s = src;
1861 while (*s)
1863 if ('\\' == *s || '"' == *s)
1864 len++;
1865 s++;
1866 len++;
1868 *des = d = (char *)MALLOC(len);
1869 if (0 == *des)
1870 no_space();
1871 s = src;
1872 while (*s)
1874 if ('\\' == *s || '"' == *s)
1875 *d++ = '\\';
1876 *d++ = *s++;
1878 *d = '\0';
1882 static void
1883 pack_symbols(void)
1885 bucket *bp;
1886 bucket **v;
1887 Value_t i, j, k, n;
1889 nsyms = 2;
1890 ntokens = 1;
1891 for (bp = first_symbol; bp; bp = bp->next)
1893 ++nsyms;
1894 if (bp->class == TERM)
1895 ++ntokens;
1897 start_symbol = (Value_t) ntokens;
1898 nvars = nsyms - ntokens;
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();
1913 v = (bucket **)MALLOC((unsigned)nsyms * sizeof(bucket *));
1914 if (v == 0)
1915 no_space();
1917 v[0] = 0;
1918 v[start_symbol] = 0;
1920 i = 1;
1921 j = (Value_t) (start_symbol + 1);
1922 for (bp = first_symbol; bp; bp = bp->next)
1924 if (bp->class == TERM)
1925 v[i++] = bp;
1926 else
1927 v[j++] = bp;
1929 assert(i == ntokens && j == nsyms);
1931 for (i = 1; i < ntokens; ++i)
1932 v[i]->index = i;
1934 goal->index = (Index_t) (start_symbol + 1);
1935 k = (Value_t) (start_symbol + 2);
1936 while (++i < nsyms)
1937 if (v[i] != goal)
1939 v[i]->index = k;
1940 ++k;
1943 goal->value = 0;
1944 k = 1;
1945 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
1947 if (v[i] != goal)
1949 v[i]->value = k;
1950 ++k;
1954 k = 0;
1955 for (i = 1; i < ntokens; ++i)
1957 n = v[i]->value;
1958 if (n > 256)
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;
1966 if (v[1]->value == UNDEFINED)
1967 v[1]->value = 256;
1969 j = 0;
1970 n = 257;
1971 for (i = 2; i < ntokens; ++i)
1973 if (v[i]->value == UNDEFINED)
1975 while (j < k && n == symbol_value[j])
1977 while (++j < k && n == symbol_value[j])
1978 continue;
1979 ++n;
1981 v[i]->value = n;
1982 ++n;
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)
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;
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)
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;
2010 if (gflag)
2012 symbol_pname = (char **)MALLOC((unsigned)nsyms * sizeof(char *));
2013 if (symbol_pname == 0)
2014 no_space();
2016 for (i = 0; i < nsyms; ++i)
2017 protect_string(symbol_name[i], &(symbol_pname[i]));
2020 FREE(v);
2023 static void
2024 pack_grammar(void)
2026 int i;
2027 Value_t j;
2028 Assoc_t assoc;
2029 Value_t prec2;
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();
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;
2058 j = 4;
2059 for (i = 3; i < nrules; ++i)
2061 rlhs[i] = plhs[i]->index;
2062 rrhs[i] = j;
2063 assoc = TOKEN;
2064 prec2 = 0;
2065 while (pitem[j])
2067 ritem[j] = pitem[j]->index;
2068 if (pitem[j]->class == TERM)
2070 prec2 = pitem[j]->prec;
2071 assoc = pitem[j]->assoc;
2073 ++j;
2075 ritem[j] = (Value_t) - i;
2076 ++j;
2077 if (rprec[i] == UNDEFINED)
2079 rprec[i] = prec2;
2080 rassoc[i] = assoc;
2083 rrhs[i] = j;
2085 FREE(plhs);
2086 FREE(pitem);
2089 static void
2090 print_grammar(void)
2092 int i, k;
2093 size_t j, spacing = 0;
2094 FILE *f = verbose_file;
2096 if (!vflag)
2097 return;
2099 k = 1;
2100 for (i = 2; i < nrules; ++i)
2102 if (rlhs[i] != rlhs[i - 1])
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;
2109 else
2111 fprintf(f, "%4d ", i - 2);
2112 j = spacing;
2113 while (j-- != 0)
2114 putc(' ', f);
2115 putc('|', f);
2118 while (ritem[k] >= 0)
2120 fprintf(f, " %s", symbol_name[ritem[k]]);
2121 ++k;
2123 ++k;
2124 putc('\n', f);
2128 void
2129 reader(void)
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();
2144 #ifdef NO_LEAKS
2145 void
2146 reader_leaks(void)
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);
2161 #endif