1 /* $Id: reader.c,v 1.57 2014/10/06 00:52:44 tom Exp $ */
5 /* The line size must be a positive integer. One hundred was chosen */
6 /* because few lines in Yacc input grammars exceed 100 characters. */
7 /* Note that if a line exceeds LINESIZE characters, the line buffer */
8 /* will be expanded to accomodate it. */
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
23 static void start_rule(bucket *bp, int s_lineno);
25 static void copy_destructor(void);
26 static char *process_destructor_XX(char *code, char *tag);
30 static int cinc, cache_size;
33 static int tagmax, havetags;
34 static char **tag_table;
44 static char last_was_action;
47 static bucket **pitem;
52 static size_t name_pool_size;
53 static char *name_pool;
55 char line_format[] = "#line %d \"%s\"\n";
61 int destructor = 0; /* =1 if at least one %destructor */
63 static bucket *default_destructor[3] =
66 #define UNTYPED_DEFAULT 0
67 #define TYPED_DEFAULT 1
68 #define TYPE_SPECIFIED 2
71 lookup_type_destructor(char *tag)
73 const char fmt[] = "%.*s destructor";
74 char name[1024] = "\0";
75 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
77 while ((bp = *bpp) != NULL)
84 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
85 *bpp = bp = make_bucket(name);
90 #endif /* defined(YYBTYACC) */
96 if (cinc >= cache_size)
99 cache = TREALLOC(char, cache, cache_size);
102 cache[cinc] = (char)c;
109 FILE *f = input_file;
113 if (saw_eof || (c = getc(f)) == EOF)
125 if (line == 0 || linesize != (LINESIZE + 1))
129 linesize = LINESIZE + 1;
130 line = TCMALLOC(char, linesize);
143 linesize += LINESIZE;
144 line = TREALLOC(char, line, linesize);
169 p = TMALLOC(char, s - line + 1);
174 while ((*t++ = *s++) != '\n')
184 int st_lineno = lineno;
185 char *st_line = dup_line();
186 char *st_cptr = st_line + (cptr - line);
191 if (*s == '*' && s[1] == '/')
201 unterminated_comment(st_lineno, st_line, st_cptr);
234 else if (s[1] == '/')
259 switch (ch = next_inline())
286 static struct keyword
292 { "binary", NONASSOC },
293 #if defined(YYBTYACC)
294 { "destructor", DESTRUCTOR },
296 { "expect", EXPECT },
297 { "expect-rr", EXPECT_RR },
300 { "lex-param", LEX_PARAM },
301 #if defined(YYBTYACC)
302 { "locations", LOCATIONS },
304 { "nonassoc", NONASSOC },
305 { "parse-param", PARSE_PARAM },
306 { "pure-parser", PURE_PARSER },
311 { "token-table", TOKEN_TABLE },
314 { "yacc", POSIX_YACC },
319 compare_keys(const void *a, const void *b)
321 const struct keyword *p = (const struct keyword *)a;
322 const struct keyword *q = (const struct keyword *)b;
323 return strcmp(p->name, q->name);
354 /* treat keywords spelled with '_' as if it were '-' */
365 if ((key = bsearch(cache, keywords,
366 sizeof(keywords) / sizeof(*key),
367 sizeof(*key), compare_keys)))
375 if (c == '%' || c == '\\')
386 syntax_error(lineno, line, t_cptr);
393 FILE *f = output_file;
399 syntax_error(lineno, line, cptr);
401 fprintf(f, "#ident \"");
421 copy_string(int quote)
423 struct mstring *temp = msnew();
425 int s_lineno = lineno;
426 char *s_line = dup_line();
427 char *s_cptr = s_line + (cptr - line - 1);
439 unterminated_string(s_lineno, s_line, s_cptr);
448 unterminated_string(s_lineno, s_line, s_cptr);
457 struct mstring *temp = msnew();
464 while ((c = *++cptr) != '\n')
467 if (c == '*' && cptr[1] == '/')
475 int c_lineno = lineno;
476 char *c_line = dup_line();
477 char *c_cptr = c_line + (cptr - line - 1);
485 if (c == '*' && *cptr == '/')
496 unterminated_comment(c_lineno, c_line, c_cptr);
508 int need_newline = 0;
509 int t_lineno = lineno;
510 char *t_line = dup_line();
511 char *t_cptr = t_line + (cptr - line - 2);
517 unterminated_text(t_lineno, t_line, t_cptr);
520 fprintf(f, line_format, lineno, input_file_name);
532 unterminated_text(t_lineno, t_line, t_cptr);
538 char *s = copy_string(c);
548 char *s = copy_comment();
575 puts_both(const char *s)
579 fputs(s, union_file);
595 int u_lineno = lineno;
596 char *u_line = dup_line();
597 char *u_cptr = u_line + (cptr - line - 6);
600 over_unionized(cptr - 6);
604 fprintf(text_file, line_format, lineno, input_file_name);
606 puts_both("#ifdef YYSTYPE\n");
607 puts_both("#undef YYSTYPE_IS_DECLARED\n");
608 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
609 puts_both("#endif\n");
610 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
611 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
612 puts_both("typedef union");
623 unterminated_union(u_lineno, u_line, u_cptr);
633 puts_both(" YYSTYPE;\n");
634 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
643 char *s = copy_string(c);
651 char *s = copy_comment();
663 after_blanks(char *s)
665 while (*s != '\0' && isspace(UCH(*s)))
671 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
672 * single space. Return index to last character in the buffer.
675 trim_blanks(char *buffer)
680 char *s = after_blanks(d);
682 while ((*d++ = *s++) != '\0')
688 while ((--d != buffer) && isspace(UCH(*d)))
691 for (s = d = buffer; (*d++ = *s++) != '\0';)
693 if (isspace(UCH(*s)))
696 while (isspace(UCH(*s)))
705 return (int)strlen(buffer) - 1;
709 * Scan forward in the current line-buffer looking for a right-curly bracket.
711 * Parameters begin with a left-curly bracket, and continue until there are no
712 * more interesting characters after the last right-curly bracket on the
713 * current line. Bison documents parameters as separated like this:
714 * {type param1} {type2 param2}
715 * but also accepts commas (although some versions of bison mishandle this)
716 * {type param1, type2 param2}
726 switch (next_inline())
745 save_param(int k, char *buffer, int name, int type2)
749 p = TMALLOC(param, 1);
752 p->type2 = strdup(buffer + type2);
754 buffer[type2] = '\0';
755 (void)trim_blanks(p->type2);
757 p->name = strdup(buffer + name);
760 (void)trim_blanks(p->name);
762 p->type = strdup(buffer);
764 (void)trim_blanks(p->type);
788 * Keep a linked list of parameters. This may be multi-line, if the trailing
789 * right-curly bracket is absent.
800 int st_lineno = lineno;
834 if ((curly == 1) && (cptr == line))
844 if (curly == 0 && !isspace(UCH(c)))
852 buf_size = (size_t) linesize;
853 buf = TMALLOC(char, buf_size);
861 buf_size += (size_t) linesize;
862 buf = TREALLOC(char, buf, buf_size);
867 if ((state == 2) && (c == L_CURL))
871 else if ((state == 2) && isspace(UCH(c)))
875 else if ((c != L_CURL) && (c != R_CURL))
882 while (curly < 2 || more_curly());
895 i = trim_blanks(buf);
900 char *parms = (comma + 1);
901 comma = strchr(parms, ',');
905 (void)trim_blanks(parms);
906 i = (int)strlen(parms) - 1;
915 while (i >= 0 && level > 0 && parms[i] != '[')
919 else if (parms[i] == '[')
932 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
935 if (!isspace(UCH(parms[i])) && parms[i] != '*')
940 save_param(k, parms, name, type2);
948 syntax_error(lineno, line, cptr);
954 if (c >= '0' && c <= '9')
956 if (c >= 'A' && c <= 'F')
957 return (c - 'A' + 10);
958 if (c >= 'a' && c <= 'f')
959 return (c - 'a' + 10);
971 int s_lineno = lineno;
972 char *s_line = dup_line();
973 char *s_cptr = s_line + (cptr - line);
983 unterminated_string(s_lineno, s_line, s_cptr);
986 char *c_cptr = cptr - 1;
994 unterminated_string(s_lineno, s_line, s_cptr);
1009 n = (n << 3) + (c - '0');
1013 n = (n << 3) + (c - '0');
1018 illegal_character(c_cptr);
1025 if (n < 0 || n >= 16)
1026 illegal_character(c_cptr);
1031 if (i < 0 || i >= 16)
1036 illegal_character(c_cptr);
1069 s = TMALLOC(char, n);
1072 for (i = 0; i < n; ++i)
1081 for (i = 0; i < n; ++i)
1084 if (c == '\\' || c == cache[0])
1089 else if (isprint(c))
1118 cachec(((c >> 6) & 7) + '0');
1119 cachec(((c >> 3) & 7) + '0');
1120 cachec((c & 7) + '0');
1134 if (n == 1 && bp->value == UNDEFINED)
1135 bp->value = UCH(*s);
1142 is_reserved(char *name)
1146 if (strcmp(name, ".") == 0 ||
1147 strcmp(name, "$accept") == 0 ||
1148 strcmp(name, "$end") == 0)
1151 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1154 while (isdigit(UCH(*s)))
1169 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1173 if (is_reserved(cache))
1174 used_reserved(cache);
1176 return (lookup(cache));
1186 for (c = *cptr; isdigit(c); c = *++cptr)
1187 n = (Value_t) (10 * n + (c - '0'));
1193 cache_tag(char *tag, size_t len)
1198 for (i = 0; i < ntags; ++i)
1200 if (strncmp(tag, tag_table[i], len) == 0 &&
1201 tag_table[i][len] == NUL)
1202 return (tag_table[i]);
1205 if (ntags >= tagmax)
1210 ? TREALLOC(char *, tag_table, tagmax)
1211 : TMALLOC(char *, tagmax));
1212 NO_SPACE(tag_table);
1215 s = TMALLOC(char, len + 1);
1218 strncpy(s, tag, len);
1220 tag_table[ntags++] = s;
1228 int t_lineno = lineno;
1229 char *t_line = dup_line();
1230 char *t_cptr = t_line + (cptr - line);
1236 if (!isalpha(c) && c != '_' && c != '$')
1237 illegal_tag(t_lineno, t_line, t_cptr);
1245 while (IS_IDENT(c));
1252 illegal_tag(t_lineno, t_line, t_cptr);
1257 return cache_tag(cache, (size_t) cinc);
1260 #if defined(YYBTYACC)
1266 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1268 return cache_tag(b, (size_t) (cptr - b));
1273 declare_tokens(int assoc)
1296 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1298 else if (c == '\'' || c == '"')
1304 tokenized_start(bp->name);
1309 if (bp->tag && tag != bp->tag)
1310 retyped_warning(bp->name);
1316 if (bp->prec && prec != bp->prec)
1317 reprec_warning(bp->name);
1318 bp->assoc = (Assoc_t) assoc;
1328 value = get_number();
1329 if (bp->value != UNDEFINED && value != bp->value)
1330 revalued_warning(bp->name);
1340 * %expect requires special handling
1341 * as it really isn't part of the yacc
1342 * grammar only a flag for yacc proper.
1345 declare_expect(int assoc)
1349 if (assoc != EXPECT && assoc != EXPECT_RR)
1353 * Stay away from nextc - doesn't
1354 * detect EOL and will read to EOF.
1364 if (assoc == EXPECT)
1365 SRexpect = get_number();
1367 RRexpect = get_number();
1371 * Looking for number before EOL.
1372 * Spaces, tabs, and numbers are ok,
1373 * words, punc., etc. are syntax errors.
1375 else if (c == '\n' || isalpha(c) || !isspace(c))
1377 syntax_error(lineno, line, cptr);
1388 #if defined(YYBTYACC)
1390 declare_argtypes(bucket *bp)
1392 char *tags[MAXARGS];
1396 retyped_warning(bp->name);
1397 cptr++; /* skip open paren */
1404 syntax_error(lineno, line, cptr);
1405 tags[args++] = get_tag();
1412 cptr++; /* skip close paren */
1414 bp->argnames = TMALLOC(char *, args);
1415 NO_SPACE(bp->argnames);
1416 bp->argtags = CALLOC(sizeof(char *), args + 1);
1417 NO_SPACE(bp->argtags);
1420 bp->argtags[args] = tags[args];
1421 bp->argnames[args] = NULL;
1444 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1447 #if defined(YYBTYACC)
1448 if (nextc() == L_PAREN)
1449 declare_argtypes(bp);
1454 else if (c == '\'' || c == '"')
1457 #if defined(YYBTYACC)
1466 if (bp->tag && tag != bp->tag)
1467 retyped_warning(bp->name);
1482 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1483 syntax_error(lineno, line, cptr);
1485 if (bp->class == TERM)
1486 terminal_start(bp->name);
1487 if (goal && goal != bp)
1488 restarted_warning();
1493 read_declarations(void)
1498 cache = TMALLOC(char, cache_size);
1507 syntax_error(lineno, line, cptr);
1508 switch (k = keyword())
1558 #if defined(YYBTYACC)
1570 /* noop for bison compatibility. byacc is already designed to be posix
1571 * yacc compatible. */
1578 initialize_grammar(void)
1583 pitem = TMALLOC(bucket *, maxitems);
1594 plhs = TMALLOC(bucket *, maxrules);
1601 rprec = TMALLOC(Value_t, maxrules);
1608 rassoc = TMALLOC(Assoc_t, maxrules);
1620 pitem = TREALLOC(bucket *, pitem, maxitems);
1629 plhs = TREALLOC(bucket *, plhs, maxrules);
1632 rprec = TREALLOC(Value_t, rprec, maxrules);
1635 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1639 /* set immediately prior to where copy_args() could be called, and incremented by
1640 the various routines that will rescan the argument list as appropriate */
1641 static int rescan_lineno;
1642 #if defined(YYBTYACC)
1645 copy_args(int *alen)
1647 struct mstring *s = msnew();
1648 int depth = 0, len = 1;
1650 int a_lineno = lineno;
1651 char *a_line = dup_line();
1652 char *a_cptr = a_line + (cptr - line - 1);
1654 while ((c = *cptr++) != R_PAREN || depth || quote)
1656 if (c == ',' && !quote && !depth)
1669 unterminated_string(a_lineno, a_line, a_cptr);
1671 unterminated_arglist(a_lineno, a_line, a_cptr);
1688 else if (c == R_PAREN)
1690 else if (c == '\"' || c == '\'')
1701 parse_id(char *p, char **save)
1708 if (!isalpha(*p) && *p != '_')
1711 while (isalnum(*p) || *p == '_' || *p == '$')
1715 *save = cache_tag(b, (size_t) (p - b));
1721 parse_int(char *p, int *save)
1723 int neg = 0, val = 0;
1736 val = val * 10 + *p++ - '0';
1745 parse_arginfo(bucket *a, char *args, int argslen)
1747 char *p = args, *tmp;
1752 if (a->args != argslen)
1753 arg_number_disagree_warning(rescan_lineno, a->name);
1758 if ((a->args = argslen) == 0)
1760 a->argnames = TMALLOC(char *, argslen);
1761 NO_SPACE(a->argnames);
1762 a->argtags = TMALLOC(char *, argslen);
1763 NO_SPACE(a->argtags);
1767 for (i = 0; i < argslen; i++)
1780 if (!(p = parse_id(p + 1, &tmp)))
1789 if (a->argtags[i] != tmp)
1790 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1793 a->argtags[i] = tmp;
1796 a->argtags[i] = NULL;
1797 if (!(p = parse_id(p, &a->argnames[i])))
1809 compile_arg(char **theptr, char *yyvaltag)
1812 struct mstring *c = msnew();
1814 Value_t *offsets = NULL, maxoffset;
1819 for (i = nitems - 1; pitem[i]; --i)
1822 if (pitem[i]->class != ARGUMENT)
1827 offsets = TMALLOC(Value_t, maxoffset + 1);
1830 for (j = 0, i++; i < nitems; i++)
1831 if (pitem[i]->class != ARGUMENT)
1832 offsets[++j] = (Value_t) (i - nitems + 1);
1834 rhs = pitem + nitems - 1;
1837 msprintf(c, "yyval.%s = ", yyvaltag);
1839 msprintf(c, "yyval = ");
1846 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1847 illegal_tag(rescan_lineno, NULL, NULL);
1848 if (isdigit(*p) || *p == '-')
1851 if (!(p = parse_int(p, &val)))
1852 dollar_error(rescan_lineno, NULL, NULL);
1855 else if (val > maxoffset)
1857 dollar_warning(rescan_lineno, val);
1858 i = val - maxoffset;
1860 else if (maxoffset > 0)
1863 if (!tag && !(tag = rhs[i]->tag) && havetags)
1864 untyped_rhs(val, rhs[i]->name);
1866 msprintf(c, "yystack.l_mark[%d]", i);
1868 msprintf(c, ".%s", tag);
1872 else if (isalpha(*p) || *p == '_')
1875 if (!(p = parse_id(p, &arg)))
1876 dollar_error(rescan_lineno, NULL, NULL);
1877 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1878 if (arg == plhs[nrules]->argnames[i])
1881 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1883 tag = plhs[nrules]->argtags[i];
1884 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1887 msprintf(c, ".%s", tag);
1889 untyped_arg_warning(rescan_lineno, "$", arg);
1892 dollar_error(rescan_lineno, NULL, NULL);
1896 at_error(rescan_lineno, NULL, NULL);
1911 #define ARG_CACHE_SIZE 1024
1912 static struct arg_cache
1914 struct arg_cache *next;
1918 *arg_cache[ARG_CACHE_SIZE];
1921 lookup_arg_cache(char *code)
1923 struct arg_cache *entry;
1925 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1928 if (!strnscmp(entry->code, code))
1930 entry = entry->next;
1936 insert_arg_cache(char *code, int rule)
1938 struct arg_cache *entry = NEW(struct arg_cache);
1942 i = strnshash(code) % ARG_CACHE_SIZE;
1945 entry->next = arg_cache[i];
1946 arg_cache[i] = entry;
1950 clean_arg_cache(void)
1952 struct arg_cache *e, *t;
1955 for (i = 0; i < ARG_CACHE_SIZE; i++)
1957 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1959 arg_cache[i] = NULL;
1965 advance_to_start(void)
1971 #if defined(YYBTYACC)
1996 syntax_error(lineno, line, s_cptr);
2001 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2002 syntax_error(lineno, line, cptr);
2006 if (bp->class == TERM)
2007 terminal_start(bp->name);
2015 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2016 #if defined(YYBTYACC)
2020 args = copy_args(&argslen);
2026 syntax_error(lineno, line, cptr);
2027 start_rule(bp, s_lineno);
2028 #if defined(YYBTYACC)
2029 parse_arginfo(bp, args, argslen);
2035 start_rule(bucket *bp, int s_lineno)
2037 if (bp->class == TERM)
2038 terminal_lhs(s_lineno);
2039 bp->class = NONTERM;
2042 if (nrules >= maxrules)
2045 rprec[nrules] = UNDEFINED;
2046 rassoc[nrules] = TOKEN;
2054 if (!last_was_action && plhs[nrules]->tag)
2056 if (pitem[nitems - 1])
2058 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2060 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2061 default_action_warning();
2065 default_action_warning();
2069 last_was_action = 0;
2070 if (nitems >= maxitems)
2078 insert_empty_rule(void)
2083 sprintf(cache, "$$%d", ++gensym);
2084 bp = make_bucket(cache);
2085 last_symbol->next = bp;
2087 bp->tag = plhs[nrules]->tag;
2089 #if defined(YYBTYACC)
2093 nitems = (Value_t) (nitems + 2);
2094 if (nitems > maxitems)
2096 bpp = pitem + nitems - 1;
2098 while ((bpp[0] = bpp[-1]) != 0)
2101 if (++nrules >= maxrules)
2103 plhs[nrules] = plhs[nrules - 1];
2104 plhs[nrules - 1] = bp;
2105 rprec[nrules] = rprec[nrules - 1];
2106 rprec[nrules - 1] = 0;
2107 rassoc[nrules] = rassoc[nrules - 1];
2108 rassoc[nrules - 1] = TOKEN;
2111 #if defined(YYBTYACC)
2113 insert_arg_rule(char *arg, char *tag)
2115 int line_number = rescan_lineno;
2116 char *code = compile_arg(&arg, tag);
2117 int rule = lookup_arg_cache(code);
2118 FILE *f = action_file;
2123 insert_arg_cache(code, rule);
2124 fprintf(f, "case %d:\n", rule - 2);
2126 fprintf(f, line_format, line_number, input_file_name);
2127 fprintf(f, "%s;\n", code);
2128 fprintf(f, "break;\n");
2129 insert_empty_rule();
2130 plhs[rule]->tag = tag;
2131 plhs[rule]->class = ARGUMENT;
2135 if (++nitems > maxitems)
2137 pitem[nitems - 1] = plhs[rule];
2149 int s_lineno = lineno;
2150 #if defined(YYBTYACC)
2156 if (c == '\'' || c == '"')
2162 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2163 #if defined(YYBTYACC)
2167 args = copy_args(&argslen);
2175 start_rule(bp, s_lineno);
2176 #if defined(YYBTYACC)
2177 parse_arginfo(bp, args, argslen);
2183 if (last_was_action)
2184 insert_empty_rule();
2185 last_was_action = 0;
2187 #if defined(YYBTYACC)
2190 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2193 if (plhs[nrules]->args != bp->args)
2194 wrong_number_args_warning("default ", bp->name);
2195 for (i = bp->args - 1; i >= 0; i--)
2196 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2197 wrong_type_for_arg_warning(i + 1, bp->name);
2199 else if (bp->args != argslen)
2200 wrong_number_args_warning("", bp->name);
2201 if (bp->args > 0 && argslen > 0)
2205 for (ap = args, i = 0; i < argslen; i++)
2206 ap = insert_arg_rule(ap, bp->argtags[i]);
2209 #endif /* defined(YYBTYACC) */
2211 if (++nitems > maxitems)
2213 pitem[nitems - 1] = bp;
2222 #if defined(YYBTYACC)
2223 int trialaction = 0;
2227 FILE *f = action_file;
2228 int a_lineno = lineno;
2229 char *a_line = dup_line();
2230 char *a_cptr = a_line + (cptr - line);
2231 Value_t *offsets = NULL, maxoffset;
2234 if (last_was_action)
2235 insert_empty_rule();
2236 last_was_action = 1;
2238 fprintf(f, "case %d:\n", nrules - 2);
2239 #if defined(YYBTYACC)
2242 if (*cptr != L_BRAC)
2243 fprintf(f, " if (!yytrial)\n");
2249 fprintf(f, line_format, lineno, input_file_name);
2253 /* avoid putting curly-braces in first column, to ease editing */
2254 if (*after_blanks(cptr) == L_CURL)
2257 cptr = after_blanks(cptr);
2262 for (i = nitems - 1; pitem[i]; --i)
2265 if (pitem[i]->class != ARGUMENT)
2270 offsets = TMALLOC(Value_t, maxoffset + 1);
2273 for (j = 0, i++; i < nitems; i++)
2275 if (pitem[i]->class != ARGUMENT)
2277 offsets[++j] = (Value_t) (i - nitems + 1);
2281 rhs = pitem + nitems - 1;
2290 int d_lineno = lineno;
2291 char *d_line = dup_line();
2292 char *d_cptr = d_line + (cptr - line);
2299 fprintf(f, "yyval.%s", tag);
2304 else if (isdigit(c))
2308 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2309 else if (i > maxoffset)
2311 dollar_warning(d_lineno, i);
2312 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2315 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2319 else if (c == '-' && isdigit(UCH(cptr[1])))
2322 i = -get_number() - n;
2323 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2327 #if defined(YYBTYACC)
2328 else if (isalpha(c) || c == '_')
2330 char *arg = scan_id();
2331 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2332 if (arg == plhs[nrules]->argnames[i])
2335 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2336 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2343 dollar_error(d_lineno, d_line, d_cptr);
2345 else if (cptr[1] == '$')
2349 tag = plhs[nrules]->tag;
2352 fprintf(f, "yyval.%s", tag);
2355 fprintf(f, "yyval");
2357 #if defined(YYBTYACC)
2362 else if (isdigit(UCH(cptr[1])))
2366 if (havetags && offsets)
2368 if (i <= 0 || i > maxoffset)
2370 tag = rhs[offsets[i]]->tag;
2372 untyped_rhs(i, rhs[offsets[i]]->name);
2373 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2378 fprintf(f, "yystack.l_mark[%d]", -n);
2379 else if (i > maxoffset)
2381 dollar_warning(lineno, i);
2382 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2385 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2389 else if (cptr[1] == '-')
2395 fprintf(f, "yystack.l_mark[%d]", -i - n);
2398 #if defined(YYBTYACC)
2399 else if (isalpha(cptr[1]) || cptr[1] == '_')
2404 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2405 if (arg == plhs[nrules]->argnames[i])
2408 unknown_arg_warning(lineno, "$", arg, line, cptr);
2409 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2410 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2412 fprintf(f, ".%s", tag);
2414 untyped_arg_warning(lineno, "$", arg);
2419 #if defined(YYBTYACC)
2424 int l_lineno = lineno;
2425 char *l_line = dup_line();
2426 char *l_cptr = l_line + (cptr - line);
2427 syntax_error(l_lineno, l_line, l_cptr);
2431 fprintf(f, "yyloc");
2435 else if (isdigit(UCH(cptr[1])))
2440 fprintf(f, "yystack.p_mark[%d]", -n);
2441 else if (i > maxoffset)
2443 at_warning(lineno, i);
2444 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2447 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2452 if (isalpha(c) || c == '_' || c == '$')
2459 while (isalnum(c) || c == '_' || c == '$');
2463 #if defined(YYBTYACC)
2466 if (trialaction && c == L_BRAC && depth == 0)
2472 if (trialaction && c == R_BRAC && depth == 1)
2477 if (c == L_BRAC && !haveyyval)
2481 if (c == L_CURL && !haveyyval)
2483 fprintf(f, " if (!yytrial)\n");
2485 fprintf(f, line_format, lineno, input_file_name);
2489 fprintf(f, "\nbreak;\n");
2504 unterminated_action(a_lineno, a_line, a_cptr);
2509 fprintf(f, "\nbreak;\n");
2515 #if defined(YYBTYACC)
2534 #if defined(YYBTYACC)
2538 if (c == L_BRAC && !haveyyval)
2543 if (c == L_CURL && !haveyyval)
2545 fprintf(f, " if (!yytrial)\n");
2547 fprintf(f, line_format, lineno, input_file_name);
2552 fprintf(f, "\nbreak;\n");
2561 char *s = copy_string(c);
2569 char *s = copy_comment();
2580 #if defined(YYBTYACC)
2582 copy_destructor(void)
2588 struct mstring *destructor_text = msnew();
2595 msprintf(destructor_text, line_format, lineno, input_file_name);
2597 cptr = after_blanks(cptr);
2598 if (*cptr == L_CURL)
2599 /* avoid putting curly-braces in first column, to ease editing */
2600 mputc(destructor_text, '\t');
2602 syntax_error(lineno, line, cptr);
2605 a_line = dup_line();
2606 a_cptr = a_line + (cptr - line);
2615 int d_lineno = lineno;
2616 char *d_line = dup_line();
2617 char *d_cptr = d_line + (cptr - line);
2624 msprintf(destructor_text, "(*val).%s", tag);
2630 dollar_error(d_lineno, d_line, d_cptr);
2632 else if (cptr[1] == '$')
2634 /* process '$$' later; replacement is context dependent */
2635 msprintf(destructor_text, "$$");
2640 if (c == '@' && cptr[1] == '$')
2644 int l_lineno = lineno;
2645 char *l_line = dup_line();
2646 char *l_cptr = l_line + (cptr - line);
2647 syntax_error(l_lineno, l_line, l_cptr);
2649 msprintf(destructor_text, "(*loc)");
2653 if (isalpha(c) || c == '_' || c == '$')
2657 mputc(destructor_text, c);
2660 while (isalnum(c) || c == '_' || c == '$');
2664 mputc(destructor_text, c);
2671 unterminated_action(a_lineno, a_line, a_cptr);
2680 goto process_symbols;
2685 char *s = copy_string(c);
2686 msprintf(destructor_text, "%s", s);
2693 char *s = copy_comment();
2694 msprintf(destructor_text, "%s", s);
2703 code_text = msdone(destructor_text);
2712 { /* "no semantic type" default destructor */
2714 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2716 static char untyped_default[] = "<>";
2717 bp = make_bucket("untyped default");
2718 bp->tag = untyped_default;
2719 default_destructor[UNTYPED_DEFAULT] = bp;
2721 if (bp->destructor != NULL)
2722 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2724 /* replace "$$" with "(*val)" in destructor code */
2725 bp->destructor = process_destructor_XX(code_text, NULL);
2727 else if (cptr[1] == '*' && cptr[2] == '>')
2728 { /* "no per-symbol or per-type" default destructor */
2730 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2732 static char typed_default[] = "<*>";
2733 bp = make_bucket("typed default");
2734 bp->tag = typed_default;
2735 default_destructor[TYPED_DEFAULT] = bp;
2737 if (bp->destructor != NULL)
2738 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2741 /* postpone re-processing destructor $$s until end of grammar spec */
2742 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2743 NO_SPACE(bp->destructor);
2744 strcpy(bp->destructor, code_text);
2748 { /* "semantic type" default destructor */
2750 bp = lookup_type_destructor(tag);
2751 if (bp->destructor != NULL)
2752 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2754 /* replace "$$" with "(*val).tag" in destructor code */
2755 bp->destructor = process_destructor_XX(code_text, tag);
2758 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2759 { /* "symbol" destructor */
2761 if (bp->destructor != NULL)
2762 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2765 /* postpone re-processing destructor $$s until end of grammar spec */
2766 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2767 NO_SPACE(bp->destructor);
2768 strcpy(bp->destructor, code_text);
2779 process_destructor_XX(char *code, char *tag)
2784 struct mstring *new_code = msnew();
2785 char *codeptr = code;
2788 loop: /* step thru code */
2790 if (c == '$' && codeptr[1] == '$')
2794 msprintf(new_code, "(*val)");
2796 msprintf(new_code, "(*val).%s", tag);
2799 if (isalpha(c) || c == '_' || c == '$')
2806 while (isalnum(c) || c == '_' || c == '$');
2820 return msdone(new_code);
2848 if (c == '*' && *codeptr == '/')
2850 mputc(new_code, '/');
2862 #endif /* defined(YYBTYACC) */
2871 if (c == '%' || c == '\\')
2879 else if ((c == 'p' || c == 'P') &&
2880 ((c = cptr[2]) == 'r' || c == 'R') &&
2881 ((c = cptr[3]) == 'e' || c == 'E') &&
2882 ((c = cptr[4]) == 'c' || c == 'C') &&
2883 ((c = cptr[5], !IS_IDENT(c))))
2886 syntax_error(lineno, line, cptr);
2889 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2891 else if (c == '\'' || c == '"')
2895 syntax_error(lineno, line, cptr);
2898 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2901 rprec[nrules] = bp->prec;
2902 rassoc[nrules] = bp->assoc;
2911 initialize_grammar();
2926 #if defined(YYBTYACC)
2927 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2929 else if (c == L_CURL || c == '=')
2935 start_rule(plhs[nrules - 1], 0);
2944 syntax_error(lineno, line, cptr);
2947 #if defined(YYBTYACC)
2949 start_requires_args(goal->name);
2961 for (i = 0; i < ntags; ++i)
2963 assert(tag_table[i]);
2975 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2976 for (bp = first_symbol; bp; bp = bp->next)
2977 name_pool_size += strlen(bp->name) + 1;
2979 name_pool = TMALLOC(char, name_pool_size);
2980 NO_SPACE(name_pool);
2982 strcpy(name_pool, "$accept");
2983 strcpy(name_pool + 8, "$end");
2985 for (bp = first_symbol; bp; bp = bp->next)
2989 while ((*t++ = *s++) != 0)
3001 if (goal->class == UNKNOWN)
3002 undefined_goal(goal->name);
3004 for (bp = first_symbol; bp; bp = bp->next)
3006 if (bp->class == UNKNOWN)
3008 undefined_symbol_warning(bp->name);
3015 protect_string(char *src, char **des)
3028 if ('\\' == *s || '"' == *s)
3034 *des = d = TMALLOC(char, len);
3040 if ('\\' == *s || '"' == *s)
3054 #if defined(YYBTYACC)
3055 Value_t max_tok_pval;
3060 for (bp = first_symbol; bp; bp = bp->next)
3063 if (bp->class == TERM)
3066 start_symbol = (Value_t) ntokens;
3067 nvars = (Value_t) (nsyms - ntokens);
3069 symbol_name = TMALLOC(char *, nsyms);
3070 NO_SPACE(symbol_name);
3072 symbol_value = TMALLOC(Value_t, nsyms);
3073 NO_SPACE(symbol_value);
3075 symbol_prec = TMALLOC(Value_t, nsyms);
3076 NO_SPACE(symbol_prec);
3078 symbol_assoc = TMALLOC(char, nsyms);
3079 NO_SPACE(symbol_assoc);
3081 #if defined(YYBTYACC)
3082 symbol_pval = TMALLOC(Value_t, nsyms);
3083 NO_SPACE(symbol_pval);
3087 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3088 NO_SPACE(symbol_destructor);
3090 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3091 NO_SPACE(symbol_type_tag);
3095 v = TMALLOC(bucket *, nsyms);
3099 v[start_symbol] = 0;
3102 j = (Value_t) (start_symbol + 1);
3103 for (bp = first_symbol; bp; bp = bp->next)
3105 if (bp->class == TERM)
3110 assert(i == ntokens && j == nsyms);
3112 for (i = 1; i < ntokens; ++i)
3115 goal->index = (Index_t) (start_symbol + 1);
3116 k = (Value_t) (start_symbol + 2);
3126 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3136 for (i = 1; i < ntokens; ++i)
3141 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3142 symbol_value[j] = symbol_value[j - 1];
3143 symbol_value[j] = n;
3149 if (v[1]->value == UNDEFINED)
3154 for (i = 2; i < ntokens; ++i)
3156 if (v[i]->value == UNDEFINED)
3158 while (j < k && n == symbol_value[j])
3160 while (++j < k && n == symbol_value[j])
3169 symbol_name[0] = name_pool + 8;
3170 symbol_value[0] = 0;
3172 symbol_assoc[0] = TOKEN;
3173 #if defined(YYBTYACC)
3177 for (i = 1; i < ntokens; ++i)
3179 symbol_name[i] = v[i]->name;
3180 symbol_value[i] = v[i]->value;
3181 symbol_prec[i] = v[i]->prec;
3182 symbol_assoc[i] = v[i]->assoc;
3183 #if defined(YYBTYACC)
3184 symbol_pval[i] = v[i]->value;
3185 if (symbol_pval[i] > max_tok_pval)
3186 max_tok_pval = symbol_pval[i];
3189 symbol_destructor[i] = v[i]->destructor;
3190 symbol_type_tag[i] = v[i]->tag;
3194 symbol_name[start_symbol] = name_pool;
3195 symbol_value[start_symbol] = -1;
3196 symbol_prec[start_symbol] = 0;
3197 symbol_assoc[start_symbol] = TOKEN;
3198 #if defined(YYBTYACC)
3199 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3201 for (++i; i < nsyms; ++i)
3204 symbol_name[k] = v[i]->name;
3205 symbol_value[k] = v[i]->value;
3206 symbol_prec[k] = v[i]->prec;
3207 symbol_assoc[k] = v[i]->assoc;
3208 #if defined(YYBTYACC)
3209 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3212 symbol_destructor[k] = v[i]->destructor;
3213 symbol_type_tag[k] = v[i]->tag;
3220 symbol_pname = TMALLOC(char *, nsyms);
3221 NO_SPACE(symbol_pname);
3223 for (i = 0; i < nsyms; ++i)
3224 protect_string(symbol_name[i], &(symbol_pname[i]));
3238 ritem = TMALLOC(Value_t, nitems);
3241 rlhs = TMALLOC(Value_t, nrules);
3244 rrhs = TMALLOC(Value_t, nrules + 1);
3247 rprec = TREALLOC(Value_t, rprec, nrules);
3250 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3254 ritem[1] = goal->index;
3259 rlhs[2] = start_symbol;
3265 for (i = 3; i < nrules; ++i)
3267 #if defined(YYBTYACC)
3268 if (plhs[i]->args > 0)
3270 if (plhs[i]->argnames)
3272 FREE(plhs[i]->argnames);
3273 plhs[i]->argnames = NULL;
3275 if (plhs[i]->argtags)
3277 FREE(plhs[i]->argtags);
3278 plhs[i]->argtags = NULL;
3281 #endif /* defined(YYBTYACC) */
3282 rlhs[i] = plhs[i]->index;
3288 ritem[j] = pitem[j]->index;
3289 if (pitem[j]->class == TERM)
3291 prec2 = pitem[j]->prec;
3292 assoc = pitem[j]->assoc;
3296 ritem[j] = (Value_t) - i;
3298 if (rprec[i] == UNDEFINED)
3308 #if defined(YYBTYACC)
3317 size_t j, spacing = 0;
3318 FILE *f = verbose_file;
3324 for (i = 2; i < nrules; ++i)
3326 if (rlhs[i] != rlhs[i - 1])
3330 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3331 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3335 fprintf(f, "%4d ", i - 2);
3342 while (ritem[k] >= 0)
3344 fprintf(f, " %s", symbol_name[ritem[k]]);
3352 #if defined(YYBTYACC)
3354 finalize_destructors(void)
3360 for (i = 2; i < nsyms; ++i)
3362 tag = symbol_type_tag[i];
3363 if (symbol_destructor[i] == NULL)
3366 { /* use <> destructor, if there is one */
3367 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3369 symbol_destructor[i] = TMALLOC(char,
3370 strlen(bp->destructor) + 1);
3371 NO_SPACE(symbol_destructor[i]);
3372 strcpy(symbol_destructor[i], bp->destructor);
3376 { /* use type destructor for this tag, if there is one */
3377 bp = lookup_type_destructor(tag);
3378 if (bp->destructor != NULL)
3380 symbol_destructor[i] = TMALLOC(char,
3381 strlen(bp->destructor) + 1);
3382 NO_SPACE(symbol_destructor[i]);
3383 strcpy(symbol_destructor[i], bp->destructor);
3386 { /* use <*> destructor, if there is one */
3387 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3388 /* replace "$$" with "(*val).tag" in destructor code */
3389 symbol_destructor[i]
3390 = process_destructor_XX(bp->destructor, tag);
3395 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3396 symbol_destructor[i]
3397 = process_destructor_XX(symbol_destructor[i], tag);
3400 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3401 DO_FREE(symbol_type_tag); /* no longer needed */
3402 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3405 /* 'bp->tag' is a static value, don't free */
3406 FREE(bp->destructor);
3409 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3412 /* 'bp->tag' is a static value, don't free */
3413 FREE(bp->destructor);
3416 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3423 /* 'bp->tag' freed by 'free_tags()' */
3424 FREE(bp->destructor);
3429 #endif /* defined(YYBTYACC) */
3434 write_section(code_file, banner);
3435 create_symbol_table();
3436 read_declarations();
3438 free_symbol_table();
3445 #if defined(YYBTYACC)
3447 finalize_destructors();
3454 free_declarations(param * list)
3458 param *next = list->next;
3471 lex_param = free_declarations(lex_param);
3472 parse_param = free_declarations(parse_param);
3482 DO_FREE(symbol_name);
3483 DO_FREE(symbol_prec);
3484 DO_FREE(symbol_assoc);
3485 DO_FREE(symbol_value);
3486 #if defined(YYBTYACC)
3487 DO_FREE(symbol_pval);
3488 DO_FREE(symbol_destructor);
3489 DO_FREE(symbol_type_tag);