+2001-12-27 Akim Demaille <akim@epita.fr>
+
+ * src/gram.h (rule_t): `guard' and `guard_line' are new members.
+ * src/reader.c (symbol_list): `guard' and `guard_line' are new
+ members.
+ (symbol_list_new): Adjust.
+ (copy_action): action_line is the first line, not the last.
+ (copy_guard): Just as for actions, store the `action' only, not
+ the switch/case/break flesh.
+ Don't parse the user action that might follow the guard, let...
+ (readgram): do it, i.e., now, there can be an action after a
+ guard.
+ In other words the guard is just explicitly optional.
+ (packgram): Adjust.
+ * src/output.c (guards_output): New.
+ (output_parser): Call it when needed.
+ (output): Also free the guard and attrs obstacks.
+ * src/files.c, src/files.h (obstack_save): Remove.
+ (output_files): Remove.
+ As a result, if one needs the former `.act' file, using an
+ appropriate skeleton which requires actions and guards is now
+ required.
+ * src/main.c (main): Adjust.
+ * tests/semantic.at: New.
+ * tests/regression.at: Use `input.y' as input file name.
+ Avoid 8+3 problems by requiring input.c when the test needs the
+ parser.
+
2001-12-27 Akim Demaille <akim@epita.fr>
* src/reader.c (symbol_list_new): Be sure to initialize all the
return result;
}
-/*--------------------------------------------------.
-| Save the content of the obstack OBS in FILENAME. |
-`--------------------------------------------------*/
-
-static void
-obstack_save (struct obstack *obs, const char *filename)
-{
- FILE *out = xfopen (filename, "w");
- size_t size = obstack_object_size (obs);
- fwrite (obstack_finish (obs), 1, size, out);
- xfclose (out);
-}
/*------------------------------------------------------------------.
| Return the path to the skeleton which locaction might be given in |
attrsfile = stringappend (attrsfile, header_extension);
#endif /* MSDOS */
}
-
-
-/*---------------------------.
-| Produce the output files. |
-`---------------------------*/
-
-void
-output_files (void)
-{
-#if 0
- /* Seems to be invalid now --akim. */
-
- /* If we output only the table, dump the actions in ACTFILE. */
- if (no_parser_flag)
- obstack_save (&action_obstack, stringappend (short_base_name, ".act"));
- obstack_free (&action_obstack, NULL);
-#endif
-
- /* If we produced a semantic parser ATTRS_OBSTACK must be dumped
- into its own file, ATTTRSFILE. */
- if (semantic_parser)
- {
- char *temp_name;
-
- obstack_save (&attrs_obstack, attrsfile);
- temp_name = stringappend (short_base_name, EXT_GUARD_C);
-#ifndef MSDOS
- temp_name = stringappend (temp_name, src_extension);
-#endif /* MSDOS */
- obstack_save (&guard_obstack, temp_name);
- }
-
- obstack_free (&guard_obstack, NULL);
- obstack_free (&attrs_obstack, NULL);
-}
extern char *attrsfile;
void compute_output_file_names PARAMS((void));
-void output_files PARAMS((void));
FILE *xfopen PARAMS ((const char *name, const char *mode));
int xfclose PARAMS ((FILE *ptr));
/* Compute the double inclusion guard's name. */
-char * compute_header_macro PARAMS ((void));
+char *compute_header_macro PARAMS ((void));
const char *skeleton_find PARAMS ((const char *envvar,
const char *skeleton_name));
short assoc;
short line;
bool useful;
+
const char *action;
short action_line;
+
+ const char *guard;
+ short guard_line;
} rule_t;
extern struct rule_s *rule_table;
free_nullable ();
free_derives ();
- output_files ();
-
/* If using alloca.c, flush the alloca'ed memory for the benefit of
people running Bison as a library in IDEs. */
#if C_ALLOCA
}
+/*----------------------------.
+| Output the guards to OOUT. |
+`----------------------------*/
+
+static void
+guards_output (FILE *out, size_t *line)
+{
+ int rule;
+ for (rule = 1; rule < nrules + 1; ++rule)
+ if (rule_table[rule].action)
+ {
+ fprintf (out, " case %d:\n", rule);
+
+ if (!no_lines_flag)
+ fprintf (out, muscle_find ("linef"),
+ rule_table[rule].guard_line,
+ quotearg_style (c_quoting_style,
+ muscle_find ("filename")));
+ fprintf (out, "{ %s; }\n break;\n\n",
+ rule_table[rule].guard);
+
+ /* We always output 4 '\n' per action. */
+ *line += 4;
+ /* Plus one if !no_lines_flag. */
+ if (!no_lines_flag)
+ ++*line;
+ /* Get the number of lines written by the user. */
+ *line += get_lines_number (rule_table[rule].guard);
+ }
+}
+
+
static void
save_column (int symbol, int default_state)
{
muscle_value = muscle_find (muscle_key);
if (!strcmp (muscle_key, "actions"))
actions_output (out, &output_line);
+ else if (!strcmp (muscle_key, "guards"))
+ guards_output (out, &output_line);
else if (!strcmp (muscle_key, "line"))
fprintf (out, "%d", output_line);
else if (!strcmp (muscle_key, "skeleton-line"))
header_output ();
free (rule_table + 1);
- obstack_free (&muscle_obstack, 0);
- obstack_free (&format_obstack, 0);
- obstack_free (&action_obstack, 0);
+ obstack_free (&muscle_obstack, NULL);
+ obstack_free (&format_obstack, NULL);
+ obstack_free (&action_obstack, NULL);
+ obstack_free (&guard_obstack, NULL);
+ obstack_free (&attrs_obstack, NULL);
}
struct symbol_list *next;
bucket *sym;
int line;
+
/* The action is attached to the LHS of a rule. */
const char *action;
int action_line;
+
+ /* The guard is attached to the LHS of a rule. */
+ const char *guard;
+ int guard_line;
bucket *ruleprec;
} symbol_list;
res->line = lineno;
res->action = NULL;
res->action_line = 0;
+ res->guard = NULL;
+ res->guard_line = 0;
res->ruleprec = NULL;
return res;
}
count = 1;
c = getc (finput);
+ rule->action_line = lineno;
+
while (count > 0)
{
while (c != '}')
obstack_1grow (&action_obstack, '\0');
rule->action = obstack_finish (&action_obstack);
- rule->action_line = lineno;
}
\f
/*-------------------------------------------------------------------.
if (semantic_parser)
stack_offset = 0;
- obstack_fgrow1 (&guard_obstack, "\ncase %d:\n", nrules);
- if (!no_lines_flag)
- obstack_fgrow2 (&guard_obstack, muscle_find ("linef"),
- lineno, quotearg_style (c_quoting_style,
- muscle_find ("filename")));
- obstack_1grow (&guard_obstack, '{');
+ rule->guard_line = lineno;
count = 0;
c = getc (finput);
c = getc (finput);
}
- c = skip_white_space ();
-
- obstack_sgrow (&guard_obstack, ";\n break;}");
- if (c == '{')
- copy_action (rule, stack_offset);
- else if (c == '=')
- {
- c = getc (finput); /* why not skip_white_space -wjh */
- if (c == '{')
- copy_action (rule, stack_offset);
- }
- else
- ungetc (c, finput);
+ obstack_1grow (&guard_obstack, '\0');
+ rule->guard = obstack_finish (&guard_obstack);
}
\f
crule->ruleprec = symval;
t = lex ();
}
+
if (t == tok_guard)
{
if (!semantic_parser)
copy_guard (crule, rulelength);
t = lex ();
}
- else if (t == tok_left_curly)
+
+ if (t == tok_left_curly)
{
/* This case never occurs -wjh */
if (action_flag)
rule_table[ruleno].useful = TRUE;
rule_table[ruleno].action = p->action;
rule_table[ruleno].action_line = p->action_line;
+ rule_table[ruleno].guard = p->guard;
+ rule_table[ruleno].guard_line = p->guard_line;
p = p->next;
while (p && p->sym)
TESTSUITE_AT = \
testsuite.at \
- output.at sets.at reduce.at calc.at torture.at regression.at
+ output.at sets.at reduce.at calc.at torture.at regression.at \
+ semantic.at
+
TESTSUITE = $(srcdir)/testsuite
AUTOTEST = $(AUTOM4TE) --language=autotest
AT_SETUP([Duplicate string])
-AT_DATA([duplicate.y],
+AT_DATA([input.y],
[[/* `Bison -v' used to dump core when two tokens are defined with the same
string, as LE and GE below. */
%%
]])
-AT_CHECK([bison -v duplicate.y -o duplicate.c], 0, ignore, ignore)
+AT_CHECK([bison -v input.y -o input.c], 0, ignore, ignore)
AT_CLEANUP
AT_SETUP([%union and --defines])
-AT_DATA([union.y],
+AT_DATA([input.y],
[%union
{
int integer;
exp: {};
])
-AT_CHECK([bison --defines union.y])
+AT_CHECK([bison --defines input.y])
AT_CLEANUP
AT_SETUP([%union and C comments])
-AT_DATA([union-comment.y],
+AT_DATA([input.y],
[%union
{
/* The int. */ int integer;
exp: {};
])
-AT_CHECK([bison union-comment.y])
-AT_CHECK([fgrep '//*' union-comment.tab.c], [1], [])
+AT_CHECK([bison input.y -o input.c])
+AT_CHECK([fgrep '//*' input.c], [1], [])
AT_CLEANUP
--- /dev/null
+# Bison Semantic Parsers. -*- Autotest -*-
+# Copyright 2001 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+AT_BANNER([[Semantic Parsers.]])
+
+# Well, nothing, or almost, is known about semantic parsers. For the
+# time being, just make sure we still parse them properly.
+
+## ---------------- ##
+## Parsing Guards. ##
+## ---------------- ##
+
+
+AT_SETUP([Parsing Guards])
+
+AT_DATA([input.y],
+[[%semantic-parser
+%union {
+ int ival;
+}
+%token <ival> INT
+%type <ival> exp
+%%
+exp: exp '+' exp { $$ = $1 + $3 }
+ | exp '/' exp %guard { if ($3 == 0) yyerror = 1 } { $$ = $1 / $3 }
+ | INT
+%%
+]])
+
+AT_CHECK([bison -v input.y -o input.c], 0, ignore, ignore)
+
+AT_CLEANUP
m4_include([calc.at])
m4_include([torture.at])
m4_include([regression.at])
+m4_include([semantic.at])