From: Joel E. Denny Date: Sat, 11 Dec 2010 16:13:33 +0000 (-0500) Subject: parse.lac: implement as %define variable. X-Git-Tag: v2.7.90~647 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/bf35c71c5827d735c125ee25b048eabf40960a55 parse.lac: implement as %define variable. LAC = lookahead correction. See discussion at . 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. (parse.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. --- diff --git a/ChangeLog b/ChangeLog index 154fd350..63d41ed6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2010-12-11 Joel E. Denny + + parse.lac: implement as %define variable. + LAC = lookahead correction. See discussion at + . + 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. + (parse.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 build: use gnulib's new bootstrap_sync option. diff --git a/data/yacc.c b/data/yacc.c index 5cf15eed..5ba564e8 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -38,6 +38,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]) ## ---------------- ## @@ -629,7 +639,8 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - YYPOPSTACK (1); \ + YYPOPSTACK (1); \]b4_lac_if([[ + YY_LAC_DISCARD ("YYBACKUP"); \]])[ goto yybackup; \ } \ else \ @@ -813,9 +824,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 @@ -904,15 +1079,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; @@ -943,7 +1121,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 @@ -951,26 +1134,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; @@ -984,12 +1180,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 @@ -999,7 +1199,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); @@ -1037,7 +1237,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, return 0; } #endif /* YYERROR_VERBOSE */ - ]b4_yydestruct_generate([b4_c_function_def])b4_push_if([], [[ @@ -1172,7 +1371,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. */ @@ -1379,13 +1579,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; } @@ -1399,7 +1604,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; @@ -1437,12 +1643,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. @@ -1493,11 +1709,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) @@ -1602,7 +1821,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([[ @@ -1633,7 +1856,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 f55a15b6..9cf16f9b 100644 --- a/src/parse-gram.c +++ b/src/parse-gram.c @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.4.537-34db. */ +/* A Bison parser, made by GNU Bison 2.4.542-10bae. */ /* Implementation for Bison's Yacc-like parsers in C @@ -45,7 +45,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.537-34db" +#define YYBISON_VERSION "2.4.542-10bae" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -73,7 +73,7 @@ #define yylloc gram_lloc /* Copy the first part of user declarations. */ -/* Line 252 of yacc.c */ +/* Line 262 of yacc.c */ #line 1 "src/parse-gram.y" /* Bison Grammar Parser -*- C -*- @@ -128,7 +128,7 @@ static void gram_error (location const *, char const *); static char const *char_name (char); -/* Line 252 of yacc.c */ +/* Line 262 of yacc.c */ #line 133 "src/parse-gram.c" /* Enabling traces. */ @@ -150,7 +150,7 @@ static char const *char_name (char); #endif /* "%code requires" blocks. */ -/* Line 272 of yacc.c */ +/* Line 282 of yacc.c */ #line 202 "src/parse-gram.y" # ifndef PARAM_TYPE @@ -165,7 +165,7 @@ static char const *char_name (char); # endif -/* Line 272 of yacc.c */ +/* Line 282 of yacc.c */ #line 170 "src/parse-gram.c" /* Tokens. */ @@ -294,7 +294,7 @@ static char const *char_name (char); #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { -/* Line 277 of yacc.c */ +/* Line 287 of yacc.c */ #line 88 "src/parse-gram.y" assoc assoc; @@ -307,13 +307,13 @@ typedef union YYSTYPE uniqstr uniqstr; unsigned char character; -/* Line 277 of yacc.c */ +/* Line 287 of yacc.c */ #line 226 "src/parse-gram.y" param_type param; -/* Line 277 of yacc.c */ +/* Line 287 of yacc.c */ #line 318 "src/parse-gram.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -337,10 +337,10 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 327 of yacc.c */ +/* Line 337 of yacc.c */ #line 342 "src/parse-gram.c" /* Unqualified %code blocks. */ -/* Line 328 of yacc.c */ +/* Line 338 of yacc.c */ #line 56 "src/parse-gram.y" static int current_prec = 0; @@ -355,7 +355,7 @@ typedef struct YYLTYPE #define YYTYPE_UINT16 uint_fast16_t #define YYTYPE_UINT8 uint_fast8_t -/* Line 328 of yacc.c */ +/* Line 338 of yacc.c */ #line 215 "src/parse-gram.y" /** Add a lex-param and/or a parse-param. @@ -368,7 +368,7 @@ typedef struct YYLTYPE static param_type current_param = param_none; -/* Line 328 of yacc.c */ +/* Line 338 of yacc.c */ #line 373 "src/parse-gram.c" #ifdef short @@ -1033,106 +1033,106 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) { case 3: // "string" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 175 "src/parse-gram.y" { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1041 "src/parse-gram.c" break; case 4: // "integer" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 188 "src/parse-gram.y" { fprintf (stderr, "%d", ((*yyvaluep).integer)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1050 "src/parse-gram.c" break; case 24: // "%" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 184 "src/parse-gram.y" { fprintf (stderr, "%%%s", ((*yyvaluep).uniqstr)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1059 "src/parse-gram.c" break; case 40: // "{...}" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 177 "src/parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1068 "src/parse-gram.c" break; case 42: // "[identifier]" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 182 "src/parse-gram.y" { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1077 "src/parse-gram.c" break; case 43: // "char" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 169 "src/parse-gram.y" { fputs (char_name (((*yyvaluep).character)), stderr); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1086 "src/parse-gram.c" break; case 44: // "epilogue" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 177 "src/parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1095 "src/parse-gram.c" break; case 46: // "identifier" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 181 "src/parse-gram.y" { fputs (((*yyvaluep).uniqstr), stderr); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1104 "src/parse-gram.c" break; case 47: // "identifier:" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 183 "src/parse-gram.y" { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1113 "src/parse-gram.c" break; case 50: // "%{...%}" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 177 "src/parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1122 "src/parse-gram.c" break; case 52: // "" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 185 "src/parse-gram.y" { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1131 "src/parse-gram.c" break; case 55: // "%param" -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 231 "src/parse-gram.y" { switch (((*yyvaluep).param)) @@ -1146,79 +1146,79 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) case param_none: aver (false); break; } } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1151 "src/parse-gram.c" break; case 72: // symbol.prec -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 191 "src/parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1160 "src/parse-gram.c" break; case 85: // variable -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 181 "src/parse-gram.y" { fputs (((*yyvaluep).uniqstr), stderr); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1169 "src/parse-gram.c" break; case 86: // content.opt -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 177 "src/parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1178 "src/parse-gram.c" break; case 87: // braceless -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 177 "src/parse-gram.y" { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1187 "src/parse-gram.c" break; case 88: // id -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 191 "src/parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1196 "src/parse-gram.c" break; case 89: // id_colon -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 192 "src/parse-gram.y" { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1205 "src/parse-gram.c" break; case 90: // symbol -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 191 "src/parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1214 "src/parse-gram.c" break; case 91: // string_as_id -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 191 "src/parse-gram.y" { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); } -/* Line 729 of yacc.c */ +/* Line 740 of yacc.c */ #line 1223 "src/parse-gram.c" break; @@ -1355,7 +1355,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1459,7 +1458,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 @@ -1467,7 +1467,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; @@ -1510,7 +1510,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)) { @@ -1522,6 +1522,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])) @@ -1544,7 +1545,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, switch (yycount) { -#define YYCASE_(N, S) \ +# define YYCASE_(N, S) \ case N: \ yyformat = S; \ break @@ -1554,7 +1555,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); @@ -1592,7 +1593,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1765,7 +1765,7 @@ YYLTYPE yylloc; #endif /* User initialization code. */ -/* Line 1230 of yacc.c */ +/* Line 1430 of yacc.c */ #line 80 "src/parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default @@ -1773,7 +1773,7 @@ YYLTYPE yylloc; boundary_set (&yylloc.start, current_file, 1, 1); boundary_set (&yylloc.end, current_file, 1, 1); } -/* Line 1230 of yacc.c */ +/* Line 1430 of yacc.c */ #line 1778 "src/parse-gram.c" yylsp[0] = yylloc; @@ -1905,7 +1905,7 @@ yybackup: if (yyn <= 0) { if (yytable_value_is_error (yyn)) - goto yyerrlab; + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1960,7 +1960,7 @@ yyreduce: switch (yyn) { case 6: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 267 "src/parse-gram.y" { code_props plain_code; @@ -1971,106 +1971,106 @@ yyreduce: plain_code.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 1976 "src/parse-gram.c" break; case 7: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 277 "src/parse-gram.y" { muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 1986 "src/parse-gram.c" break; case 8: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 281 "src/parse-gram.y" { muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 1997 "src/parse-gram.c" break; case 9: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 285 "src/parse-gram.y" { defines_flag = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2005 "src/parse-gram.c" break; case 10: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 287 "src/parse-gram.y" { defines_flag = true; spec_defines_file = xstrdup ((yyvsp[0].chars)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2016 "src/parse-gram.c" break; case 11: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 292 "src/parse-gram.y" { muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose", MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2027 "src/parse-gram.c" break; case 12: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 296 "src/parse-gram.y" { expected_sr_conflicts = (yyvsp[0].integer); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2035 "src/parse-gram.c" break; case 13: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 297 "src/parse-gram.y" { expected_rr_conflicts = (yyvsp[0].integer); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2043 "src/parse-gram.c" break; case 14: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 298 "src/parse-gram.y" { spec_file_prefix = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2051 "src/parse-gram.c" break; case 15: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 299 "src/parse-gram.y" { spec_file_prefix = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2059 "src/parse-gram.c" break; case 16: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 301 "src/parse-gram.y" { nondeterministic_parser = true; glr_parser = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2070 "src/parse-gram.c" break; case 17: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 306 "src/parse-gram.y" { code_props action; @@ -2080,92 +2080,92 @@ yyreduce: muscle_code_grow ("initial_action", action.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2085 "src/parse-gram.c" break; case 18: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 314 "src/parse-gram.y" { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2093 "src/parse-gram.c" break; case 19: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 315 "src/parse-gram.y" { spec_name_prefix = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2101 "src/parse-gram.c" break; case 20: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 316 "src/parse-gram.y" { spec_name_prefix = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2109 "src/parse-gram.c" break; case 21: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 317 "src/parse-gram.y" { no_lines_flag = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2117 "src/parse-gram.c" break; case 22: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 318 "src/parse-gram.y" { nondeterministic_parser = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2125 "src/parse-gram.c" break; case 23: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 319 "src/parse-gram.y" { spec_outfile = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2133 "src/parse-gram.c" break; case 24: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 320 "src/parse-gram.y" { spec_outfile = (yyvsp[0].chars); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2141 "src/parse-gram.c" break; case 25: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 321 "src/parse-gram.y" { current_param = (yyvsp[0].param); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2149 "src/parse-gram.c" break; case 26: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 321 "src/parse-gram.y" { current_param = param_none; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2157 "src/parse-gram.c" break; case 27: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 322 "src/parse-gram.y" { version_check (&(yylsp[0]), (yyvsp[0].chars)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2165 "src/parse-gram.c" break; case 28: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 324 "src/parse-gram.y" { char const *skeleton_user = (yyvsp[0].chars); @@ -2190,62 +2190,62 @@ yyreduce: } skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2195 "src/parse-gram.c" break; case 29: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 347 "src/parse-gram.y" { token_table_flag = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2203 "src/parse-gram.c" break; case 30: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 348 "src/parse-gram.y" { report_flag |= report_states; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2211 "src/parse-gram.c" break; case 31: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 349 "src/parse-gram.y" { yacc_flag = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2219 "src/parse-gram.c" break; case 33: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 354 "src/parse-gram.y" { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2227 "src/parse-gram.c" break; case 34: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 355 "src/parse-gram.y" { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2235 "src/parse-gram.c" break; case 37: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 367 "src/parse-gram.y" { grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2245 "src/parse-gram.c" break; case 38: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 371 "src/parse-gram.y" { symbol_list *list; @@ -2253,12 +2253,12 @@ yyreduce: symbol_list_destructor_set (list, (yyvsp[-1].code), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2258 "src/parse-gram.c" break; case 39: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 378 "src/parse-gram.y" { symbol_list *list; @@ -2266,32 +2266,32 @@ yyreduce: symbol_list_printer_set (list, (yyvsp[-1].code), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2271 "src/parse-gram.c" break; case 40: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 385 "src/parse-gram.y" { default_prec = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2281 "src/parse-gram.c" break; case 41: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 389 "src/parse-gram.y" { default_prec = false; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2291 "src/parse-gram.c" break; case 42: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 393 "src/parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes @@ -2299,89 +2299,89 @@ yyreduce: muscle_code_grow ("percent_code()", (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2304 "src/parse-gram.c" break; case 43: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 400 "src/parse-gram.y" { muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2315 "src/parse-gram.c" break; case 44: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 414 "src/parse-gram.y" {} -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2323 "src/parse-gram.c" break; case 45: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 415 "src/parse-gram.y" { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2331 "src/parse-gram.c" break; case 46: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 420 "src/parse-gram.y" { union_seen = true; muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2343 "src/parse-gram.c" break; case 47: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 431 "src/parse-gram.y" { current_class = nterm_sym; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2351 "src/parse-gram.c" break; case 48: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 432 "src/parse-gram.y" { current_class = unknown_sym; current_type = NULL; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2362 "src/parse-gram.c" break; case 49: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 436 "src/parse-gram.y" { current_class = token_sym; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2370 "src/parse-gram.c" break; case 50: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 437 "src/parse-gram.y" { current_class = unknown_sym; current_type = NULL; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2381 "src/parse-gram.c" break; case 51: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 442 "src/parse-gram.y" { symbol_list *list; @@ -2390,12 +2390,12 @@ yyreduce: symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2395 "src/parse-gram.c" break; case 52: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 453 "src/parse-gram.y" { symbol_list *list; @@ -2408,202 +2408,202 @@ yyreduce: symbol_list_free ((yyvsp[0].list)); current_type = NULL; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2413 "src/parse-gram.c" break; case 53: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 467 "src/parse-gram.y" { (yyval.assoc) = left_assoc; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2421 "src/parse-gram.c" break; case 54: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 468 "src/parse-gram.y" { (yyval.assoc) = right_assoc; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2429 "src/parse-gram.c" break; case 55: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 469 "src/parse-gram.y" { (yyval.assoc) = non_assoc; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2437 "src/parse-gram.c" break; case 56: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 470 "src/parse-gram.y" { (yyval.assoc) = precedence_assoc; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2445 "src/parse-gram.c" break; case 57: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 474 "src/parse-gram.y" { current_type = NULL; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2453 "src/parse-gram.c" break; case 58: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 475 "src/parse-gram.y" { current_type = (yyvsp[0].uniqstr); tag_seen = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2461 "src/parse-gram.c" break; case 59: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 481 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2469 "src/parse-gram.c" break; case 60: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 483 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2477 "src/parse-gram.c" break; case 61: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 487 "src/parse-gram.y" { (yyval.symbol) = (yyvsp[0].symbol); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2485 "src/parse-gram.c" break; case 62: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 488 "src/parse-gram.y" { (yyval.symbol) = (yyvsp[-1].symbol); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2493 "src/parse-gram.c" break; case 63: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 494 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2501 "src/parse-gram.c" break; case 64: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 496 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2509 "src/parse-gram.c" break; case 65: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 500 "src/parse-gram.y" { (yyval.list) = (yyvsp[0].list); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2517 "src/parse-gram.c" break; case 66: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 501 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2525 "src/parse-gram.c" break; case 67: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 505 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2533 "src/parse-gram.c" break; case 68: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 506 "src/parse-gram.y" { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2541 "src/parse-gram.c" break; case 69: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 507 "src/parse-gram.y" { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2549 "src/parse-gram.c" break; case 70: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 508 "src/parse-gram.y" { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2557 "src/parse-gram.c" break; case 71: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 514 "src/parse-gram.y" { current_type = (yyvsp[0].uniqstr); tag_seen = true; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2568 "src/parse-gram.c" break; case 72: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 519 "src/parse-gram.y" { symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true); symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2579 "src/parse-gram.c" break; case 73: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 524 "src/parse-gram.y" { symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2591 "src/parse-gram.c" break; case 74: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 530 "src/parse-gram.y" { symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2603 "src/parse-gram.c" break; case 75: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 536 "src/parse-gram.y" { symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true); @@ -2611,144 +2611,144 @@ yyreduce: symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1])); symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2616 "src/parse-gram.c" break; case 82: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 566 "src/parse-gram.y" { yyerrok; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2626 "src/parse-gram.c" break; case 83: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 572 "src/parse-gram.y" { current_lhs = (yyvsp[-1].symbol); current_lhs_location = (yylsp[-1]); current_lhs_named_ref = (yyvsp[0].named_ref); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2635 "src/parse-gram.c" break; case 85: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 577 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2643 "src/parse-gram.c" break; case 86: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 578 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2651 "src/parse-gram.c" break; case 88: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 584 "src/parse-gram.y" { grammar_current_rule_begin (current_lhs, current_lhs_location, current_lhs_named_ref); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2660 "src/parse-gram.c" break; case 89: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 587 "src/parse-gram.y" { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2668 "src/parse-gram.c" break; case 90: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 589 "src/parse-gram.y" { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2676 "src/parse-gram.c" break; case 91: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 591 "src/parse-gram.y" { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2684 "src/parse-gram.c" break; case 92: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 593 "src/parse-gram.y" { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2692 "src/parse-gram.c" break; case 93: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 595 "src/parse-gram.y" { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2700 "src/parse-gram.c" break; case 94: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 597 "src/parse-gram.y" { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2708 "src/parse-gram.c" break; case 95: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 601 "src/parse-gram.y" { (yyval.named_ref) = 0; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2716 "src/parse-gram.c" break; case 96: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 603 "src/parse-gram.y" { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2724 "src/parse-gram.c" break; case 98: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 614 "src/parse-gram.y" { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2732 "src/parse-gram.c" break; case 99: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 619 "src/parse-gram.y" { (yyval.chars) = ""; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2740 "src/parse-gram.c" break; case 100: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 620 "src/parse-gram.y" { (yyval.chars) = (yyvsp[0].uniqstr); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2748 "src/parse-gram.c" break; case 102: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 631 "src/parse-gram.y" { code_props plain_code; @@ -2758,51 +2758,51 @@ yyreduce: gram_scanner_last_string_free (); (yyval.chars) = plain_code.code; } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2763 "src/parse-gram.c" break; case 103: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 651 "src/parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2771 "src/parse-gram.c" break; case 104: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 653 "src/parse-gram.y" { (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0])); symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2783 "src/parse-gram.c" break; case 105: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 661 "src/parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2791 "src/parse-gram.c" break; case 108: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 673 "src/parse-gram.y" { (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].chars)), (yylsp[0])); symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2802 "src/parse-gram.c" break; case 110: -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 682 "src/parse-gram.y" { code_props plain_code; @@ -2812,12 +2812,12 @@ yyreduce: muscle_code_grow ("epilogue", plain_code.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2817 "src/parse-gram.c" break; -/* Line 1443 of yacc.c */ +/* Line 1646 of yacc.c */ #line 2822 "src/parse-gram.c" default: break; } @@ -2871,11 +2871,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) @@ -3052,7 +3053,7 @@ yyreturn: return YYID (yyresult); } -/* Line 1680 of yacc.c */ +/* Line 1903 of yacc.c */ #line 692 "src/parse-gram.y" diff --git a/src/parse-gram.h b/src/parse-gram.h index fd1c8571..e391f134 100644 --- a/src/parse-gram.h +++ b/src/parse-gram.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 2.4.537-34db. */ +/* A Bison parser, made by GNU Bison 2.4.542-10bae. */ /* Interface for Bison's Yacc-like parsers in C @@ -31,7 +31,7 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* "%code requires" blocks. */ -/* Line 1681 of yacc.c */ +/* Line 1904 of yacc.c */ #line 202 "src/parse-gram.y" # ifndef PARAM_TYPE @@ -46,7 +46,7 @@ # endif -/* Line 1681 of yacc.c */ +/* Line 1904 of yacc.c */ #line 51 "src/parse-gram.h" /* Tokens. */ @@ -175,7 +175,7 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { -/* Line 1681 of yacc.c */ +/* Line 1904 of yacc.c */ #line 88 "src/parse-gram.y" assoc assoc; @@ -188,13 +188,13 @@ typedef union YYSTYPE uniqstr uniqstr; unsigned char character; -/* Line 1681 of yacc.c */ +/* Line 1904 of yacc.c */ #line 226 "src/parse-gram.y" param_type param; -/* Line 1681 of yacc.c */ +/* Line 1904 of yacc.c */ #line 199 "src/parse-gram.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 diff --git a/tests/conflicts.at b/tests/conflicts.at index 655a666c..16e1956f 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 @@ -342,6 +348,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]) @@ -417,6 +435,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]) @@ -426,6 +454,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 + 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 241c4d06..25466854 100644 --- a/tests/input.at +++ b/tests/input.at @@ -1289,3 +1289,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]], [], +[[:2: %define variable `parse.lac.es-capacity-initial' is not used +]]) + +AT_CLEANUP diff --git a/tests/regression.at b/tests/regression.at index b3fdc29f..65d4ac23 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -1469,3 +1469,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 + void yyerror (char const *); + int yylex (]AT_PURE_IF([[YYSTYPE *]], [[void]])[); +} + +]$1[ +%define parse.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 + 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