From: Joel E. Denny <joeldenny@joeldenny.org> Date: Sat, 11 Dec 2010 16:13:33 +0000 (-0500) Subject: parse.lac: implement as %define variable. X-Git-Tag: v2.5_rc1~51 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/ea13bea8ab1c8da513e065f8ba21216616203a4a parse.lac: implement as %define variable. LAC = lookahead correction. See discussion at <http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00034.html>. However, one point there must be corrected: because of %nonassoc, LAC is *not* always redundant for lr.type=canonical-lr. * data/yacc.c: Accept values of "none" (default) or "full" for parse.lac. Accept %define parse.lac.es-capacity to specify capacity of LAC's temporary exploratory stack. It defaults to 20 and, for now, will not grow dynamically. (b4_lac_flag, b4_lac_if): New m4 macros. Evaluate as true for parse.lac!=none. (YYBACKUP): Invoke YY_LAC_DISCARD. (YY_LAC_ESTABLISH, YY_LAC_DISCARD): New cpp macros that invoke yy_lac and track when it needs to be invoked (yy_lac): New function that, given the current stack, determines whether a token can eventually be shifted. Return status mimics yyparse return status. (yysyntax_error): Change yystate argument to yyssp so stack top can be passed to yy_lac. If LAC is requested, build expected token list by invoking yy_lac for every token instead of just checking the current state for lookaheads. Return 2 if yy_lac exhausts memory. (yyparse, yypush_parse): Use local variable yy_lac_established and cpp macros YY_LAC_ESTABLISH and YY_LAC_DISCARD to implement LAC. Update yysyntax_error invocation. Add yyexhaustedlab code if LAC is requested. * tests/conflicts.at (%nonassoc and eof): Extend to check the effect of each of -Dlr.type=canonical-lr and -Dparse.lac=full. (%error-verbose and consistent errors): Likewise. (LAC: %nonassoc requires splitting canonical LR states): New test group demonstrating how LAC can fix canonical LR. * tests/input.at (LAC: Errors for %define): New test group. * tests/regression.at (LAC: Exploratory stack): New test group. (LAC: Memory exhaustion): New test group. (cherry picked from commit bf35c71c5827d735c125ee25b048eabf40960a55) Conflicts: src/parse-gram.c src/parse-gram.h --- diff --git a/ChangeLog b/ChangeLog index 3c6df27f..017deb6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2010-12-11 Joel E. Denny <jdenny@clemson.edu> + + parse.lac: implement as %define variable. + LAC = lookahead correction. See discussion at + <http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00034.html>. + However, one point there must be corrected: because of %nonassoc, + LAC is *not* always redundant for lr.type=canonical-lr. + * data/yacc.c: Accept values of "none" (default) or "full" for + parse.lac. Accept %define parse.lac.es-capacity to specify + capacity of LAC's temporary exploratory stack. It defaults to 20 + and, for now, will not grow dynamically. + (b4_lac_flag, b4_lac_if): New m4 macros. Evaluate as true for + parse.lac!=none. + (YYBACKUP): Invoke YY_LAC_DISCARD. + (YY_LAC_ESTABLISH, YY_LAC_DISCARD): New cpp macros that invoke + yy_lac and track when it needs to be invoked + (yy_lac): New function that, given the current stack, determines + whether a token can eventually be shifted. Return status mimics + yyparse return status. + (yysyntax_error): Change yystate argument to yyssp so stack top + can be passed to yy_lac. If LAC is requested, build expected + token list by invoking yy_lac for every token instead of just + checking the current state for lookaheads. Return 2 if yy_lac + exhausts memory. + (yyparse, yypush_parse): Use local variable yy_lac_established and + cpp macros YY_LAC_ESTABLISH and YY_LAC_DISCARD to implement LAC. + Update yysyntax_error invocation. Add yyexhaustedlab code if LAC + is requested. + * tests/conflicts.at (%nonassoc and eof): Extend to check the + effect of each of -Dlr.type=canonical-lr and -Dparse.lac=full. + (%error-verbose and consistent errors): Likewise. + (LAC: %nonassoc requires splitting canonical LR states): New test + group demonstrating how LAC can fix canonical LR. + * tests/input.at (LAC: Errors for %define): New test group. + * tests/regression.at (LAC: Exploratory stack): New test group. + (LAC: Memory exhaustion): New test group. + 2010-11-21 Joel E. Denny <jdenny@clemson.edu> build: use gnulib's new bootstrap_sync option. diff --git a/data/yacc.c b/data/yacc.c index bf804a40..b6758c69 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -36,6 +36,16 @@ b4_use_push_for_pull_if([ b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])], [m4_define([b4_push_flag], [[1]])])]) +# Check the value of %define parse.lac, where LAC stands for lookahead +# correction. +b4_percent_define_default([[parse.lac]], [[none]]) +b4_percent_define_default([[parse.lac.es-capacity]], [[20]]) +b4_percent_define_check_values([[[[parse.lac]], [[full]], [[none]]]]) +b4_define_flag_if([lac]) +m4_define([b4_lac_flag], + [m4_if(b4_percent_define_get([[parse.lac]]), + [none], [[0]], [[1]])]) + m4_include(b4_pkgdatadir/[c.m4]) ## ---------------- ## @@ -697,7 +707,8 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - YYPOPSTACK (1); \ + YYPOPSTACK (1); \]b4_lac_if([[ + YY_LAC_DISCARD ("YYBACKUP"); \]])[ goto yybackup; \ } \ else \ @@ -879,9 +890,173 @@ int yydebug; #ifndef YYMAXDEPTH # define YYMAXDEPTH ]b4_stack_depth_max[ +#endif]b4_lac_if([[ + +/* Establish the initial context for the current lookahead if no initial + context is currently established. + + We define a context as a snapshot of the parser stacks. We define + the initial context for a lookahead as the context in which the + parser initially examines that lookahead in order to select a + syntactic action. Thus, if the lookahead eventually proves + syntactically unacceptable (possibly in a later context reached via a + series of reductions), the initial context can be used to determine + the exact set of tokens that would be syntactically acceptable in the + lookahead's place. Moreover, it is the context after which any + further semantic actions would be erroneous because they would be + determined by a syntactically unacceptable token. + + YY_LAC_ESTABLISH should be invoked when a reduction is about to be + performed in an inconsistent state (which, for the purposes of LAC, + includes consistent states that don't know they're consistent because + their default reductions have been disabled). Iff there is a + lookahead token, it should also be invoked before reporting a syntax + error. This latter case is for the sake of the debugging output. + + For parse.lac=full, the implementation of YY_LAC_ESTABLISH is as + follows. If no initial context is currently established for the + current lookahead, then check if that lookahead can eventually be + shifted if syntactic actions continue from the current context. + Report a syntax error if it cannot. */ +#define YY_LAC_ESTABLISH \ +do { \ + if (!yy_lac_established) \ + { \ + YYDPRINTF ((stderr, \ + "LAC: initial context established for %s\n", \ + yytname[yytoken])); \ + yy_lac_established = 1; \ + { \ + int yy_lac_status = \ + yy_lac (yyssp, yytoken); \ + if (yy_lac_status == 2) \ + goto yyexhaustedlab; \ + if (yy_lac_status == 1) \ + goto yyerrlab; \ + } \ + } \ +} while (YYID (0)) + +/* Discard any previous initial lookahead context because of Event, + which may be a lookahead change or an invalidation of the currently + established initial context for the current lookahead. + + The most common example of a lookahead change is a shift. An example + of both cases is syntax error recovery. That is, a syntax error + occurs when the lookahead is syntactically erroneous for the + currently established initial context, so error recovery manipulates + the parser stacks to try to find a new initial context in which the + current lookahead is syntactically acceptable. If it fails to find + such a context, it discards the lookahead. */ +#if YYDEBUG +# define YY_LAC_DISCARD(Event) \ +do { \ + if (yy_lac_established) \ + { \ + if (yydebug) \ + YYFPRINTF (stderr, "LAC: initial context discarded due to " \ + Event "\n"); \ + yy_lac_established = 0; \ + } \ +} while (YYID (0)) +#else +# define YY_LAC_DISCARD(Event) yy_lac_established = 0 #endif - +/* Given the stack whose top is *YYSSP, return 0 iff YYTOKEN can + eventually (after perhaps some reductions) be shifted, and return 1 + if not. Return 2 if memory is exhausted. */ +static int +yy_lac (yytype_int16 *yyssp, int yytoken) +{ + yytype_int16 *yyes_prev = yyssp; + yytype_int16 yyes@{]b4_percent_define_get([[parse.lac.es-capacity]])[@}; + yytype_int16 *yyesp = yyes_prev; + YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken])); + if (yytoken == YYUNDEFTOK) + { + YYDPRINTF ((stderr, " Always Err\n")); + return 1; + } + while (1) + { + int yyrule = yypact[*yyesp]; + if (yypact_value_is_default (yyrule) + || (yyrule += yytoken) < 0 || YYLAST < yyrule + || yycheck[yyrule] != yytoken) + { + yyrule = yydefact[*yyesp]; + if (yyrule == 0) + { + YYDPRINTF ((stderr, " Err\n")); + return 1; + } + } + else + { + yyrule = yytable[yyrule]; + if (yytable_value_is_error (yyrule)) + { + YYDPRINTF ((stderr, " Err\n")); + return 1; + } + if (0 < yyrule) + { + YYDPRINTF ((stderr, " S%d\n", yyrule)); + return 0; + } + yyrule = -yyrule; + } + { + YYSIZE_T yylen = yyr2[yyrule]; + YYDPRINTF ((stderr, " R%d", yyrule - 1)); + if (yyesp != yyes_prev) + { + YYSIZE_T yysize = yyesp - yyes + 1; + if (yylen < yysize) + { + yyesp -= yylen; + yylen = 0; + } + else + { + yylen -= yysize; + yyesp = yyes_prev; + } + } + if (yylen) + yyesp = yyes_prev -= yylen; + } + { + int yystate; + { + int yylhs = yyr1[yyrule] - YYNTOKENS; + yystate = yypgoto[yylhs] + *yyesp; + if (yystate < 0 || YYLAST < yystate + || yycheck[yystate] != *yyesp) + yystate = yydefgoto[yylhs]; + else + yystate = yytable[yystate]; + } + if (yyesp == yyes_prev) + { + yyesp = yyes; + *yyesp = yystate; + } + else + { + if (yyesp == yyes + (sizeof yyes / sizeof *yyes) - 1) + { + YYDPRINTF ((stderr, " (max stack size exceeded)\n")); + return 2; + } + *++yyesp = yystate; + } + YYDPRINTF ((stderr, " G%d", *yyesp)); + } + } +}]])[ + #if YYERROR_VERBOSE @@ -970,15 +1145,18 @@ yytnamerr (char *yyres, const char *yystr) # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN while in state YYSTATE. + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP.]b4_lac_if([[ In order to see if a particular token T is a + valid looakhead, invoke yy_lac (YYSSP, T).]])[ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ + required number of bytes is too large to store]b4_lac_if([[ or if + yy_lac returned 2]])[. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - int yystate, int yytoken) + yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); YYSIZE_T yysize = yysize0; @@ -1009,7 +1187,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. + action, or user semantic action that manipulated yychar.]b4_lac_if([[ + In the first two cases, it might appear that the current syntax + error should have been detected in the previous state when yy_lac + was invoked. However, at that time, there might have been a + different syntax error that discarded a different initial context + during error recovery, leaving behind the current lookahead.]], [[ - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the @@ -1017,26 +1200,39 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be - accepted due to an error action in a later state. + accepted due to an error action in a later state.]])[ */ if (yytoken != YYEMPTY) { - int yyn = yypact[yystate]; + int yyn = yypact[*yyssp];]b4_lac_if([[ + YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[ yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) - { + {]b4_lac_if([], [[ /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;]])[ + int yyx;]b4_lac_if([[ + + for (yyx = 0; yyx < YYNTOKENS; ++yyx) + if (yyx != YYTERROR && yyx != YYUNDEFTOK) + { + { + int yy_lac_status = yy_lac (yyssp, yyx); + if (yy_lac_status == 2) + return 2; + if (yy_lac_status == 1) + continue; + }]], [[ + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) - { + {]])[ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; @@ -1050,12 +1246,16 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, return 2; yysize = yysize1; } - } + }]b4_lac_if([[ +# if YYDEBUG + else if (yydebug) + YYFPRINTF (stderr, "No expected tokens.\n"); +# endif]])[ } switch (yycount) { -#define YYCASE_(N, S) \ +# define YYCASE_(N, S) \ case N: \ yyformat = S; \ break @@ -1065,7 +1265,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -#undef YYCASE_ +# undef YYCASE_ } yysize1 = yysize + yystrlen (yyformat); @@ -1103,7 +1303,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, return 0; } #endif /* YYERROR_VERBOSE */ - ]b4_yydestruct_generate([b4_c_function_def])b4_push_if([], [[ @@ -1238,7 +1437,8 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[ YYLTYPE yypushed_loc = yylloc;]]) ])], [b4_declare_parser_state_variables -])[ +])b4_lac_if([[ + int yy_lac_established = 0;]])[ int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ @@ -1445,13 +1645,18 @@ yyread_pushed_token:]])[ /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)]b4_lac_if([[ + { + YY_LAC_ESTABLISH; + goto yydefault; + }]], [[ + goto yydefault;]])[ yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) - goto yyerrlab; + goto yyerrlab;]b4_lac_if([[ + YY_LAC_ESTABLISH;]])[ yyn = -yyn; goto yyreduce; } @@ -1465,7 +1670,8 @@ yyread_pushed_token:]])[ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ - yychar = YYEMPTY; + yychar = YYEMPTY;]b4_lac_if([[ + YY_LAC_DISCARD ("shift");]])[ yystate = yyn; *++yyvsp = yylval; @@ -1503,12 +1709,22 @@ yyreduce: ]b4_locations_if( [[ /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);]])[ - YY_REDUCE_PRINT (yyn); + YY_REDUCE_PRINT (yyn);]b4_lac_if([[ + { + int yychar_backup = yychar; + switch (yyn) + { + ]b4_user_actions[ + default: break; + } + if (yychar_backup != yychar) + YY_LAC_DISCARD ("yychar change"); + }]], [[ switch (yyn) { ]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. @@ -1559,11 +1775,14 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (]b4_yyerror_args[YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yystate, \ +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yyssp, \ yytoken) { char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status = YYSYNTAX_ERROR; + int yysyntax_error_status;]b4_lac_if([[ + if (yychar != YYEMPTY) + YY_LAC_ESTABLISH;]])[ + yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) @@ -1668,7 +1887,11 @@ yyerrlab1: YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); - } + }]b4_lac_if([[ + + /* If the stack popping above didn't lose the initial context for the + current lookahead token, the shift below will for sure. */ + YY_LAC_DISCARD ("error recovery");]])[ *++yyvsp = yylval; ]b4_locations_if([[ @@ -1699,7 +1922,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if ]b4_lac_if([[1]], [[!defined(yyoverflow) || YYERROR_VERBOSE]])[ /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ diff --git a/src/parse-gram.c b/src/parse-gram.c index a06602de..50fc1c60 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.247-0e0f-dirty. */ +/* A Bison parser, made by GNU Bison 2.4.1.252-dcd39. */ /* 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.247-0e0f-dirty" +#define YYBISON_VERSION "2.4.1.252-dcd39" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -74,7 +74,7 @@ /* Copy the first part of user declarations. */ -/* Line 251 of yacc.c */ +/* Line 261 of yacc.c */ #line 1 "parse-gram.y" /* Bison Grammar Parser -*- C -*- @@ -151,7 +151,7 @@ static int current_prec = 0; #define YYTYPE_UINT8 uint_fast8_t -/* Line 251 of yacc.c */ +/* Line 261 of yacc.c */ #line 156 "parse-gram.c" /* Enabling traces. */ @@ -302,7 +302,7 @@ static int current_prec = 0; typedef union YYSTYPE { -/* Line 276 of yacc.c */ +/* Line 286 of yacc.c */ #line 94 "parse-gram.y" symbol *symbol; @@ -317,7 +317,7 @@ typedef union YYSTYPE -/* Line 276 of yacc.c */ +/* Line 286 of yacc.c */ #line 322 "parse-gram.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -342,7 +342,7 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 326 of yacc.c */ +/* Line 336 of yacc.c */ #line 347 "parse-gram.c" #ifdef short @@ -1049,164 +1049,164 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) { case 3: /* "\"string\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 184 "parse-gram.y" { fputs (quotearg_style (c_quoting_style, (yyvaluep->chars)), stderr); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1058 "parse-gram.c" break; case 4: /* "\"integer\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 196 "parse-gram.y" { fprintf (stderr, "%d", (yyvaluep->integer)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1067 "parse-gram.c" break; case 43: /* "\"{...}\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->code)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1076 "parse-gram.c" break; case 44: /* "\"[identifier]\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 191 "parse-gram.y" { fprintf (stderr, "[%s]", (yyvaluep->uniqstr)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1085 "parse-gram.c" break; case 45: /* "\"char\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 178 "parse-gram.y" { fputs (char_name ((yyvaluep->character)), stderr); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1094 "parse-gram.c" break; case 46: /* "\"epilogue\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1103 "parse-gram.c" break; case 48: /* "\"identifier\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 190 "parse-gram.y" { fputs ((yyvaluep->uniqstr), stderr); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1112 "parse-gram.c" break; case 49: /* "\"identifier:\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 192 "parse-gram.y" { fprintf (stderr, "%s:", (yyvaluep->uniqstr)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1121 "parse-gram.c" break; case 52: /* "\"%{...%}\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1130 "parse-gram.c" break; case 54: /* "\"type\"" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 193 "parse-gram.y" { fprintf (stderr, "<%s>", (yyvaluep->uniqstr)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1139 "parse-gram.c" break; case 71: /* "symbol.prec" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1148 "parse-gram.c" break; case 84: /* "variable" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 190 "parse-gram.y" { fputs ((yyvaluep->uniqstr), stderr); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1157 "parse-gram.c" break; case 85: /* "content.opt" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1166 "parse-gram.c" break; case 86: /* "braceless" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 186 "parse-gram.y" { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1175 "parse-gram.c" break; case 87: /* "id" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1184 "parse-gram.c" break; case 88: /* "id_colon" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 200 "parse-gram.y" { fprintf (stderr, "%s:", (yyvaluep->symbol)->tag); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1193 "parse-gram.c" break; case 89: /* "symbol" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1202 "parse-gram.c" break; case 90: /* "string_as_id" */ -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 199 "parse-gram.y" { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); }; -/* Line 797 of yacc.c */ +/* Line 808 of yacc.c */ #line 1211 "parse-gram.c" break; default: @@ -1340,7 +1340,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1444,7 +1443,8 @@ yytnamerr (char *yyres, const char *yystr) # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN while in state YYSTATE. + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set @@ -1452,7 +1452,7 @@ yytnamerr (char *yyres, const char *yystr) required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - int yystate, int yytoken) + yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); YYSIZE_T yysize = yysize0; @@ -1495,7 +1495,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, */ if (yytoken != YYEMPTY) { - int yyn = yypact[yystate]; + int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { @@ -1507,6 +1507,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) @@ -1529,7 +1530,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, switch (yycount) { -#define YYCASE_(N, S) \ +# define YYCASE_(N, S) \ case N: \ yyformat = S; \ break @@ -1539,7 +1540,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -#undef YYCASE_ +# undef YYCASE_ } yysize1 = yysize + yystrlen (yyformat); @@ -1577,7 +1578,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1750,7 +1750,7 @@ YYLTYPE yylloc; /* User initialization code. */ -/* Line 1296 of yacc.c */ +/* Line 1496 of yacc.c */ #line 86 "parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default @@ -1759,7 +1759,7 @@ YYLTYPE yylloc; boundary_set (&yylloc.end, current_file, 1, 1); } -/* Line 1296 of yacc.c */ +/* Line 1496 of yacc.c */ #line 1764 "parse-gram.c" yylsp[0] = yylloc; @@ -1891,7 +1891,7 @@ yybackup: if (yyn <= 0) { if (yytable_value_is_error (yyn)) - goto yyerrlab; + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1947,7 +1947,7 @@ yyreduce: { case 6: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 225 "parse-gram.y" { code_props plain_code; @@ -1962,14 +1962,14 @@ yyreduce: case 7: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 234 "parse-gram.y" { debug_flag = true; } break; case 8: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 236 "parse-gram.y" { muscle_percent_define_insert ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), @@ -1979,14 +1979,14 @@ yyreduce: case 9: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 240 "parse-gram.y" { defines_flag = true; } break; case 10: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 242 "parse-gram.y" { defines_flag = true; @@ -1996,42 +1996,42 @@ yyreduce: case 11: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 246 "parse-gram.y" { error_verbose = true; } break; case 12: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 247 "parse-gram.y" { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 13: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 248 "parse-gram.y" { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); } break; case 14: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 249 "parse-gram.y" { spec_file_prefix = (yyvsp[(2) - (2)].chars); } break; case 15: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 250 "parse-gram.y" { spec_file_prefix = (yyvsp[(3) - (3)].chars); } break; case 16: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 252 "parse-gram.y" { nondeterministic_parser = true; @@ -2041,7 +2041,7 @@ yyreduce: case 17: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 257 "parse-gram.y" { code_props action; @@ -2055,77 +2055,77 @@ yyreduce: case 18: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 265 "parse-gram.y" { language_argmatch ((yyvsp[(2) - (2)].chars), grammar_prio, (yylsp[(1) - (2)])); } break; case 19: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 266 "parse-gram.y" { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 20: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 267 "parse-gram.y" { locations_flag = true; } break; case 21: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 268 "parse-gram.y" { spec_name_prefix = (yyvsp[(2) - (2)].chars); } break; case 22: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 269 "parse-gram.y" { spec_name_prefix = (yyvsp[(3) - (3)].chars); } break; case 23: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 270 "parse-gram.y" { no_lines_flag = true; } break; case 24: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 271 "parse-gram.y" { nondeterministic_parser = true; } break; case 25: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 272 "parse-gram.y" { spec_outfile = (yyvsp[(2) - (2)].chars); } break; case 26: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 273 "parse-gram.y" { spec_outfile = (yyvsp[(3) - (3)].chars); } break; case 27: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 274 "parse-gram.y" { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); } break; case 28: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 276 "parse-gram.y" { /* %pure-parser is deprecated in favor of `%define api.pure', so use @@ -2145,14 +2145,14 @@ yyreduce: case 29: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 290 "parse-gram.y" { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); } break; case 30: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 292 "parse-gram.y" { char const *skeleton_user = (yyvsp[(2) - (2)].chars); @@ -2181,28 +2181,28 @@ yyreduce: case 31: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 315 "parse-gram.y" { token_table_flag = true; } break; case 32: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 316 "parse-gram.y" { report_flag |= report_states; } break; case 33: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 317 "parse-gram.y" { yacc_flag = true; } break; case 37: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 325 "parse-gram.y" { grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); @@ -2211,7 +2211,7 @@ yyreduce: case 38: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 329 "parse-gram.y" { symbol_list *list; @@ -2223,7 +2223,7 @@ yyreduce: case 39: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 336 "parse-gram.y" { symbol_list *list; @@ -2235,7 +2235,7 @@ yyreduce: case 40: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 343 "parse-gram.y" { default_prec = true; @@ -2244,7 +2244,7 @@ yyreduce: case 41: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 347 "parse-gram.y" { default_prec = false; @@ -2253,7 +2253,7 @@ yyreduce: case 42: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 351 "parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes @@ -2265,7 +2265,7 @@ yyreduce: case 43: -/* Line 1509 of yacc.c */ +/* Line 1712 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)])); @@ -2275,21 +2275,21 @@ yyreduce: case 44: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 372 "parse-gram.y" {} break; case 45: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 373 "parse-gram.y" { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 46: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 378 "parse-gram.y" { union_seen = true; @@ -2300,14 +2300,14 @@ yyreduce: case 47: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 389 "parse-gram.y" { current_class = nterm_sym; } break; case 48: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 390 "parse-gram.y" { current_class = unknown_sym; @@ -2317,14 +2317,14 @@ yyreduce: case 49: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 394 "parse-gram.y" { current_class = token_sym; } break; case 50: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 395 "parse-gram.y" { current_class = unknown_sym; @@ -2334,7 +2334,7 @@ yyreduce: case 51: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 400 "parse-gram.y" { symbol_list *list; @@ -2347,7 +2347,7 @@ yyreduce: case 52: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 411 "parse-gram.y" { symbol_list *list; @@ -2364,126 +2364,126 @@ yyreduce: case 53: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 425 "parse-gram.y" { (yyval.assoc) = left_assoc; } break; case 54: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 426 "parse-gram.y" { (yyval.assoc) = right_assoc; } break; case 55: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 427 "parse-gram.y" { (yyval.assoc) = non_assoc; } break; case 56: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 431 "parse-gram.y" { current_type = NULL; } break; case 57: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 432 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; } break; case 58: -/* Line 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 444 "parse-gram.y" { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); } break; case 61: -/* Line 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 457 "parse-gram.y" { (yyval.list) = (yyvsp[(1) - (1)].list); } break; case 65: -/* Line 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 464 "parse-gram.y" { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); } break; case 69: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 465 "parse-gram.y" { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); } break; case 70: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 471 "parse-gram.y" { current_type = (yyvsp[(1) - (1)].uniqstr); @@ -2493,7 +2493,7 @@ yyreduce: case 71: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 476 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true); @@ -2503,7 +2503,7 @@ yyreduce: case 72: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 481 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2514,7 +2514,7 @@ yyreduce: case 73: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 487 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true); @@ -2525,7 +2525,7 @@ yyreduce: case 74: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 493 "parse-gram.y" { symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true); @@ -2537,7 +2537,7 @@ yyreduce: case 81: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 523 "parse-gram.y" { yyerrok; @@ -2546,7 +2546,7 @@ yyreduce: case 82: -/* Line 1509 of yacc.c */ +/* Line 1712 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); } @@ -2554,21 +2554,21 @@ yyreduce: case 84: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 534 "parse-gram.y" { grammar_current_rule_end ((yylsp[(1) - (1)])); } break; case 85: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 535 "parse-gram.y" { grammar_current_rule_end ((yylsp[(3) - (3)])); } break; case 87: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 541 "parse-gram.y" { grammar_current_rule_begin (current_lhs, current_lhs_location, current_lhs_named_ref); } @@ -2576,77 +2576,77 @@ yyreduce: case 88: -/* Line 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 548 "parse-gram.y" { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); } break; case 91: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 550 "parse-gram.y" { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); } break; case 92: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 552 "parse-gram.y" { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); } break; case 93: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 556 "parse-gram.y" { (yyval.named_ref) = 0; } break; case 94: -/* Line 1509 of yacc.c */ +/* Line 1712 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 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 570 "parse-gram.y" { (yyval.uniqstr) = uniqstr_new ((yyvsp[(1) - (1)].chars)); } break; case 97: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 575 "parse-gram.y" { (yyval.chars) = ""; } break; case 98: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 576 "parse-gram.y" { (yyval.chars) = (yyvsp[(1) - (1)].uniqstr); } break; case 100: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 587 "parse-gram.y" { code_props plain_code; @@ -2660,14 +2660,14 @@ yyreduce: case 101: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 607 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 102: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 609 "parse-gram.y" { (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)])); @@ -2678,14 +2678,14 @@ yyreduce: case 103: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 617 "parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); } break; case 106: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 629 "parse-gram.y" { (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)])); @@ -2695,7 +2695,7 @@ yyreduce: case 108: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 638 "parse-gram.y" { code_props plain_code; @@ -2709,7 +2709,7 @@ yyreduce: -/* Line 1509 of yacc.c */ +/* Line 1712 of yacc.c */ #line 2714 "parse-gram.c" default: break; } @@ -2763,11 +2763,12 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yystate, \ +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yyssp, \ yytoken) { char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status = YYSYNTAX_ERROR; + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) @@ -2946,7 +2947,7 @@ yyreturn: -/* Line 1747 of yacc.c */ +/* Line 1970 of yacc.c */ #line 648 "parse-gram.y" diff --git a/src/parse-gram.h b/src/parse-gram.h index eba94171..325cf245 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.247-0e0f-dirty. */ +/* A Bison parser, made by GNU Bison 2.4.1.252-dcd39. */ /* Skeleton interface for Bison's Yacc-like parsers in C @@ -161,7 +161,7 @@ typedef union YYSTYPE { -/* Line 1748 of yacc.c */ +/* Line 1971 of yacc.c */ #line 94 "parse-gram.y" symbol *symbol; @@ -176,7 +176,7 @@ typedef union YYSTYPE -/* Line 1748 of yacc.c */ +/* Line 1971 of yacc.c */ #line 181 "parse-gram.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 diff --git a/tests/conflicts.at b/tests/conflicts.at index f455d1f5..37411699 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -94,46 +94,52 @@ main (int argc, const char *argv[]) } ]]) -# Specify the output files to avoid problems on different file systems. -AT_BISON_CHECK([-o input.c input.y]) +m4_pushdef([AT_NONASSOC_AND_EOF_CHECK], +[AT_BISON_CHECK([$1[ -o input.c input.y]]) AT_COMPILE([input]) +m4_pushdef([AT_EXPECTING], [m4_if($2, [correct], [[, expecting $end]])]) + AT_PARSER_CHECK([./input '0<0']) AT_PARSER_CHECK([./input '0<0<0'], [1], [], - [syntax error, unexpected '<' + [syntax error, unexpected '<'AT_EXPECTING ]) AT_PARSER_CHECK([./input '0>0']) AT_PARSER_CHECK([./input '0>0>0'], [1], [], - [syntax error, unexpected '>' + [syntax error, unexpected '>'AT_EXPECTING ]) AT_PARSER_CHECK([./input '0<0>0'], [1], [], - [syntax error, unexpected '>' + [syntax error, unexpected '>'AT_EXPECTING ]) -# We must disable default reductions in inconsistent states in order to -# have an explicit list of all expected tokens. (However, unless we use -# canonical LR, lookahead sets are merged for different left contexts, -# so it is still possible to have extra incorrect tokens in the expected -# list. That just doesn't happen to be a problem for this test case.) - -AT_BISON_CHECK([-Dlr.default-reductions=consistent -o input.c input.y]) -AT_COMPILE([input]) - -AT_PARSER_CHECK([./input '0<0']) -AT_PARSER_CHECK([./input '0<0<0'], [1], [], - [syntax error, unexpected '<', expecting $end -]) +m4_popdef([AT_EXPECTING])]) -AT_PARSER_CHECK([./input '0>0']) -AT_PARSER_CHECK([./input '0>0>0'], [1], [], - [syntax error, unexpected '>', expecting $end -]) +# Expected token list is missing. +AT_NONASSOC_AND_EOF_CHECK([], [[incorrect]]) -AT_PARSER_CHECK([./input '0<0>0'], [1], [], - [syntax error, unexpected '>', expecting $end -]) +# We must disable default reductions in inconsistent states in order to +# have an explicit list of all expected tokens. +AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reductions=consistent]], + [[correct]]) + +# lr.default-reductions=consistent happens to work for this test case. +# However, for other grammars, lookahead sets can be merged for +# different left contexts, so it is still possible to have an incorrect +# expected list. Canonical LR is almost a general solution (that is, it +# can fail only when %nonassoc is used), so make sure it gives the same +# result as above. +AT_NONASSOC_AND_EOF_CHECK([[-Dlr.type=canonical-lr]], [[correct]]) + +# parse.lac=full is a completely general solution that does not require +# any of the above sacrifices. Of course, it does not extend the +# language-recognition power of LALR to (IE)LR, but it does ensure that +# the reported list of expected tokens matches what the given parser +# would have accepted in place of the unexpected token. +AT_NONASSOC_AND_EOF_CHECK([[-Dparse.lac=full]], [[correct]]) + +m4_popdef([AT_NONASSOC_AND_EOF_CHECK]) AT_CLEANUP @@ -343,6 +349,18 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], [AT_PREVIOUS_STATE_INPUT], [[$end]], [[ab]]) +# Only LAC gets it right. +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr + %define parse.lac full]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[b]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %define parse.lac full]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[b]]) + m4_popdef([AT_PREVIOUS_STATE_GRAMMAR]) m4_popdef([AT_PREVIOUS_STATE_INPUT]) @@ -422,6 +440,16 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], [AT_USER_ACTION_INPUT], [[$end]], [[a]]) +AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [['b']], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full + %define lr.default-reductions accepting]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [[$end]], [[none]]) + m4_popdef([AT_USER_ACTION_GRAMMAR]) m4_popdef([AT_USER_ACTION_INPUT]) @@ -431,6 +459,113 @@ AT_CLEANUP +## ------------------------------------------------------- ## +## LAC: %nonassoc requires splitting canonical LR states. ## +## ------------------------------------------------------- ## + +# This test case demonstrates that, when %nonassoc is used, canonical +# LR(1) parser table construction followed by conflict resolution +# without further state splitting is not always sufficient to produce a +# parser that can detect all syntax errors as soon as possible on one +# token of lookahead. However, LAC solves the problem completely even +# with minimal LR parser tables. + +AT_SETUP([[LAC: %nonassoc requires splitting canonical LR states]]) + +AT_DATA_GRAMMAR([[input.y]], +[[%code { + #include <stdio.h> + void yyerror (char const *); + int yylex (void); +} + +%error-verbose +%nonassoc 'a' + +%% + +start: + 'a' problem 'a' // First context. +| 'b' problem 'b' // Second context. +| 'c' reduce-nonassoc // Just makes reduce-nonassoc useful. +; + +problem: + look reduce-nonassoc +| look 'a' +| look 'b' +; + +// For the state reached after shifting the 'a' in these productions, +// lookahead sets are the same in both the first and second contexts. +// Thus, canonical LR reuses the same state for both contexts. However, +// the lookahead 'a' for the reduction "look: 'a'" later becomes an +// error action only in the first context. In order to immediately +// detect the syntax error on 'a' here for only the first context, this +// canonical LR state would have to be split into two states, and the +// 'a' lookahead would have to be removed from only one of the states. +look: + 'a' // Reduction lookahead set is always ['a', 'b']. +| 'a' 'b' +| 'a' 'c' // 'c' is forgotten as an expected token. +; + +reduce-nonassoc: %prec 'a'; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + char const *input = "aaa"; + return *input++; +} + +int +main (void) +{ + return yyparse (); +} +]]) + +# Show canonical LR's failure. +AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]], + [[0]], [[]], +[[input.y: conflicts: 2 shift/reduce +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[1]], [[]], +[[syntax error, unexpected 'a', expecting 'b' +]]) + +# It's corrected by LAC. +AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \ + -o input.c input.y]], [[0]], [[]], +[[input.y: conflicts: 2 shift/reduce +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[1]], [[]], +[[syntax error, unexpected 'a', expecting 'b' or 'c' +]]) + +# IELR is sufficient when LAC is used. +AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]], + [[0]], [[]], +[[input.y: conflicts: 2 shift/reduce +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input]], [[1]], [[]], +[[syntax error, unexpected 'a', expecting 'b' or 'c' +]]) + +AT_CLEANUP + ## ------------------------- ## ## Unresolved SR Conflicts. ## ## ------------------------- ## diff --git a/tests/input.at b/tests/input.at index 1d50fe02..d59f6f15 100644 --- a/tests/input.at +++ b/tests/input.at @@ -1283,3 +1283,22 @@ input.y:5.19: invalid character after \-escape: \001 ]]) AT_CLEANUP + +## ------------------------- ## +## LAC: Errors for %define. ## +## ------------------------- ## + +AT_SETUP([[LAC: Errors for %define]]) + +AT_DATA([[input.y]], +[[%% +start: ; +]]) + +# parse.lac.* options are useless if LAC isn't actually activated. +AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]], + [[1]], [], +[[<command line>:2: %define variable `parse.lac.es-capacity-initial' is not used +]]) + +AT_CLEANUP diff --git a/tests/regression.at b/tests/regression.at index 544565ad..1157bea9 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -1477,3 +1477,186 @@ memory exhausted ]]) AT_CLEANUP + + + +## ------------------------ ## +## LAC: Exploratory stack. ## +## ------------------------ ## + +AT_SETUP([[LAC: Exploratory stack]]) + +m4_pushdef([AT_LAC_CHECK], [ + +AT_BISON_OPTION_PUSHDEFS([$1]) + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include <stdio.h> + void yyerror (char const *); + int yylex (]AT_PURE_IF([[YYSTYPE *]], [[void]])[); +} + +]$1[ +%error-verbose +%token 'c' + +%% + +// default reductions in inconsistent states +// v v v v v v v v v v v v v v +S: A B A A B A A A A B A A A A A A A B C C A A A A A A A A A A A A B ; + +A: 'a' | /*empty*/ { printf ("inconsistent default reduction\n"); } ; +B: 'b' ; +C: /*empty*/ { printf ("consistent default reduction\n"); } ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (]AT_PURE_IF([[YYSTYPE *v]], [[void]])[) +{ + static char const *input = "bbbbc";]AT_PURE_IF([[ + *v = 0;]])[ + return *input++; +} + +int +main (void) +{ + yydebug = 1; + return yyparse (); +} +]]) + +# Give exactly the right amount of memory to be sure there's no +# off-by-one error, for example. +AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity=12 \ + -t -o input.c input.y]], [[0]], [], +[[input.y: conflicts: 21 shift/reduce +]]) +AT_COMPILE([[input]]) +AT_PARSER_CHECK([[./input > stdout.txt 2> stderr.txt]], [[1]]) + +# Make sure syntax error doesn't forget that 'a' is expected. It would +# be forgotten without lookahead correction. +AT_CHECK([[grep 'syntax error,' stderr.txt]], [[0]], +[[syntax error, unexpected 'c', expecting 'a' or 'b' +]]) + +# Check number of default reductions in inconsistent states to be sure +# syntax error is detected before unnecessary reductions are performed. +AT_CHECK([[perl -0777 -ne 'print s/inconsistent default reduction//g;' \ + < stdout.txt || exit 77]], [[0]], [[14]]) + +# Check number of default reductions in consistent states to be sure +# it is performed before the syntax error is detected. +AT_CHECK([[perl -0777 -ne 'print s/\bconsistent default reduction//g;' \ + < stdout.txt || exit 77]], [[0]], [[2]]) + +AT_BISON_OPTION_POPDEFS +]) + +AT_LAC_CHECK([[%define api.push-pull pull]]) +AT_LAC_CHECK([[%define api.push-pull pull %define api.pure]]) +AT_LAC_CHECK([[%define api.push-pull both]]) +AT_LAC_CHECK([[%define api.push-pull both %define api.pure]]) + +m4_popdef([AT_LAC_CHECK]) + +AT_CLEANUP + + + +## ------------------------ ## +## LAC: Memory exhaustion. ## +## ------------------------ ## + +AT_SETUP([[LAC: Memory exhaustion]]) + +m4_pushdef([AT_LAC_CHECK], [ + +AT_DATA_GRAMMAR([input.y], +[[%code { + #include <stdio.h> + void yyerror (char const *); + int yylex (void); +} + +%error-verbose + +%% + +S: A A A A A A A A A ; +A: /*empty*/ | 'a' ; + +%% + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +yylex (void) +{ + static char const *input = "]$1["; + return *input++; +} + +int +main (void) +{ + yydebug = 1; + return yyparse (); +} +]]) + +AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity=8 \ + -t -o input.c input.y]], [[0]], [], +[[input.y: conflicts: 8 shift/reduce +]]) +AT_COMPILE([[input]]) + +]) + +# Check for memory exhaustion during parsing. +AT_LAC_CHECK([[]]) +AT_PARSER_CHECK([[./input]], [[2]], [[]], +[[Starting parse +Entering state 0 +Reading a token: Now at end of input. +LAC: initial context established for $end +LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max stack size exceeded) +memory exhausted +Cleanup: discarding lookahead token $end () +Stack now 0 +]]) + +# Induce an immediate syntax error with an undefined token, and check +# for memory exhaustion while building syntax error message. +AT_LAC_CHECK([[z]], [[0]]) +AT_PARSER_CHECK([[./input]], [[2]], [[]], +[[Starting parse +Entering state 0 +Reading a token: Next token is token $undefined () +LAC: initial context established for $undefined +LAC: checking lookahead $undefined: Always Err +Constructing syntax error message +LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max stack size exceeded) +syntax error +memory exhausted +Cleanup: discarding lookahead token $undefined () +Stack now 0 +]]) + +m4_popdef([AT_LAC_CHECK]) + +AT_CLEANUP