+2006-06-24 Joel E. Denny <jdenny@ces.clemson.edu>
+
+ Fix bug that mistakes braced code in a declaration in the rules section
+ to be a rule action. Mentioned at
+ <http://lists.gnu.org/archive/html/bison-patches/2006-06/msg00105.html>.
+ * src/scan-gram.l: Move midrule action detection from the start of the
+ scanning of any braced code to...
+ * src/parse-gram.y (rhs): ... the parsing of braced code as a rule
+ action. For readability, use $2 and @2 rather than the equivalent
+ global variables.
+ * tests/regression.at (Braced code in declaration in rules section):
+ New test to catch the error fixed by the above patch.
+
+ Work on code readability some.
+ * src/scan-code.l (current_rule): Get rid of this misleading and
+ redundant declaration: it's actually extern'ed in reader.h.
+ (YY_DECL, code_lex, handle_action_dollar, handle_action_at,
+ translate_action): Add a rule argument and use it instead of the global
+ current_rule.
+ (translate_rule_action): This already receives current_rule through an
+ argument, so pass it on to translate_action instead of assigning
+ current_rule to current_rule.
+ (translate_symbol_action, translate_code): Pass rule = NULL to
+ translate_action.
+
2006-06-23 Joel E. Denny <jdenny@ces.clemson.edu>
Rename %before-definitions to %start-header and %after-definitions to
305, 309, 323, 324, 328, 350, 350, 355, 355, 360,
370, 385, 386, 387, 391, 392, 397, 398, 403, 407,
412, 418, 424, 435, 436, 445, 446, 452, 453, 454,
- 461, 461, 465, 466, 467, 472, 473, 475, 478, 480,
- 482, 495, 497, 506, 511, 512, 517, 526, 531, 533
+ 461, 461, 465, 466, 467, 472, 473, 475, 481, 483,
+ 485, 498, 500, 509, 514, 515, 520, 529, 534, 536
};
#endif
case 77:
#line 476 "parse-gram.y"
- { grammar_current_rule_action_append (gram_last_string,
- gram_last_braced_code_loc); }
+ {
+ if (current_rule && current_rule->action)
+ grammar_midrule_action ();
+ grammar_current_rule_action_append ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
+ }
break;
case 78:
-#line 479 "parse-gram.y"
+#line 482 "parse-gram.y"
{ grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
break;
case 79:
-#line 481 "parse-gram.y"
+#line 484 "parse-gram.y"
{ grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
break;
case 80:
-#line 483 "parse-gram.y"
+#line 486 "parse-gram.y"
{ grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
break;
case 81:
-#line 496 "parse-gram.y"
+#line 499 "parse-gram.y"
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
break;
case 82:
-#line 498 "parse-gram.y"
+#line 501 "parse-gram.y"
{
(yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
break;
case 83:
-#line 506 "parse-gram.y"
+#line 509 "parse-gram.y"
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
break;
case 86:
-#line 518 "parse-gram.y"
+#line 521 "parse-gram.y"
{
(yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
break;
case 87:
-#line 527 "parse-gram.y"
+#line 530 "parse-gram.y"
{ (yyval.chars) = (yyvsp[(1) - (1)].chars); }
break;
case 89:
-#line 534 "parse-gram.y"
+#line 537 "parse-gram.y"
{
muscle_code_grow ("epilogue", translate_code ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])), (yylsp[(2) - (2)]));
gram_scanner_last_string_free ();
/* Line 1274 of yacc.c. */
-#line 2238 "parse-gram.c"
+#line 2241 "parse-gram.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
}
-#line 540 "parse-gram.y"
+#line 543 "parse-gram.y"
| rhs symbol
{ grammar_current_rule_symbol_append ($2, @2); }
| rhs "{...}"
- { grammar_current_rule_action_append (gram_last_string,
- gram_last_braced_code_loc); }
+ {
+ if (current_rule && current_rule->action)
+ grammar_midrule_action ();
+ grammar_current_rule_action_append ($2, @2);
+ }
| rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT
/* The current calling start condition: SC_RULE_ACTION or
SC_SYMBOL_ACTION. */
-# define YY_DECL const char *code_lex (int sc_context)
+# define YY_DECL const char *code_lex (int sc_context, symbol_list *rule)
YY_DECL;
#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
-static void handle_action_dollar (char *cp, location dollar_loc);
-static void handle_action_at (char *cp, location at_loc);
+static void handle_action_dollar (symbol_list *rule, char *cp,
+ location dollar_loc);
+static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
static location the_location;
static location *loc = &the_location;
-
-/* The rule being processed. */
-symbol_list *current_rule;
%}
/* C and C++ comments in code. */
%x SC_COMMENT SC_LINE_COMMENT
<SC_RULE_ACTION>
{
- "$"("<"{tag}">")?(-?[0-9]+|"$") handle_action_dollar (yytext, *loc);
- "@"(-?[0-9]+|"$") handle_action_at (yytext, *loc);
+ "$"("<"{tag}">")?(-?[0-9]+|"$") handle_action_dollar (rule, yytext, *loc);
+ "@"(-?[0-9]+|"$") handle_action_at (rule, yytext, *loc);
"$" {
warn_at (*loc, _("stray `$'"));
`------------------------------------------------------------------*/
static void
-handle_action_dollar (char *text, location dollar_loc)
+handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
{
const char *type_name = NULL;
char *cp = text + 1;
- int rule_length = symbol_list_length (current_rule->next);
+ int rule_length = symbol_list_length (rule->next);
/* Get the type name if explicit. */
if (*cp == '<')
if (*cp == '$')
{
if (!type_name)
- type_name = symbol_list_n_type_name_get (current_rule, dollar_loc, 0);
+ type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
if (!type_name && typed)
complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
- current_rule->sym->tag);
+ rule->sym->tag);
if (!type_name)
type_name = "";
obstack_fgrow1 (&obstack_for_string,
"]b4_lhs_value([%s])[", type_name);
- current_rule->used = true;
+ rule->used = true;
}
else
{
max_left_semantic_context = 1-n;
if (!type_name && n > 0)
type_name =
- symbol_list_n_type_name_get (current_rule, dollar_loc, n);
+ symbol_list_n_type_name_get (rule, dollar_loc, n);
if (!type_name && typed)
complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
- n, current_rule->sym->tag);
+ n, rule->sym->tag);
if (!type_name)
type_name = "";
obstack_fgrow3 (&obstack_for_string,
"]b4_rhs_value(%d, %d, [%s])[",
rule_length, n, type_name);
- symbol_list_n_used_set (current_rule, n, true);
+ symbol_list_n_used_set (rule, n, true);
}
else
complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
`------------------------------------------------------*/
static void
-handle_action_at (char *text, location at_loc)
+handle_action_at (symbol_list *rule, char *text, location at_loc)
{
char *cp = text + 1;
- int rule_length = symbol_list_length (current_rule->next);
+ int rule_length = symbol_list_length (rule->next);
locations_flag = true;
if (*cp == '$')
INITIAL), the processing is different. */
static const char *
-translate_action (int sc_context, const char *a, location l)
+translate_action (int sc_context, symbol_list *rule, const char *a, location l)
{
const char *res;
static bool initialized = false;
loc->start = loc->end = l.start;
yy_switch_to_buffer (yy_scan_string (a));
- res = code_lex (sc_context);
+ res = code_lex (sc_context, rule);
yy_delete_buffer (YY_CURRENT_BUFFER);
return res;
}
const char *
-translate_rule_action (symbol_list *r, const char *a, location l)
+translate_rule_action (symbol_list *rule, const char *a, location l)
{
- current_rule = r;
- return translate_action (SC_RULE_ACTION, a, l);
+ return translate_action (SC_RULE_ACTION, rule, a, l);
}
const char *
translate_symbol_action (const char *a, location l)
{
- return translate_action (SC_SYMBOL_ACTION, a, l);
+ return translate_action (SC_SYMBOL_ACTION, NULL, a, l);
}
const char *
translate_code (const char *a, location l)
{
- return translate_action (INITIAL, a, l);
+ return translate_action (INITIAL, NULL, a, l);
}
/*-----------------------------------------------.
/* Code in between braces. */
"{" {
- if (current_rule && current_rule->action)
- grammar_midrule_action ();
STRING_GROW;
braces_level = 0;
code_start = loc->start;
AT_CHECK_EXPECT2()
AT_CHECK_EXPECT2([%glr-parser])
AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])
+
+
+
+## --------------------------------------------- ##
+## Braced code in declaration in rules section. ##
+## --------------------------------------------- ##
+
+AT_SETUP([Braced code in declaration in rules section])
+
+# Bison once mistook braced code in a declaration in the rules section to be a
+# rule action.
+
+AT_DATA_GRAMMAR([input.y],
+[[%{
+#include <stdio.h>
+void yyerror (char const *msg);
+int yylex (void);
+%}
+
+%error-verbose
+
+%%
+
+start:
+ {
+ printf ("Bison would once convert this action to a midrule because of the"
+ " subsequent braced code.\n");
+ }
+ ;
+
+%destructor { fprintf (stderr, "DESTRUCTOR\n"); } 'a';
+%printer { fprintf (yyoutput, "PRINTER"); } 'a';
+
+%%
+
+void
+yyerror (char const *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+}
+
+int
+yylex (void)
+{
+ return 'a';
+}
+
+int
+main (void)
+{
+ yydebug = 1;
+ return !yyparse ();
+}
+]])
+
+AT_CHECK([bison -t -o input.c input.y])
+AT_COMPILE([input])
+AT_PARSER_CHECK([./input], 0,
+[[Bison would once convert this action to a midrule because of the subsequent braced code.
+]],
+[[Starting parse
+Entering state 0
+Reducing stack by rule 1 (line 22):
+-> $$ = nterm start ()
+Stack now 0
+Entering state 1
+Reading a token: Next token is token 'a' (PRINTER)
+syntax error, unexpected 'a', expecting $end
+Error: popping nterm start ()
+Stack now 0
+Cleanup: discarding lookahead token 'a' (PRINTER)
+DESTRUCTOR
+Stack now 0
+]])
+
+AT_CLEANUP