summaryrefslogtreecommitdiffstats
path: root/contrib/byacc/reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/byacc/reader.c')
-rw-r--r--contrib/byacc/reader.c1698
1 files changed, 1376 insertions, 322 deletions
diff --git a/contrib/byacc/reader.c b/contrib/byacc/reader.c
index 6b24d7d..8312a69 100644
--- a/contrib/byacc/reader.c
+++ b/contrib/byacc/reader.c
@@ -1,4 +1,4 @@
-/* $Id: reader.c,v 1.36 2012/05/26 16:05:41 tom Exp $ */
+/* $Id: reader.c,v 1.47 2014/04/09 21:09:27 tom Exp $ */
#include "defs.h"
@@ -9,16 +9,28 @@
#define LINESIZE 100
-#define L_CURL '{'
-#define R_CURL '}'
+#define L_CURL '{'
+#define R_CURL '}'
+#define L_PAREN '('
+#define R_PAREN ')'
+#define L_BRAC '['
+#define R_BRAC ']'
+
+/* the maximum number of arguments (inherited attributes) to a non-terminal */
+/* this is a hard limit, but seems more than adequate */
+#define MAXARGS 20
static void start_rule(bucket *bp, int s_lineno);
+#if defined(YYBTYACC)
+static void copy_destructor(void);
+static char *process_destructor_XX(char *code, char *tag);
+#endif
static char *cache;
static int cinc, cache_size;
int ntags;
-static int tagmax;
+static int tagmax, havetags;
static char **tag_table;
static char saw_eof;
@@ -45,6 +57,36 @@ char line_format[] = "#line %d \"%s\"\n";
param *lex_param;
param *parse_param;
+#if defined(YYBTYACC)
+int destructor = 0; /* =1 if at least one %destructor */
+
+static bucket *default_destructor[3] =
+{0, 0, 0};
+
+#define UNTYPED_DEFAULT 0
+#define TYPED_DEFAULT 1
+#define TYPE_SPECIFIED 2
+
+static bucket *
+lookup_type_destructor(char *tag)
+{
+ char name[1024] = "\0";
+ bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
+
+ while ((bp = *bpp) != NULL)
+ {
+ if (bp->tag == tag)
+ return (bp);
+ bpp = &bp->link;
+ }
+
+ *bpp = bp = make_bucket(strcat(strcpy(name, tag), " destructor"));
+ bp->tag = tag;
+
+ return (bp);
+}
+#endif /* defined(YYBTYACC) */
+
static void
cachec(int c)
{
@@ -93,10 +135,7 @@ get_line(void)
{
line[i] = (char)c;
if (c == '\n')
- {
- cptr = line;
- return;
- }
+ break;
if (++i >= linesize)
{
linesize += LINESIZE;
@@ -108,10 +147,11 @@ get_line(void)
{
line[i] = '\n';
saw_eof = 1;
- cptr = line;
- return;
+ break;
}
}
+ cptr = line;
+ return;
}
static char *
@@ -226,35 +266,45 @@ nextc(void)
}
}
}
+/* *INDENT-OFF* */
+static struct keyword
+{
+ char name[13];
+ int token;
+}
+keywords[] = {
+ { "binary", NONASSOC },
+#if defined(YYBTYACC)
+ { "destructor", DESTRUCTOR },
+#endif
+ { "expect", EXPECT },
+ { "expect-rr", EXPECT_RR },
+ { "ident", IDENT },
+ { "left", LEFT },
+ { "lex-param", LEX_PARAM },
+#if defined(YYBTYACC)
+ { "locations", LOCATIONS },
+#endif
+ { "nonassoc", NONASSOC },
+ { "parse-param", PARSE_PARAM },
+ { "pure-parser", PURE_PARSER },
+ { "right", RIGHT },
+ { "start", START },
+ { "term", TOKEN },
+ { "token", TOKEN },
+ { "token-table", TOKEN_TABLE },
+ { "type", TYPE },
+ { "union", UNION },
+ { "yacc", POSIX_YACC },
+};
+/* *INDENT-ON* */
-/*
- * Compare keyword to cached token, treating '_' and '-' the same. Some
- * grammars rely upon this misfeature.
- */
static int
-matchec(const char *name)
+compare_keys(const void *a, const void *b)
{
- const char *p = cache;
- const char *q = name;
- int code = 0; /* assume mismatch */
-
- while (*p != '\0' && *q != '\0')
- {
- char a = *p++;
- char b = *q++;
- if (a == '_')
- a = '-';
- if (b == '_')
- b = '-';
- if (a != b)
- break;
- if (*p == '\0' && *q == '\0')
- {
- code = 1;
- break;
- }
- }
- return code;
+ const struct keyword *p = (const struct keyword *)a;
+ const struct keyword *q = (const struct keyword *)b;
+ return strcmp(p->name, q->name);
}
static int
@@ -262,6 +312,7 @@ keyword(void)
{
int c;
char *t_cptr = cptr;
+ struct keyword *key;
c = *++cptr;
if (isalpha(c))
@@ -277,12 +328,16 @@ keyword(void)
}
else if (isdigit(c)
|| c == '-'
- || c == '_'
|| c == '.'
|| c == '$')
{
cachec(c);
}
+ else if (c == '_')
+ {
+ /* treat keywords spelled with '_' as if it were '-' */
+ cachec('-');
+ }
else
{
break;
@@ -291,34 +346,10 @@ keyword(void)
}
cachec(NUL);
- if (matchec("token") || matchec("term"))
- return (TOKEN);
- if (matchec("type"))
- return (TYPE);
- if (matchec("left"))
- return (LEFT);
- if (matchec("right"))
- return (RIGHT);
- if (matchec("nonassoc") || matchec("binary"))
- return (NONASSOC);
- if (matchec("start"))
- return (START);
- if (matchec("union"))
- return (UNION);
- if (matchec("ident"))
- return (IDENT);
- if (matchec("expect"))
- return (EXPECT);
- if (matchec("expect-rr"))
- return (EXPECT_RR);
- if (matchec("pure-parser"))
- return (PURE_PARSER);
- if (matchec("parse-param"))
- return (PARSE_PARAM);
- if (matchec("lex-param"))
- return (LEX_PARAM);
- if (matchec("yacc"))
- return (POSIX_YACC);
+ if ((key = bsearch(cache, keywords,
+ sizeof(keywords) / sizeof(*key),
+ sizeof(*key), compare_keys)))
+ return key->token;
}
else
{
@@ -337,7 +368,6 @@ keyword(void)
return (NONASSOC);
}
syntax_error(lineno, line, t_cptr);
- /*NOTREACHED */
return (-1);
}
@@ -372,11 +402,93 @@ copy_ident(void)
}
}
+static char *
+copy_string(int quote)
+{
+ struct mstring *temp = msnew();
+ int c;
+ int s_lineno = lineno;
+ char *s_line = dup_line();
+ char *s_cptr = s_line + (cptr - line - 1);
+
+ for (;;)
+ {
+ c = *cptr++;
+ mputc(temp, c);
+ if (c == quote)
+ {
+ FREE(s_line);
+ return msdone(temp);
+ }
+ if (c == '\n')
+ unterminated_string(s_lineno, s_line, s_cptr);
+ if (c == '\\')
+ {
+ c = *cptr++;
+ mputc(temp, c);
+ if (c == '\n')
+ {
+ get_line();
+ if (line == 0)
+ unterminated_string(s_lineno, s_line, s_cptr);
+ }
+ }
+ }
+}
+
+static char *
+copy_comment(void)
+{
+ struct mstring *temp = msnew();
+ int c;
+
+ c = *cptr;
+ if (c == '/')
+ {
+ mputc(temp, '*');
+ while ((c = *++cptr) != '\n')
+ {
+ mputc(temp, c);
+ if (c == '*' && cptr[1] == '/')
+ mputc(temp, ' ');
+ }
+ mputc(temp, '*');
+ mputc(temp, '/');
+ }
+ else if (c == '*')
+ {
+ int c_lineno = lineno;
+ char *c_line = dup_line();
+ char *c_cptr = c_line + (cptr - line - 1);
+
+ mputc(temp, c);
+ ++cptr;
+ for (;;)
+ {
+ c = *cptr++;
+ mputc(temp, c);
+ if (c == '*' && *cptr == '/')
+ {
+ mputc(temp, '/');
+ ++cptr;
+ FREE(c_line);
+ return msdone(temp);
+ }
+ if (c == '\n')
+ {
+ get_line();
+ if (line == 0)
+ unterminated_comment(c_lineno, c_line, c_cptr);
+ }
+ }
+ }
+ return msdone(temp);
+}
+
static void
copy_text(void)
{
int c;
- int quote;
FILE *f = text_file;
int need_newline = 0;
int t_lineno = lineno;
@@ -397,7 +509,6 @@ copy_text(void)
switch (c)
{
case '\n':
- next_line:
putc('\n', f);
need_newline = 0;
get_line();
@@ -407,82 +518,21 @@ copy_text(void)
case '\'':
case '"':
+ putc(c, f);
{
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
-
- quote = c;
- putc(c, f);
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == quote)
- {
- need_newline = 1;
- FREE(s_line);
- goto loop;
- }
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
- {
- c = *cptr++;
- putc(c, f);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
- }
- }
+ char *s = copy_string(c);
+ fputs(s, f);
+ free(s);
}
+ need_newline = 1;
+ goto loop;
case '/':
putc(c, f);
- need_newline = 1;
- c = *cptr;
- if (c == '/')
- {
- putc('*', f);
- while ((c = *++cptr) != '\n')
- {
- if (c == '*' && cptr[1] == '/')
- fprintf(f, "* ");
- else
- putc(c, f);
- }
- fprintf(f, "*/");
- goto next_line;
- }
- if (c == '*')
{
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
-
- putc('*', f);
- ++cptr;
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == '*' && *cptr == '/')
- {
- putc('/', f);
- ++cptr;
- FREE(c_line);
- goto loop;
- }
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
- }
+ char *s = copy_comment();
+ fputs(s, f);
+ free(s);
}
need_newline = 1;
goto loop;
@@ -526,7 +576,6 @@ static void
copy_union(void)
{
int c;
- int quote;
int depth;
int u_lineno = lineno;
char *u_line = dup_line();
@@ -554,7 +603,6 @@ copy_union(void)
switch (c)
{
case '\n':
- next_line:
get_line();
if (line == 0)
unterminated_union(u_lineno, u_line, u_cptr);
@@ -577,81 +625,17 @@ copy_union(void)
case '\'':
case '"':
{
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
-
- quote = c;
- for (;;)
- {
- c = *cptr++;
- putc_both(c);
- if (c == quote)
- {
- FREE(s_line);
- goto loop;
- }
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
- {
- c = *cptr++;
- putc_both(c);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
- }
- }
+ char *s = copy_string(c);
+ puts_both(s);
+ free(s);
}
+ goto loop;
case '/':
- c = *cptr;
- if (c == '/')
{
- putc_both('*');
- while ((c = *++cptr) != '\n')
- {
- if (c == '*' && cptr[1] == '/')
- {
- puts_both("* ");
- }
- else
- {
- putc_both(c);
- }
- }
- puts_both("*/\n");
- goto next_line;
- }
- if (c == '*')
- {
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
-
- putc_both('*');
- ++cptr;
- for (;;)
- {
- c = *cptr++;
- putc_both(c);
- if (c == '*' && *cptr == '/')
- {
- putc_both('/');
- ++cptr;
- FREE(c_line);
- goto loop;
- }
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
- }
+ char *s = copy_comment();
+ puts_both(s);
+ free(s);
}
goto loop;
@@ -675,20 +659,20 @@ copy_param(int k)
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (c != '{')
+ if (c != L_CURL)
goto out;
cptr++;
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (c == '}')
+ if (c == R_CURL)
goto out;
buf = TMALLOC(char, linesize);
NO_SPACE(buf);
- for (i = 0; (c = *cptr++) != '}'; i++)
+ for (i = 0; (c = *cptr++) != R_CURL; i++)
{
if (c == '\0')
missing_brace();
@@ -701,7 +685,7 @@ copy_param(int k)
goto out;
buf[i--] = '\0';
- while (i >= 0 && isspace(UCH(buf[i])))
+ while (i > 0 && isspace(UCH(buf[i])))
buf[i--] = '\0';
if (buf[i] == ']')
@@ -724,8 +708,8 @@ copy_param(int k)
type2 = i + 1;
}
- while (i >= 0 && (isalnum(UCH(buf[i])) ||
- UCH(buf[i]) == '_'))
+ while (i > 0 && (isalnum(UCH(buf[i])) ||
+ UCH(buf[i]) == '_'))
i--;
if (!isspace(UCH(buf[i])) && buf[i] != '*')
@@ -1014,11 +998,41 @@ get_number(void)
}
static char *
-get_tag(void)
+cache_tag(char *tag, size_t len)
{
- int c;
int i;
char *s;
+
+ for (i = 0; i < ntags; ++i)
+ {
+ if (strncmp(tag, tag_table[i], len) == 0 &&
+ tag_table[i][len] == NUL)
+ return (tag_table[i]);
+ }
+
+ if (ntags >= tagmax)
+ {
+ tagmax += 16;
+ tag_table =
+ (tag_table
+ ? TREALLOC(char *, tag_table, tagmax)
+ : TMALLOC(char *, tagmax));
+ NO_SPACE(tag_table);
+ }
+
+ s = TMALLOC(char, len + 1);
+ NO_SPACE(s);
+
+ strncpy(s, tag, len);
+ s[len] = 0;
+ tag_table[ntags++] = s;
+ return s;
+}
+
+static char *
+get_tag(void)
+{
+ int c;
int t_lineno = lineno;
char *t_line = dup_line();
char *t_cptr = t_line + (cptr - line);
@@ -1046,34 +1060,22 @@ get_tag(void)
illegal_tag(t_lineno, t_line, t_cptr);
++cptr;
- for (i = 0; i < ntags; ++i)
- {
- if (strcmp(cache, tag_table[i]) == 0)
- {
- FREE(t_line);
- return (tag_table[i]);
- }
- }
-
- if (ntags >= tagmax)
- {
- tagmax += 16;
- tag_table =
- (tag_table
- ? TREALLOC(char *, tag_table, tagmax)
- : TMALLOC(char *, tagmax));
- NO_SPACE(tag_table);
- }
+ FREE(t_line);
+ havetags = 1;
+ return cache_tag(cache, (size_t) cinc);
+}
- s = TMALLOC(char, cinc);
- NO_SPACE(s);
+#if defined(YYBTYACC)
+static char *
+scan_id(void)
+{
+ char *b = cptr;
- strcpy(s, cache);
- tag_table[ntags] = s;
- ++ntags;
- FREE(t_line);
- return (s);
+ while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
+ cptr++;
+ return cache_tag(b, (size_t) (cptr - b));
}
+#endif
static void
declare_tokens(int assoc)
@@ -1191,33 +1193,88 @@ declare_expect(int assoc)
}
}
+#if defined(YYBTYACC)
+static void
+declare_argtypes(bucket *bp)
+{
+ char *tags[MAXARGS];
+ int args = 0, c;
+
+ if (bp->args >= 0)
+ retyped_warning(bp->name);
+ cptr++; /* skip open paren */
+ for (;;)
+ {
+ c = nextc();
+ if (c == EOF)
+ unexpected_EOF();
+ if (c != '<')
+ syntax_error(lineno, line, cptr);
+ tags[args++] = get_tag();
+ c = nextc();
+ if (c == R_PAREN)
+ break;
+ if (c == EOF)
+ unexpected_EOF();
+ }
+ cptr++; /* skip close paren */
+ bp->args = args;
+ bp->argnames = TMALLOC(char *, args);
+ NO_SPACE(bp->argnames);
+ bp->argtags = CALLOC(sizeof(char *), args + 1);
+ NO_SPACE(bp->argtags);
+ while (--args >= 0)
+ {
+ bp->argtags[args] = tags[args];
+ bp->argnames[args] = NULL;
+ }
+}
+#endif
+
static void
declare_types(void)
{
int c;
bucket *bp;
- char *tag;
+ char *tag = NULL;
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (c != '<')
- syntax_error(lineno, line, cptr);
- tag = get_tag();
+ if (c == '<')
+ tag = get_tag();
for (;;)
{
c = nextc();
+ if (c == EOF)
+ unexpected_EOF();
if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ {
bp = get_name();
+#if defined(YYBTYACC)
+ if (nextc() == L_PAREN)
+ declare_argtypes(bp);
+ else
+ bp->args = 0;
+#endif
+ }
else if (c == '\'' || c == '"')
+ {
bp = get_literal();
+#if defined(YYBTYACC)
+ bp->args = 0;
+#endif
+ }
else
return;
- if (bp->tag && tag != bp->tag)
- retyped_warning(bp->name);
- bp->tag = tag;
+ if (tag)
+ {
+ if (bp->tag && tag != bp->tag)
+ retyped_warning(bp->name);
+ bp->tag = tag;
+ }
}
}
@@ -1302,6 +1359,21 @@ read_declarations(void)
copy_param(k);
break;
+ case TOKEN_TABLE:
+ token_table = 1;
+ break;
+
+#if defined(YYBTYACC)
+ case LOCATIONS:
+ locations = 1;
+ break;
+
+ case DESTRUCTOR:
+ destructor = 1;
+ copy_destructor();
+ break;
+#endif
+
case POSIX_YACC:
/* noop for bison compatibility. byacc is already designed to be posix
* yacc compatible. */
@@ -1372,6 +1444,330 @@ expand_rules(void)
NO_SPACE(rassoc);
}
+/* set immediately prior to where copy_args() could be called, and incremented by
+ the various routines that will rescan the argument list as appropriate */
+static int rescan_lineno;
+#if defined(YYBTYACC)
+
+static char *
+copy_args(int *alen)
+{
+ struct mstring *s = msnew();
+ int depth = 0, len = 1;
+ char c, quote = 0;
+ int a_lineno = lineno;
+ char *a_line = dup_line();
+ char *a_cptr = a_line + (cptr - line - 1);
+
+ while ((c = *cptr++) != R_PAREN || depth || quote)
+ {
+ if (c == ',' && !quote && !depth)
+ {
+ len++;
+ mputc(s, 0);
+ continue;
+ }
+ mputc(s, c);
+ if (c == '\n')
+ {
+ get_line();
+ if (!line)
+ {
+ if (quote)
+ unterminated_string(a_lineno, a_line, a_cptr);
+ else
+ unterminated_arglist(a_lineno, a_line, a_cptr);
+ }
+ }
+ else if (quote)
+ {
+ if (c == quote)
+ quote = 0;
+ else if (c == '\\')
+ {
+ if (*cptr != '\n')
+ mputc(s, *cptr++);
+ }
+ }
+ else
+ {
+ if (c == L_PAREN)
+ depth++;
+ else if (c == R_PAREN)
+ depth--;
+ else if (c == '\"' || c == '\'')
+ quote = c;
+ }
+ }
+ if (alen)
+ *alen = len;
+ FREE(a_line);
+ return msdone(s);
+}
+
+static char *
+parse_id(char *p, char **save)
+{
+ char *b;
+
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (!isalpha(*p) && *p != '_')
+ return NULL;
+ b = p;
+ while (isalnum(*p) || *p == '_' || *p == '$')
+ p++;
+ if (save)
+ {
+ *save = cache_tag(b, (size_t) (p - b));
+ }
+ return p;
+}
+
+static char *
+parse_int(char *p, int *save)
+{
+ int neg = 0, val = 0;
+
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (*p == '-')
+ {
+ neg = 1;
+ p++;
+ }
+ if (!isdigit(*p))
+ return NULL;
+ while (isdigit(*p))
+ val = val * 10 + *p++ - '0';
+ if (neg)
+ val = -val;
+ if (save)
+ *save = val;
+ return p;
+}
+
+static void
+parse_arginfo(bucket *a, char *args, int argslen)
+{
+ char *p = args, *tmp;
+ int i, redec = 0;
+
+ if (a->args > 0)
+ {
+ if (a->args != argslen)
+ arg_number_disagree_warning(rescan_lineno, a->name);
+ redec = 1;
+ }
+ else
+ {
+ if ((a->args = argslen) == 0)
+ return;
+ a->argnames = TMALLOC(char *, argslen);
+ NO_SPACE(a->argnames);
+ a->argtags = TMALLOC(char *, argslen);
+ NO_SPACE(a->argtags);
+ }
+ if (!args)
+ return;
+ for (i = 0; i < argslen; i++)
+ {
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (*p++ != '$')
+ bad_formals();
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (*p == '<')
+ {
+ havetags = 1;
+ if (!(p = parse_id(p + 1, &tmp)))
+ bad_formals();
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (*p++ != '>')
+ bad_formals();
+ if (redec)
+ {
+ if (a->argtags[i] != tmp)
+ arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
+ }
+ else
+ a->argtags[i] = tmp;
+ }
+ else if (!redec)
+ a->argtags[i] = NULL;
+ if (!(p = parse_id(p, &a->argnames[i])))
+ bad_formals();
+ while (isspace(*p))
+ if (*p++ == '\n')
+ rescan_lineno++;
+ if (*p++)
+ bad_formals();
+ }
+ free(args);
+}
+
+static char *
+compile_arg(char **theptr, char *yyvaltag)
+{
+ char *p = *theptr;
+ struct mstring *c = msnew();
+ int i, j, n;
+ Value_t *offsets = NULL, maxoffset;
+ bucket **rhs;
+
+ maxoffset = 0;
+ n = 0;
+ for (i = nitems - 1; pitem[i]; --i)
+ {
+ n++;
+ if (pitem[i]->class != ARGUMENT)
+ maxoffset++;
+ }
+ if (maxoffset > 0)
+ {
+ offsets = TMALLOC(Value_t, maxoffset + 1);
+ NO_SPACE(offsets);
+ }
+ for (j = 0, i++; i < nitems; i++)
+ if (pitem[i]->class != ARGUMENT)
+ offsets[++j] = (Value_t) (i - nitems + 1);
+ rhs = pitem + nitems - 1;
+
+ if (yyvaltag)
+ msprintf(c, "yyval.%s = ", yyvaltag);
+ else
+ msprintf(c, "yyval = ");
+ while (*p)
+ {
+ if (*p == '$')
+ {
+ char *tag = NULL;
+ if (*++p == '<')
+ if (!(p = parse_id(++p, &tag)) || *p++ != '>')
+ illegal_tag(rescan_lineno, NULL, NULL);
+ if (isdigit(*p) || *p == '-')
+ {
+ int val;
+ if (!(p = parse_int(p, &val)))
+ dollar_error(rescan_lineno, NULL, NULL);
+ if (val <= 0)
+ i = val - n;
+ else if (val > maxoffset)
+ {
+ dollar_warning(rescan_lineno, val);
+ i = val - maxoffset;
+ }
+ else
+ {
+ i = offsets[val];
+ if (!tag && !(tag = rhs[i]->tag) && havetags)
+ untyped_rhs(val, rhs[i]->name);
+ }
+ msprintf(c, "yystack.l_mark[%d]", i);
+ if (tag)
+ msprintf(c, ".%s", tag);
+ else if (havetags)
+ unknown_rhs(val);
+ }
+ else if (isalpha(*p) || *p == '_')
+ {
+ char *arg;
+ if (!(p = parse_id(p, &arg)))
+ dollar_error(rescan_lineno, NULL, NULL);
+ for (i = plhs[nrules]->args - 1; i >= 0; i--)
+ if (arg == plhs[nrules]->argnames[i])
+ break;
+ if (i < 0)
+ unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
+ else if (!tag)
+ tag = plhs[nrules]->argtags[i];
+ msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
+ - n);
+ if (tag)
+ msprintf(c, ".%s", tag);
+ else if (havetags)
+ untyped_arg_warning(rescan_lineno, "$", arg);
+ }
+ else
+ dollar_error(rescan_lineno, NULL, NULL);
+ }
+ else if (*p == '@')
+ {
+ at_error(rescan_lineno, NULL, NULL);
+ }
+ else
+ {
+ if (*p == '\n')
+ rescan_lineno++;
+ mputc(c, *p++);
+ }
+ }
+ *theptr = p;
+ if (maxoffset > 0)
+ FREE(offsets);
+ return msdone(c);
+}
+
+#define ARG_CACHE_SIZE 1024
+static struct arg_cache
+{
+ struct arg_cache *next;
+ char *code;
+ int rule;
+}
+ *arg_cache[ARG_CACHE_SIZE];
+
+static int
+lookup_arg_cache(char *code)
+{
+ struct arg_cache *entry;
+
+ entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
+ while (entry)
+ {
+ if (!strnscmp(entry->code, code))
+ return entry->rule;
+ entry = entry->next;
+ }
+ return -1;
+}
+
+static void
+insert_arg_cache(char *code, int rule)
+{
+ struct arg_cache *entry = NEW(struct arg_cache);
+ int i;
+
+ NO_SPACE(entry);
+ i = strnshash(code) % ARG_CACHE_SIZE;
+ entry->code = code;
+ entry->rule = rule;
+ entry->next = arg_cache[i];
+ arg_cache[i] = entry;
+}
+
+static void
+clean_arg_cache(void)
+{
+ struct arg_cache *e, *t;
+ int i;
+
+ for (i = 0; i < ARG_CACHE_SIZE; i++)
+ {
+ for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
+ free(e->code);
+ arg_cache[i] = NULL;
+ }
+}
+#endif
+
static void
advance_to_start(void)
{
@@ -1379,6 +1775,10 @@ advance_to_start(void)
bucket *bp;
char *s_cptr;
int s_lineno;
+#if defined(YYBTYACC)
+ char *args = NULL;
+ int argslen = 0;
+#endif
for (;;)
{
@@ -1419,9 +1819,22 @@ advance_to_start(void)
c = nextc();
if (c == EOF)
unexpected_EOF();
+ rescan_lineno = lineno; /* line# for possible inherited args rescan */
+#if defined(YYBTYACC)
+ if (c == L_PAREN)
+ {
+ ++cptr;
+ args = copy_args(&argslen);
+ NO_SPACE(args);
+ c = nextc();
+ }
+#endif
if (c != ':')
syntax_error(lineno, line, cptr);
start_rule(bp, s_lineno);
+#if defined(YYBTYACC)
+ parse_arginfo(bp, args, argslen);
+#endif
++cptr;
}
@@ -1431,6 +1844,8 @@ start_rule(bucket *bp, int s_lineno)
if (bp->class == TERM)
terminal_lhs(s_lineno);
bp->class = NONTERM;
+ if (!bp->index)
+ bp->index = nrules;
if (nrules >= maxrules)
expand_rules();
plhs[nrules] = bp;
@@ -1477,9 +1892,13 @@ insert_empty_rule(void)
last_symbol->next = bp;
last_symbol = bp;
bp->tag = plhs[nrules]->tag;
- bp->class = NONTERM;
+ bp->class = ACTION;
+#if defined(YYBTYACC)
+ bp->args = 0;
+#endif
- if ((nitems += 2) > maxitems)
+ nitems = (Value_t) (nitems + 2);
+ if (nitems > maxitems)
expand_items();
bpp = pitem + nitems - 1;
*bpp-- = bp;
@@ -1496,12 +1915,49 @@ insert_empty_rule(void)
rassoc[nrules - 1] = TOKEN;
}
+#if defined(YYBTYACC)
+static char *
+insert_arg_rule(char *arg, char *tag)
+{
+ int line_number = rescan_lineno;
+ char *code = compile_arg(&arg, tag);
+ int rule = lookup_arg_cache(code);
+ FILE *f = action_file;
+
+ if (rule < 0)
+ {
+ rule = nrules;
+ insert_arg_cache(code, rule);
+ fprintf(f, "case %d:\n", rule - 2);
+ if (!lflag)
+ fprintf(f, line_format, line_number, input_file_name);
+ fprintf(f, "%s;\n", code);
+ fprintf(f, "break;\n");
+ insert_empty_rule();
+ plhs[rule]->tag = tag;
+ plhs[rule]->class = ARGUMENT;
+ }
+ else
+ {
+ if (++nitems > maxitems)
+ expand_items();
+ pitem[nitems - 1] = plhs[rule];
+ free(code);
+ }
+ return arg + 1;
+}
+#endif
+
static void
add_symbol(void)
{
int c;
bucket *bp;
int s_lineno = lineno;
+#if defined(YYBTYACC)
+ char *args = NULL;
+ int argslen = 0;
+#endif
c = *cptr;
if (c == '\'' || c == '"')
@@ -1510,10 +1966,23 @@ add_symbol(void)
bp = get_name();
c = nextc();
+ rescan_lineno = lineno; /* line# for possible inherited args rescan */
+#if defined(YYBTYACC)
+ if (c == L_PAREN)
+ {
+ ++cptr;
+ args = copy_args(&argslen);
+ NO_SPACE(args);
+ c = nextc();
+ }
+#endif
if (c == ':')
{
end_rule();
start_rule(bp, s_lineno);
+#if defined(YYBTYACC)
+ parse_arginfo(bp, args, argslen);
+#endif
++cptr;
return;
}
@@ -1522,6 +1991,30 @@ add_symbol(void)
insert_empty_rule();
last_was_action = 0;
+#if defined(YYBTYACC)
+ if (bp->args < 0)
+ bp->args = argslen;
+ if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
+ {
+ int i;
+ if (plhs[nrules]->args != bp->args)
+ wrong_number_args_warning("default ", bp->name);
+ for (i = bp->args - 1; i >= 0; i--)
+ if (plhs[nrules]->argtags[i] != bp->argtags[i])
+ wrong_type_for_arg_warning(i + 1, bp->name);
+ }
+ else if (bp->args != argslen)
+ wrong_number_args_warning("", bp->name);
+ if (bp->args > 0 && argslen > 0)
+ {
+ char *ap;
+ int i;
+ for (ap = args, i = 0; i < argslen; i++)
+ ap = insert_arg_rule(ap, bp->argtags[i]);
+ free(args);
+ }
+#endif /* defined(YYBTYACC) */
+
if (++nitems > maxitems)
expand_items();
pitem[nitems - 1] = bp;
@@ -1539,20 +2032,34 @@ static void
copy_action(void)
{
int c;
- int i, n;
+ int i, j, n;
int depth;
- int quote;
+#if defined(YYBTYACC)
+ int trialaction = 0;
+ int haveyyval = 0;
+#endif
char *tag;
FILE *f = action_file;
int a_lineno = lineno;
char *a_line = dup_line();
char *a_cptr = a_line + (cptr - line);
+ Value_t *offsets = NULL, maxoffset;
+ bucket **rhs;
if (last_was_action)
insert_empty_rule();
last_was_action = 1;
fprintf(f, "case %d:\n", nrules - 2);
+#if defined(YYBTYACC)
+ if (backtrack)
+ {
+ if (*cptr != L_BRAC)
+ fprintf(f, " if (!yytrial)\n");
+ else
+ trialaction = 1;
+ }
+#endif
if (!lflag)
fprintf(f, line_format, lineno, input_file_name);
if (*cptr == '=')
@@ -1565,9 +2072,27 @@ copy_action(void)
cptr = after_blanks(cptr);
}
+ maxoffset = 0;
n = 0;
for (i = nitems - 1; pitem[i]; --i)
+ {
++n;
+ if (pitem[i]->class != ARGUMENT)
+ maxoffset++;
+ }
+ if (maxoffset > 0)
+ {
+ offsets = TMALLOC(Value_t, maxoffset + 1);
+ NO_SPACE(offsets);
+ }
+ for (j = 0, i++; i < nitems; i++)
+ {
+ if (pitem[i]->class != ARGUMENT)
+ {
+ offsets[++j] = (Value_t) (i - nitems + 1);
+ }
+ }
+ rhs = pitem + nitems - 1;
depth = 0;
loop:
@@ -1593,9 +2118,15 @@ copy_action(void)
else if (isdigit(c))
{
i = get_number();
- if (i > n)
+ if (i == 0)
+ fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
+ else if (i > maxoffset)
+ {
dollar_warning(d_lineno, i);
- fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
+ fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
+ }
+ else if (offsets)
+ fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
FREE(d_line);
goto loop;
}
@@ -1607,12 +2138,27 @@ copy_action(void)
FREE(d_line);
goto loop;
}
+#if defined(YYBTYACC)
+ else if (isalpha(c) || c == '_')
+ {
+ char *arg = scan_id();
+ for (i = plhs[nrules]->args - 1; i >= 0; i--)
+ if (arg == plhs[nrules]->argnames[i])
+ break;
+ if (i < 0)
+ unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
+ fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
+ 1 - n, tag);
+ FREE(d_line);
+ goto loop;
+ }
+#endif
else
dollar_error(d_lineno, d_line, d_cptr);
}
else if (cptr[1] == '$')
{
- if (ntags)
+ if (havetags)
{
tag = plhs[nrules]->tag;
if (tag == 0)
@@ -1622,26 +2168,35 @@ copy_action(void)
else
fprintf(f, "yyval");
cptr += 2;
+#if defined(YYBTYACC)
+ haveyyval = 1;
+#endif
goto loop;
}
else if (isdigit(UCH(cptr[1])))
{
++cptr;
i = get_number();
- if (ntags)
+ if (havetags)
{
- if (i <= 0 || i > n)
+ if (i <= 0 || i > maxoffset)
unknown_rhs(i);
- tag = pitem[nitems + i - n - 1]->tag;
+ tag = rhs[offsets[i]]->tag;
if (tag == 0)
- untyped_rhs(i, pitem[nitems + i - n - 1]->name);
- fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
+ untyped_rhs(i, rhs[offsets[i]]->name);
+ fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
}
else
{
- if (i > n)
+ if (i == 0)
+ fprintf(f, "yystack.l_mark[%d]", -n);
+ else if (i > maxoffset)
+ {
dollar_warning(lineno, i);
- fprintf(f, "yystack.l_mark[%d]", i - n);
+ fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
+ }
+ else if (offsets)
+ fprintf(f, "yystack.l_mark[%d]", offsets[i]);
}
goto loop;
}
@@ -1649,12 +2204,65 @@ copy_action(void)
{
cptr += 2;
i = get_number();
- if (ntags)
+ if (havetags)
unknown_rhs(-i);
fprintf(f, "yystack.l_mark[%d]", -i - n);
goto loop;
}
+#if defined(YYBTYACC)
+ else if (isalpha(cptr[1]) || cptr[1] == '_')
+ {
+ char *arg;
+ ++cptr;
+ arg = scan_id();
+ for (i = plhs[nrules]->args - 1; i >= 0; i--)
+ if (arg == plhs[nrules]->argnames[i])
+ break;
+ if (i < 0)
+ unknown_arg_warning(lineno, "$", arg, line, cptr);
+ tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
+ fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
+ if (tag)
+ fprintf(f, ".%s", tag);
+ else if (havetags)
+ untyped_arg_warning(lineno, "$", arg);
+ goto loop;
+ }
+#endif
+ }
+#if defined(YYBTYACC)
+ if (c == '@')
+ {
+ if (!locations)
+ {
+ int l_lineno = lineno;
+ char *l_line = dup_line();
+ char *l_cptr = l_line + (cptr - line);
+ syntax_error(l_lineno, l_line, l_cptr);
+ }
+ if (cptr[1] == '$')
+ {
+ fprintf(f, "yyloc");
+ cptr += 2;
+ goto loop;
+ }
+ else if (isdigit(UCH(cptr[1])))
+ {
+ ++cptr;
+ i = get_number();
+ if (i == 0)
+ fprintf(f, "yystack.p_mark[%d]", -n);
+ else if (i > maxoffset)
+ {
+ at_warning(lineno, i);
+ fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
+ }
+ else if (offsets)
+ fprintf(f, "yystack.p_mark[%d]", offsets[i]);
+ goto loop;
+ }
}
+#endif
if (isalpha(c) || c == '_' || c == '$')
{
do
@@ -1665,12 +2273,45 @@ copy_action(void)
while (isalnum(c) || c == '_' || c == '$');
goto loop;
}
- putc(c, f);
++cptr;
+#if defined(YYBTYACC)
+ if (backtrack)
+ {
+ if (trialaction && c == L_BRAC && depth == 0)
+ {
+ ++depth;
+ putc(L_CURL, f);
+ goto loop;
+ }
+ if (trialaction && c == R_BRAC && depth == 1)
+ {
+ --depth;
+ putc(R_CURL, f);
+ c = nextc();
+ if (c == L_BRAC && !haveyyval)
+ {
+ goto loop;
+ }
+ if (c == L_CURL && !haveyyval)
+ {
+ fprintf(f, " if (!yytrial)\n");
+ if (!lflag)
+ fprintf(f, line_format, lineno, input_file_name);
+ trialaction = 0;
+ goto loop;
+ }
+ fprintf(f, "\nbreak;\n");
+ FREE(a_line);
+ if (maxoffset > 0)
+ FREE(offsets);
+ return;
+ }
+ }
+#endif
+ putc(c, f);
switch (c)
{
case '\n':
- next_line:
get_line();
if (line)
goto loop;
@@ -1681,8 +2322,22 @@ copy_action(void)
goto loop;
fprintf(f, "\nbreak;\n");
free(a_line);
+ if (maxoffset > 0)
+ FREE(offsets);
return;
+#if defined(YYBTYACC)
+ case L_BRAC:
+ if (backtrack)
+ ++depth;
+ goto loop;
+
+ case R_BRAC:
+ if (backtrack)
+ --depth;
+ goto loop;
+#endif
+
case L_CURL:
++depth;
goto loop;
@@ -1690,83 +2345,326 @@ copy_action(void)
case R_CURL:
if (--depth > 0)
goto loop;
+#if defined(YYBTYACC)
+ if (backtrack)
+ {
+ c = nextc();
+ if (c == L_BRAC && !haveyyval)
+ {
+ trialaction = 1;
+ goto loop;
+ }
+ if (c == L_CURL && !haveyyval)
+ {
+ fprintf(f, " if (!yytrial)\n");
+ if (!lflag)
+ fprintf(f, line_format, lineno, input_file_name);
+ goto loop;
+ }
+ }
+#endif
fprintf(f, "\nbreak;\n");
free(a_line);
+ if (maxoffset > 0)
+ FREE(offsets);
return;
case '\'':
case '"':
{
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
+ char *s = copy_string(c);
+ fputs(s, f);
+ free(s);
+ }
+ goto loop;
- quote = c;
- for (;;)
+ case '/':
+ {
+ char *s = copy_comment();
+ fputs(s, f);
+ free(s);
+ }
+ goto loop;
+
+ default:
+ goto loop;
+ }
+}
+
+#if defined(YYBTYACC)
+static void
+copy_destructor(void)
+{
+ int c;
+ int depth;
+ char *tag;
+ bucket *bp;
+ struct mstring *destructor_text = msnew();
+ char *code_text;
+ int a_lineno;
+ char *a_line;
+ char *a_cptr;
+
+ if (!lflag)
+ msprintf(destructor_text, line_format, lineno, input_file_name);
+
+ cptr = after_blanks(cptr);
+ if (*cptr == L_CURL)
+ /* avoid putting curly-braces in first column, to ease editing */
+ mputc(destructor_text, '\t');
+ else
+ syntax_error(lineno, line, cptr);
+
+ a_lineno = lineno;
+ a_line = dup_line();
+ a_cptr = a_line + (cptr - line);
+
+ depth = 0;
+ loop:
+ c = *cptr;
+ if (c == '$')
+ {
+ if (cptr[1] == '<')
+ {
+ int d_lineno = lineno;
+ char *d_line = dup_line();
+ char *d_cptr = d_line + (cptr - line);
+
+ ++cptr;
+ tag = get_tag();
+ c = *cptr;
+ if (c == '$')
{
- c = *cptr++;
- putc(c, f);
- if (c == quote)
+ msprintf(destructor_text, "(*val).%s", tag);
+ ++cptr;
+ FREE(d_line);
+ goto loop;
+ }
+ else
+ dollar_error(d_lineno, d_line, d_cptr);
+ }
+ else if (cptr[1] == '$')
+ {
+ /* process '$$' later; replacement is context dependent */
+ msprintf(destructor_text, "$$");
+ cptr += 2;
+ goto loop;
+ }
+ }
+ if (c == '@' && cptr[1] == '$')
+ {
+ if (!locations)
+ {
+ int l_lineno = lineno;
+ char *l_line = dup_line();
+ char *l_cptr = l_line + (cptr - line);
+ syntax_error(l_lineno, l_line, l_cptr);
+ }
+ msprintf(destructor_text, "(*loc)");
+ cptr += 2;
+ goto loop;
+ }
+ if (isalpha(c) || c == '_' || c == '$')
+ {
+ do
+ {
+ mputc(destructor_text, c);
+ c = *++cptr;
+ }
+ while (isalnum(c) || c == '_' || c == '$');
+ goto loop;
+ }
+ ++cptr;
+ mputc(destructor_text, c);
+ switch (c)
+ {
+ case '\n':
+ get_line();
+ if (line)
+ goto loop;
+ unterminated_action(a_lineno, a_line, a_cptr);
+
+ case L_CURL:
+ ++depth;
+ goto loop;
+
+ case R_CURL:
+ if (--depth > 0)
+ goto loop;
+ goto process_symbols;
+
+ case '\'':
+ case '"':
+ {
+ char *s = copy_string(c);
+ msprintf(destructor_text, "%s", s);
+ free(s);
+ }
+ goto loop;
+
+ case '/':
+ {
+ char *s = copy_comment();
+ msprintf(destructor_text, "%s", s);
+ free(s);
+ }
+ goto loop;
+
+ default:
+ goto loop;
+ }
+ process_symbols:
+ code_text = msdone(destructor_text);
+ for (;;)
+ {
+ c = nextc();
+ if (c == EOF)
+ unexpected_EOF();
+ if (c == '<')
+ {
+ if (cptr[1] == '>')
+ { /* "no semantic type" default destructor */
+ cptr += 2;
+ if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
{
- FREE(s_line);
- goto loop;
+ static char untyped_default[] = "<>";
+ bp = make_bucket("untyped default");
+ bp->tag = untyped_default;
+ default_destructor[UNTYPED_DEFAULT] = bp;
}
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
+ if (bp->destructor != NULL)
+ destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ else
+ /* replace "$$" with "(*val)" in destructor code */
+ bp->destructor = process_destructor_XX(code_text, NULL);
+ }
+ else if (cptr[1] == '*' && cptr[2] == '>')
+ { /* "no per-symbol or per-type" default destructor */
+ cptr += 3;
+ if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
{
- c = *cptr++;
- putc(c, f);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
+ static char typed_default[] = "<*>";
+ bp = make_bucket("typed default");
+ bp->tag = typed_default;
+ default_destructor[TYPED_DEFAULT] = bp;
}
+ if (bp->destructor != NULL)
+ destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ else
+ {
+ /* postpone re-processing destructor $$s until end of grammar spec */
+ bp->destructor = TMALLOC(char, strlen(code_text) + 1);
+ NO_SPACE(bp->destructor);
+ strcpy(bp->destructor, code_text);
+ }
+ }
+ else
+ { /* "semantic type" default destructor */
+ tag = get_tag();
+ bp = lookup_type_destructor(tag);
+ if (bp->destructor != NULL)
+ destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ else
+ /* replace "$$" with "(*val).tag" in destructor code */
+ bp->destructor = process_destructor_XX(code_text, tag);
}
}
+ else if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ { /* "symbol" destructor */
+ bp = get_name();
+ if (bp->destructor != NULL)
+ destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ else
+ {
+ /* postpone re-processing destructor $$s until end of grammar spec */
+ bp->destructor = TMALLOC(char, strlen(code_text) + 1);
+ NO_SPACE(bp->destructor);
+ strcpy(bp->destructor, code_text);
+ }
+ }
+ else
+ break;
+ }
+ free(a_line);
+ free(code_text);
+}
- case '/':
- c = *cptr;
- if (c == '/')
+static char *
+process_destructor_XX(char *code, char *tag)
+{
+ int c;
+ int quote;
+ int depth;
+ struct mstring *new_code = msnew();
+ char *codeptr = code;
+
+ depth = 0;
+ loop: /* step thru code */
+ c = *codeptr;
+ if (c == '$' && codeptr[1] == '$')
+ {
+ codeptr += 2;
+ if (tag == NULL)
+ msprintf(new_code, "(*val)");
+ else
+ msprintf(new_code, "(*val).%s", tag);
+ goto loop;
+ }
+ if (isalpha(c) || c == '_' || c == '$')
+ {
+ do
{
- putc('*', f);
- while ((c = *++cptr) != '\n')
+ mputc(new_code, c);
+ c = *++codeptr;
+ }
+ while (isalnum(c) || c == '_' || c == '$');
+ goto loop;
+ }
+ ++codeptr;
+ mputc(new_code, c);
+ switch (c)
+ {
+ case L_CURL:
+ ++depth;
+ goto loop;
+
+ case R_CURL:
+ if (--depth > 0)
+ goto loop;
+ return msdone(new_code);
+
+ case '\'':
+ case '"':
+ quote = c;
+ for (;;)
+ {
+ c = *codeptr++;
+ mputc(new_code, c);
+ if (c == quote)
+ goto loop;
+ if (c == '\\')
{
- if (c == '*' && cptr[1] == '/')
- fprintf(f, "* ");
- else
- putc(c, f);
+ c = *codeptr++;
+ mputc(new_code, c);
}
- fprintf(f, "*/\n");
- goto next_line;
}
+
+ case '/':
+ c = *codeptr;
if (c == '*')
{
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
-
- putc('*', f);
- ++cptr;
+ mputc(new_code, c);
+ ++codeptr;
for (;;)
{
- c = *cptr++;
- putc(c, f);
- if (c == '*' && *cptr == '/')
+ c = *codeptr++;
+ mputc(new_code, c);
+ if (c == '*' && *codeptr == '/')
{
- putc('/', f);
- ++cptr;
- FREE(c_line);
+ mputc(new_code, '/');
+ ++codeptr;
goto loop;
}
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
}
}
goto loop;
@@ -1775,6 +2673,7 @@ copy_action(void)
goto loop;
}
}
+#endif /* defined(YYBTYACC) */
static int
mark_symbol(void)
@@ -1808,7 +2707,6 @@ mark_symbol(void)
else
{
syntax_error(lineno, line, cptr);
- /*NOTREACHED */
}
if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
@@ -1839,7 +2737,11 @@ read_grammar(void)
|| c == '\''
|| c == '"')
add_symbol();
+#if defined(YYBTYACC)
+ else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
+#else
else if (c == L_CURL || c == '=')
+#endif
copy_action();
else if (c == '|')
{
@@ -1856,6 +2758,10 @@ read_grammar(void)
syntax_error(lineno, line, cptr);
}
end_rule();
+#if defined(YYBTYACC)
+ if (goal->args > 0)
+ start_requires_args(goal->name);
+#endif
}
static void
@@ -1959,6 +2865,9 @@ pack_symbols(void)
bucket *bp;
bucket **v;
Value_t i, j, k, n;
+#if defined(YYBTYACC)
+ Value_t max_tok_pval;
+#endif
nsyms = 2;
ntokens = 1;
@@ -1969,7 +2878,7 @@ pack_symbols(void)
++ntokens;
}
start_symbol = (Value_t) ntokens;
- nvars = nsyms - ntokens;
+ nvars = (Value_t) (nsyms - ntokens);
symbol_name = TMALLOC(char *, nsyms);
NO_SPACE(symbol_name);
@@ -1977,12 +2886,26 @@ pack_symbols(void)
symbol_value = TMALLOC(Value_t, nsyms);
NO_SPACE(symbol_value);
- symbol_prec = TMALLOC(short, nsyms);
+ symbol_prec = TMALLOC(Value_t, nsyms);
NO_SPACE(symbol_prec);
symbol_assoc = TMALLOC(char, nsyms);
NO_SPACE(symbol_assoc);
+#if defined(YYBTYACC)
+ symbol_pval = TMALLOC(Value_t, nsyms);
+ NO_SPACE(symbol_pval);
+
+ if (destructor)
+ {
+ symbol_destructor = CALLOC(sizeof(char *), nsyms);
+ NO_SPACE(symbol_destructor);
+
+ symbol_type_tag = CALLOC(sizeof(char *), nsyms);
+ NO_SPACE(symbol_type_tag);
+ }
+#endif
+
v = TMALLOC(bucket *, nsyms);
NO_SPACE(v);
@@ -2061,17 +2984,34 @@ pack_symbols(void)
symbol_value[0] = 0;
symbol_prec[0] = 0;
symbol_assoc[0] = TOKEN;
+#if defined(YYBTYACC)
+ symbol_pval[0] = 0;
+ max_tok_pval = 0;
+#endif
for (i = 1; i < ntokens; ++i)
{
symbol_name[i] = v[i]->name;
symbol_value[i] = v[i]->value;
symbol_prec[i] = v[i]->prec;
symbol_assoc[i] = v[i]->assoc;
+#if defined(YYBTYACC)
+ symbol_pval[i] = v[i]->value;
+ if (symbol_pval[i] > max_tok_pval)
+ max_tok_pval = symbol_pval[i];
+ if (destructor)
+ {
+ symbol_destructor[i] = v[i]->destructor;
+ symbol_type_tag[i] = v[i]->tag;
+ }
+#endif
}
symbol_name[start_symbol] = name_pool;
symbol_value[start_symbol] = -1;
symbol_prec[start_symbol] = 0;
symbol_assoc[start_symbol] = TOKEN;
+#if defined(YYBTYACC)
+ symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
+#endif
for (++i; i < nsyms; ++i)
{
k = v[i]->index;
@@ -2079,6 +3019,14 @@ pack_symbols(void)
symbol_value[k] = v[i]->value;
symbol_prec[k] = v[i]->prec;
symbol_assoc[k] = v[i]->assoc;
+#if defined(YYBTYACC)
+ symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
+ if (destructor)
+ {
+ symbol_destructor[k] = v[i]->destructor;
+ symbol_type_tag[k] = v[i]->tag;
+ }
+#endif
}
if (gflag)
@@ -2130,6 +3078,21 @@ pack_grammar(void)
j = 4;
for (i = 3; i < nrules; ++i)
{
+#if defined(YYBTYACC)
+ if (plhs[i]->args > 0)
+ {
+ if (plhs[i]->argnames)
+ {
+ FREE(plhs[i]->argnames);
+ plhs[i]->argnames = NULL;
+ }
+ if (plhs[i]->argtags)
+ {
+ FREE(plhs[i]->argtags);
+ plhs[i]->argtags = NULL;
+ }
+ }
+#endif /* defined(YYBTYACC) */
rlhs[i] = plhs[i]->index;
rrhs[i] = j;
assoc = TOKEN;
@@ -2156,6 +3119,9 @@ pack_grammar(void)
FREE(plhs);
FREE(pitem);
+#if defined(YYBTYACC)
+ clean_arg_cache();
+#endif
}
static void
@@ -2197,6 +3163,85 @@ print_grammar(void)
}
}
+#if defined(YYBTYACC)
+static void
+finalize_destructors(void)
+{
+ int i;
+ bucket *bp;
+ char *tag;
+
+ for (i = 2; i < nsyms; ++i)
+ {
+ tag = symbol_type_tag[i];
+ if (symbol_destructor[i] == NULL)
+ {
+ if (tag == NULL)
+ { /* use <> destructor, if there is one */
+ if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
+ {
+ symbol_destructor[i] = TMALLOC(char,
+ strlen(bp->destructor) + 1);
+ NO_SPACE(symbol_destructor[i]);
+ strcpy(symbol_destructor[i], bp->destructor);
+ }
+ }
+ else
+ { /* use type destructor for this tag, if there is one */
+ bp = lookup_type_destructor(tag);
+ if (bp->destructor != NULL)
+ {
+ symbol_destructor[i] = TMALLOC(char,
+ strlen(bp->destructor) + 1);
+ NO_SPACE(symbol_destructor[i]);
+ strcpy(symbol_destructor[i], bp->destructor);
+ }
+ else
+ { /* use <*> destructor, if there is one */
+ if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
+ /* replace "$$" with "(*val).tag" in destructor code */
+ symbol_destructor[i]
+ = process_destructor_XX(bp->destructor, tag);
+ }
+ }
+ }
+ else
+ { /* replace "$$" with "(*val)[.tag]" in destructor code */
+ symbol_destructor[i]
+ = process_destructor_XX(symbol_destructor[i], tag);
+ }
+ }
+ /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
+ DO_FREE(symbol_type_tag); /* no longer needed */
+ if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
+ {
+ FREE(bp->name);
+ /* 'bp->tag' is a static value, don't free */
+ FREE(bp->destructor);
+ FREE(bp);
+ }
+ if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
+ {
+ FREE(bp->name);
+ /* 'bp->tag' is a static value, don't free */
+ FREE(bp->destructor);
+ FREE(bp);
+ }
+ if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
+ {
+ bucket *p;
+ for (; bp; bp = p)
+ {
+ p = bp->link;
+ FREE(bp->name);
+ /* 'bp->tag' freed by 'free_tags()' */
+ FREE(bp->destructor);
+ FREE(bp);
+ }
+ }
+}
+#endif /* defined(YYBTYACC) */
+
void
reader(void)
{
@@ -2205,13 +3250,17 @@ reader(void)
read_declarations();
read_grammar();
free_symbol_table();
- free_tags();
pack_names();
check_symbols();
pack_symbols();
pack_grammar();
free_symbols();
print_grammar();
+#if defined(YYBTYACC)
+ if (destructor)
+ finalize_destructors();
+#endif
+ free_tags();
}
#ifdef NO_LEAKS
@@ -2248,5 +3297,10 @@ reader_leaks(void)
DO_FREE(symbol_prec);
DO_FREE(symbol_assoc);
DO_FREE(symbol_value);
+#if defined(YYBTYACC)
+ DO_FREE(symbol_pval);
+ DO_FREE(symbol_destructor);
+ DO_FREE(symbol_type_tag);
+#endif
}
#endif
OpenPOWER on IntegriCloud