diff --git a/ChangeLog b/ChangeLog index 312796a4..ec110633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2009-12-20 Joel E. Denny + + Fix handling of yychar manipulation in user semantic actions. + The problem was that yacc.c didn't always update the yychar + translation afterwards. However, other skeletons appear to be + fine. glr.c appears to already translate yychar before every + use. lalr1.cc does not define yychar and does not document its + replacement, yyla, for users. It does provide yyclearin, but + that does not manipulate yyla and thus requires no translation + update. In lalr1.java, yychar is out of scope during semantic + actions. + * NEWS (2.5): Document. + * data/yacc.c (YYBACKUP): Don't bother translating yychar into + yytoken here. + (yyparse, yypush_parse): Instead, translate before every use of + yytoken, and add comments explaining this approach. + * tests/actions.at (Destroying lookahead assigned by semantic + action): New test group checking that translation happens before + lookahead destructor calls at parser return. Previously, + incorrect destructors were called. + * tests/conflicts.at (%error-verbose and consistent + errors): New test group checking that translation happens at + syntax error detection before the associated verbose error + message and the associated lookahead destructor calls. While + the destructor call is fixed by this patch, the verbose error + message is currently incorrect due to another bug (see + comments in test group), so this is an expected failure for now. + 2009-12-21 Joel E. Denny YYFAIL: warn about uses and remove from lalr1.java. diff --git a/NEWS b/NEWS index d6eed912..7553a861 100644 --- a/NEWS +++ b/NEWS @@ -173,6 +173,13 @@ Bison News were resolved with %nonassoc. Such tokens are now properly omitted from the list. +** Destructor calls fixed for lookaheads altered in semantic actions. + + Previously for deterministic parsers in C, if a user semantic action + altered yychar, the parser in some cases used the old yychar value to + determine which destructor to call for the lookahead upon a syntax + error or upon parser return. This bug has been fixed. + * Changes in version 2.4.2 (????-??-??): ** Detection of GNU M4 1.4.6 or newer during configure is improved. diff --git a/data/yacc.c b/data/yacc.c index 357539e4..fc74e58a 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -698,7 +698,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -1495,6 +1494,17 @@ yyreduce: ]b4_user_actions[ default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1523,6 +1533,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1675,8 +1689,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); diff --git a/src/parse-gram.c b/src/parse-gram.c index 2fe9c9ac..19038b32 100644 --- a/src/parse-gram.c +++ b/src/parse-gram.c @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.4.1.171-692d. */ +/* A Bison parser, made by GNU Bison 2.4.1.173-62efdd. */ /* Skeleton implementation for Bison's Yacc-like parsers in C @@ -45,7 +45,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1.171-692d" +#define YYBISON_VERSION "2.4.1.173-62efdd" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -927,7 +927,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -1050,165 +1049,165 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) { case 3: /* "\"string\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 184 "parse-gram.y" { fputs (quotearg_style (c_quoting_style, (yyvaluep->chars)), stderr); }; -/* Line 799 of yacc.c */ -#line 1059 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1058 "parse-gram.c" break; case 4: /* "\"integer\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 196 "parse-gram.y" { fprintf (stderr, "%d", (yyvaluep->integer)); }; -/* Line 799 of yacc.c */ -#line 1068 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1067 "parse-gram.c" break; case 43: /* "\"{...}\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->code)); }; -/* Line 799 of yacc.c */ -#line 1077 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1076 "parse-gram.c" break; case 44: /* "\"[identifier]\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 191 "parse-gram.y" { fprintf (stderr, "[%s]", (yyvaluep->uniqstr)); }; -/* Line 799 of yacc.c */ -#line 1086 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1085 "parse-gram.c" break; case 45: /* "\"char\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 178 "parse-gram.y" { fputs (char_name ((yyvaluep->character)), stderr); }; -/* Line 799 of yacc.c */ -#line 1095 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1094 "parse-gram.c" break; case 46: /* "\"epilogue\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 799 of yacc.c */ -#line 1104 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1103 "parse-gram.c" break; case 48: /* "\"identifier\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 190 "parse-gram.y" { fputs ((yyvaluep->uniqstr), stderr); }; -/* Line 799 of yacc.c */ -#line 1113 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1112 "parse-gram.c" break; case 49: /* "\"identifier:\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 192 "parse-gram.y" { fprintf (stderr, "%s:", (yyvaluep->uniqstr)); }; -/* Line 799 of yacc.c */ -#line 1122 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1121 "parse-gram.c" break; case 52: /* "\"%{...%}\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 799 of yacc.c */ -#line 1131 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1130 "parse-gram.c" break; case 54: /* "\"type\"" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 193 "parse-gram.y" { fprintf (stderr, "<%s>", (yyvaluep->uniqstr)); }; -/* Line 799 of yacc.c */ -#line 1140 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1139 "parse-gram.c" break; case 71: /* "symbol.prec" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 799 of yacc.c */ -#line 1149 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1148 "parse-gram.c" break; case 84: /* "variable" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 190 "parse-gram.y" { fputs ((yyvaluep->uniqstr), stderr); }; -/* Line 799 of yacc.c */ -#line 1158 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1157 "parse-gram.c" break; case 85: /* "content.opt" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 799 of yacc.c */ -#line 1167 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1166 "parse-gram.c" break; case 86: /* "braceless" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 799 of yacc.c */ -#line 1176 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1175 "parse-gram.c" break; case 87: /* "id" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 799 of yacc.c */ -#line 1185 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1184 "parse-gram.c" break; case 88: /* "id_colon" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 200 "parse-gram.y" { fprintf (stderr, "%s:", (yyvaluep->symbol)->tag); }; -/* Line 799 of yacc.c */ -#line 1194 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1193 "parse-gram.c" break; case 89: /* "symbol" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 799 of yacc.c */ -#line 1203 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1202 "parse-gram.c" break; case 90: /* "string_as_id" */ -/* Line 799 of yacc.c */ +/* Line 798 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 799 of yacc.c */ -#line 1212 "parse-gram.c" +/* Line 798 of yacc.c */ +#line 1211 "parse-gram.c" break; default: break; @@ -1735,7 +1734,7 @@ YYLTYPE yylloc; /* User initialization code. */ -/* Line 1282 of yacc.c */ +/* Line 1281 of yacc.c */ #line 86 "parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default @@ -1744,8 +1743,8 @@ YYLTYPE yylloc; boundary_set (&yylloc.end, current_file, 1, 1); } -/* Line 1282 of yacc.c */ -#line 1749 "parse-gram.c" +/* Line 1281 of yacc.c */ +#line 1748 "parse-gram.c" yylsp[0] = yylloc; goto yysetstate; @@ -1932,7 +1931,7 @@ yyreduce: { case 6: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 225 "parse-gram.y" { code_props plain_code; @@ -1947,14 +1946,14 @@ yyreduce: case 7: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 234 "parse-gram.y" { debug_flag = true; } break; case 8: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 236 "parse-gram.y" { muscle_percent_define_insert ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), @@ -1964,14 +1963,14 @@ yyreduce: case 9: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 240 "parse-gram.y" { defines_flag = true; } break; case 10: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 242 "parse-gram.y" { defines_flag = true; @@ -1981,42 +1980,42 @@ yyreduce: case 11: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 246 "parse-gram.y" { error_verbose = true; } break; case 12: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 247 "parse-gram.y" { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 13: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 248 "parse-gram.y" { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 14: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 249 "parse-gram.y" { spec_file_prefix = (yyvsp[(2) - (2)].chars); } break; case 15: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 250 "parse-gram.y" { spec_file_prefix = (yyvsp[(3) - (3)].chars); } break; case 16: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 252 "parse-gram.y" { nondeterministic_parser = true; @@ -2026,7 +2025,7 @@ yyreduce: case 17: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 257 "parse-gram.y" { code_props action; @@ -2040,77 +2039,77 @@ yyreduce: case 18: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 265 "parse-gram.y" { language_argmatch ((yyvsp[(2) - (2)].chars), grammar_prio, (yylsp[(1) - (2)])); } break; case 19: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 266 "parse-gram.y" { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 20: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 267 "parse-gram.y" { locations_flag = true; } break; case 21: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 268 "parse-gram.y" { spec_name_prefix = (yyvsp[(2) - (2)].chars); } break; case 22: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 269 "parse-gram.y" { spec_name_prefix = (yyvsp[(3) - (3)].chars); } break; case 23: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 270 "parse-gram.y" { no_lines_flag = true; } break; case 24: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 271 "parse-gram.y" { nondeterministic_parser = true; } break; case 25: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 272 "parse-gram.y" { spec_outfile = (yyvsp[(2) - (2)].chars); } break; case 26: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 273 "parse-gram.y" { spec_outfile = (yyvsp[(3) - (3)].chars); } break; case 27: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 274 "parse-gram.y" { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 28: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 276 "parse-gram.y" { /* %pure-parser is deprecated in favor of `%define api.pure', so use @@ -2130,14 +2129,14 @@ yyreduce: case 29: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 290 "parse-gram.y" { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); } break; case 30: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 292 "parse-gram.y" { char const *skeleton_user = (yyvsp[(2) - (2)].chars); @@ -2166,28 +2165,28 @@ yyreduce: case 31: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 315 "parse-gram.y" { token_table_flag = true; } break; case 32: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 316 "parse-gram.y" { report_flag |= report_states; } break; case 33: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 317 "parse-gram.y" { yacc_flag = true; } break; case 37: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 325 "parse-gram.y" { grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); @@ -2196,7 +2195,7 @@ yyreduce: case 38: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 329 "parse-gram.y" { symbol_list *list; @@ -2208,7 +2207,7 @@ yyreduce: case 39: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 336 "parse-gram.y" { symbol_list *list; @@ -2220,7 +2219,7 @@ yyreduce: case 40: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 343 "parse-gram.y" { default_prec = true; @@ -2229,7 +2228,7 @@ yyreduce: case 41: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 347 "parse-gram.y" { default_prec = false; @@ -2238,7 +2237,7 @@ yyreduce: case 42: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 351 "parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes @@ -2250,7 +2249,7 @@ yyreduce: case 43: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 358 "parse-gram.y" { muscle_percent_code_grow ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)])); @@ -2260,21 +2259,21 @@ yyreduce: case 44: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 372 "parse-gram.y" {} break; case 45: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 373 "parse-gram.y" { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 46: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 378 "parse-gram.y" { union_seen = true; @@ -2285,14 +2284,14 @@ yyreduce: case 47: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 389 "parse-gram.y" { current_class = nterm_sym; } break; case 48: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 390 "parse-gram.y" { current_class = unknown_sym; @@ -2302,14 +2301,14 @@ yyreduce: case 49: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 394 "parse-gram.y" { current_class = token_sym; } break; case 50: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 395 "parse-gram.y" { current_class = unknown_sym; @@ -2319,7 +2318,7 @@ yyreduce: case 51: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 400 "parse-gram.y" { symbol_list *list; @@ -2332,7 +2331,7 @@ yyreduce: case 52: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 411 "parse-gram.y" { symbol_list *list; @@ -2349,126 +2348,126 @@ yyreduce: case 53: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 425 "parse-gram.y" { (yyval.assoc) = left_assoc; } break; case 54: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 426 "parse-gram.y" { (yyval.assoc) = right_assoc; } break; case 55: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 427 "parse-gram.y" { (yyval.assoc) = non_assoc; } break; case 56: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 431 "parse-gram.y" { current_type = NULL; } break; case 57: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 432 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; } break; case 58: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 438 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 59: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 440 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); } break; case 60: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 444 "parse-gram.y" { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); } break; case 61: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 445 "parse-gram.y" { (yyval.symbol) = (yyvsp[(1) - (2)].symbol); symbol_user_token_number_set ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].integer), (yylsp[(2) - (2)])); } break; case 62: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 451 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 63: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 453 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); } break; case 64: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 457 "parse-gram.y" { (yyval.list) = (yyvsp[(1) - (1)].list); } break; case 65: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 458 "parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); } break; case 66: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 462 "parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); } break; case 67: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 463 "parse-gram.y" { (yyval.list) = symbol_list_type_new ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 68: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 464 "parse-gram.y" { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); } break; case 69: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 465 "parse-gram.y" { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); } break; case 70: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 471 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); @@ -2478,7 +2477,7 @@ yyreduce: case 71: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 476 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true); @@ -2488,7 +2487,7 @@ yyreduce: case 72: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 481 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2499,7 +2498,7 @@ yyreduce: case 73: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 487 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2510,7 +2509,7 @@ yyreduce: case 74: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 493 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true); @@ -2522,7 +2521,7 @@ yyreduce: case 81: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 523 "parse-gram.y" { yyerrok; @@ -2531,7 +2530,7 @@ yyreduce: case 82: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 529 "parse-gram.y" { current_lhs = (yyvsp[(1) - (2)].symbol); current_lhs_location = (yylsp[(1) - (2)]); current_lhs_named_ref = (yyvsp[(2) - (2)].named_ref); } @@ -2539,21 +2538,21 @@ yyreduce: case 84: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 534 "parse-gram.y" { grammar_current_rule_end ((yylsp[(1) - (1)])); } break; case 85: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 535 "parse-gram.y" { grammar_current_rule_end ((yylsp[(3) - (3)])); } break; case 87: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 541 "parse-gram.y" { grammar_current_rule_begin (current_lhs, current_lhs_location, current_lhs_named_ref); } @@ -2561,77 +2560,77 @@ yyreduce: case 88: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 544 "parse-gram.y" { grammar_current_rule_symbol_append ((yyvsp[(2) - (3)].symbol), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); } break; case 89: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 546 "parse-gram.y" { grammar_current_rule_action_append ((yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); } break; case 90: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 548 "parse-gram.y" { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); } break; case 91: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 550 "parse-gram.y" { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); } break; case 92: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 552 "parse-gram.y" { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); } break; case 93: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 556 "parse-gram.y" { (yyval.named_ref) = 0; } break; case 94: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 558 "parse-gram.y" { (yyval.named_ref) = named_ref_new((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 96: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 570 "parse-gram.y" { (yyval.uniqstr) = uniqstr_new ((yyvsp[(1) - (1)].chars)); } break; case 97: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 575 "parse-gram.y" { (yyval.chars) = ""; } break; case 98: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 576 "parse-gram.y" { (yyval.chars) = (yyvsp[(1) - (1)].uniqstr); } break; case 100: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 587 "parse-gram.y" { code_props plain_code; @@ -2645,14 +2644,14 @@ yyreduce: case 101: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 607 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 102: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 609 "parse-gram.y" { (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)])); @@ -2663,14 +2662,14 @@ yyreduce: case 103: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 617 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 106: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 629 "parse-gram.y" { (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)])); @@ -2680,7 +2679,7 @@ yyreduce: case 108: -/* Line 1495 of yacc.c */ +/* Line 1494 of yacc.c */ #line 638 "parse-gram.y" { code_props plain_code; @@ -2694,10 +2693,21 @@ yyreduce: -/* Line 1495 of yacc.c */ -#line 2699 "parse-gram.c" +/* Line 1494 of yacc.c */ +#line 2698 "parse-gram.c" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2726,6 +2736,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -2878,8 +2892,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2904,7 +2923,7 @@ yyreturn: -/* Line 1706 of yacc.c */ +/* Line 1725 of yacc.c */ #line 648 "parse-gram.y" diff --git a/src/parse-gram.h b/src/parse-gram.h index 8bd4bc3d..d307aa08 100644 --- a/src/parse-gram.h +++ b/src/parse-gram.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.4.1.171-692d. */ +/* A Bison parser, made by GNU Bison 2.4.1.173-62efdd. */ /* Skeleton interface for Bison's Yacc-like parsers in C @@ -161,7 +161,7 @@ typedef union YYSTYPE { -/* Line 1707 of yacc.c */ +/* Line 1726 of yacc.c */ #line 94 "parse-gram.y" symbol *symbol; @@ -176,7 +176,7 @@ typedef union YYSTYPE -/* Line 1707 of yacc.c */ +/* Line 1726 of yacc.c */ #line 181 "parse-gram.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 diff --git a/tests/actions.at b/tests/actions.at index dd57b080..4833a4fb 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -1408,3 +1408,74 @@ AT_MATCHES_CHECK([input.c], [[// TEST:Y:1 [;{}]*\n;\}$]], [[12]]) AT_MATCHES_CHECK([input.c], [[#define TEST_MACRO_N \\\n\[\]"broken\\" \$ \@ \$\$ \@\$ \[\];\\\nstring;"\}]], [[2]]) AT_CLEANUP + + +## -------------------------------------------------- ## +## Destroying lookahead assigned by semantic action. ## +## -------------------------------------------------- ## + +AT_SETUP([[Destroying lookahead assigned by semantic action]]) + +AT_DATA_GRAMMAR([input.y], +[[ +%code { + #include + #include + static void yyerror (char const *); + static int yylex (void); + #define USE(Var) +} + +%destructor { fprintf (stderr, "'a' destructor\n"); } 'a' +%destructor { fprintf (stderr, "'b' destructor\n"); } 'b' + +%% + +// In a previous version of Bison, yychar assigned by the semantic +// action below was not translated into yytoken before the lookahead was +// discarded and thus before its destructor (selected according to +// yytoken) was called in order to return from yyparse. This would +// happen even if YYACCEPT was performed in a later semantic action as +// long as only consistent states with default reductions were visited +// in between. However, we leave YYACCEPT in the same semantic action +// for this test in order to show that skeletons cannot simply translate +// immediately after every semantic action because a semantic action +// that has set yychar might not always return normally. Instead, +// skeletons must translate before every use of yytoken. +start: 'a' accept { USE($1); } ; +accept: /*empty*/ { + assert (yychar == YYEMPTY); + yychar = 'b'; + YYACCEPT; +} ; + +%% + +static void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +static int +yylex (void) +{ + static char const *input = "a"; + return *input++; +} + +int +main (void) +{ + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-o input.c input.y]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[0]], [], +[['b' destructor +'a' destructor +]]) + +AT_CLEANUP diff --git a/tests/conflicts.at b/tests/conflicts.at index 6fefea05..18877296 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -139,6 +139,130 @@ AT_CLEANUP +## -------------------------------------- ## +## %error-verbose and consistent errors. ## +## -------------------------------------- ## + +AT_SETUP([[%error-verbose and consistent errors]]) + +m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [ + +AT_BISON_CHECK([$1[ -o input.c input.y]]) +AT_COMPILE([[input]]) + +m4_pushdef([AT_EXPECTING], [m4_if($3, [ab], [[, expecting 'a' or 'b']], + $3, [a], [[, expecting 'a']], + $3, [b], [[, expecting 'b']])]) + +AT_PARSER_CHECK([[./input]], [[1]], [], +[[syntax error, unexpected ]$2[]AT_EXPECTING[ +]]) + +m4_popdef([AT_EXPECTING]) + +]) + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include + #include + int yylex (void); + void yyerror (char const *); + #define USE(Var) +} + +%error-verbose + +// The point isn't to test IELR here, but state merging happens to +// complicate the example. +%define lr.type ielr + +%nonassoc 'a' + +// If yylval=0 here, then we know that the 'a' destructor is being +// invoked incorrectly for the 'b' set in the semantic action below. +// All 'a' tokens are returned by yylex, which sets yylval=1. +%destructor { + if (!$$) + fprintf (stderr, "Wrong destructor.\n"); +} 'a' + +%% + +// The lookahead assigned by the semantic action isn't needed before +// either error action is encountered. In a previous version of Bison, +// this was a problem as it meant yychar was not translated into yytoken +// before either error action. The second error action thus invoked a +// destructor that it selected according to the incorrect yytoken. The +// first error action would have reported an incorrect unexpected token +// except that, due to another bug, the unexpected token is not reported +// at all because the error action is the default action in a consistent +// state. That bug still needs to be fixed. +start: error-reduce consistent-error 'a' { USE ($3); } ; + +error-reduce: + 'a' 'a' consistent-reduction consistent-error 'a' + { USE (($1, $2, $5)); } +| 'a' error + { USE ($1); } +; + +consistent-reduction: /*empty*/ { + assert (yychar == YYEMPTY); + yylval = 0; + yychar = 'b'; +} ; + +consistent-error: + 'a' { USE ($1); } +| /*empty*/ %prec 'a' +; + +// Provide another context in which all rules are useful so that this +// test case looks a little more realistic. +start: 'b' consistent-error 'b' ; + +%% + +int +yylex (void) +{ + static char const *input = "aa"; + yylval = 1; + return *input++; +} + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +main (void) +{ + return yyparse (); +} +]]) + +# See comments in grammar for why this test doesn't succeed. +AT_XFAIL_IF([[:]]) + +AT_CONSISTENT_ERRORS_CHECK([], [['b']], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[-Dlr.default-reductions=consistent]], + [['b']], [[none]]) + +# Canonical LR doesn't foresee the error for 'a'! +AT_CONSISTENT_ERRORS_CHECK([[-Dlr.default-reductions=accepting]], + [[$end]], [[a]]) +AT_CONSISTENT_ERRORS_CHECK([[-Flr.type=canonical-lr]], [[$end]], [[a]]) + +m4_popdef([AT_CONSISTENT_ERRORS_CHECK]) + +AT_CLEANUP + + + ## ------------------------- ## ## Unresolved SR Conflicts. ## ## ------------------------- ##