[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 01/12] yacc.c: extract yyerror_message_arguments
From: |
Akim Demaille |
Subject: |
[PATCH 01/12] yacc.c: extract yyerror_message_arguments |
Date: |
Thu, 16 Jan 2020 07:58:12 +0100 |
Isolate a function that returns the list of expected and unexpected
tokens. It will be exposed to users willing to customize their error
messages.
* data/skeletons/yacc.c (yyparse_context_t): New.
(yyerror_message_arguments): New, extracted from yysyntax_error.
---
data/skeletons/yacc.c | 178 ++++++++++++++++++++++++------------------
1 file changed, 103 insertions(+), 75 deletions(-)
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index c7c1570e..cc4e4bdf 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -1046,6 +1046,95 @@ yy_lac (yy_state_t *yyesa, yy_state_t **yyes,
}
}]])[
+]m4_if(b4_percent_define_get([[parse.error]]), [simple], [],
+[[typedef struct
+{
+ yy_state_t *yyssp;
+ int yytoken;]b4_lac_if([[
+ yy_state_t *yyesa;
+ yy_state_t **yyes_p;
+ YYPTRDIFF_T *yyes_capacity_p;]])[
+} yyparse_context_t;
+
+static int
+yysyntax_error_arguments (const yyparse_context_t *yyctx,
+ const char *yyarg[], int yyargn)
+{
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - 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.]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
+ scanner and before detecting a syntax error. Thus, state merging
+ (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.]])[
+ */
+ if (yyctx->yytoken != YYEMPTY)
+ {
+ int yyn = yypact[+*yyctx->yyssp];]b4_lac_if([[
+ YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
+ yyarg[yycount++] = yytname[yyctx->yytoken];
+ if (!yypact_value_is_default (yyn))
+ {]b4_lac_if([[
+ int yyx;
+ for (yyx = 0; yyx < YYNTOKENS; ++yyx)
+ if (yyx != YYTERROR && yyx != YYUNDEFTOK)
+ {
+ {
+ int yy_lac_status = yy_lac (yyctx->yyesa, yyctx->yyes_p,
yyctx->yyes_capacity_p,
+ yyctx->yyssp, yyx);
+ if (yy_lac_status == 2)
+ return -2;
+ if (yy_lac_status == 1)
+ continue;
+ }]], [[
+ /* 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;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {]])[
+ if (yycount == yyargn)
+ {
+ yycount = 1;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ }
+ }]b4_lac_if([[
+ else
+ YYDPRINTF ((stderr, "No expected tokens.\n"));]])[
+ }
+ return yycount;
+}
+]])[
]m4_case(b4_percent_define_get([[parse.error]]), [verbose],
[[# ifndef yystrlen
@@ -1135,6 +1224,7 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
+
/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
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
@@ -1147,8 +1237,7 @@ yytnamerr (char *yyres, const char *yystr)
yy_lac returned 2]])[. */
static int
yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
- ]b4_lac_if([[yy_state_t *yyesa, yy_state_t **yyes,
- YYPTRDIFF_T *yyes_capacity, ]])[yy_state_t *yyssp, int yytoken)
+ const yyparse_context_t *yyctx)
{
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
@@ -1161,76 +1250,15 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
/* Cumulated lengths of YYARG. */
YYPTRDIFF_T yysize = 0;
- /* There are many possibilities here to consider:
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - 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.]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
- scanner and before detecting a syntax error. Thus, state merging
- (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.]])[
- */
- if (yytoken != YYEMPTY)
- {
- 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([[
- int yyx;
- for (yyx = 0; yyx < YYNTOKENS; ++yyx)
- if (yyx != YYTERROR && yyx != YYUNDEFTOK)
- {
- {
- int yy_lac_status = yy_lac (yyesa, yyes, yyes_capacity,
- yyssp, yyx);
- if (yy_lac_status == 2)
- return 2;
- if (yy_lac_status == 1)
- continue;
- }]], [[
- /* 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;
- 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;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- }
- }]b4_lac_if([[
- else
- YYDPRINTF ((stderr, "No expected tokens.\n"));]])[
- }
+ {
+ int yyn
+ = yysyntax_error_arguments (yyctx, yyarg,
+ YYSIZEOF (yyarg) / YYSIZEOF (*yyarg));
+ if (yyn == -2)
+ return 2;
+ else
+ yycount = yyn;
+ }
switch (yycount)
{
@@ -1760,11 +1788,11 @@ yyerrlab:
[simple],
[[ yyerror (]b4_yyerror_args[YY_("syntax error"));]],
[verbose],
-[[# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \]b4_lac_if([[
- yyesa, &yyes, &yyes_capacity, \]])[
- yyssp, yytoken)
+[[# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, &yyctx)
{
char const *yymsgp = YY_("syntax error");
+ yyparse_context_t yyctx
+ = {yyssp, yytoken]b4_lac_if([[, yyesa, &yyes, &yyes_capacity]])[};
int yysyntax_error_status;]b4_lac_if([[
if (yychar != YYEMPTY)
YY_LAC_ESTABLISH;]])[
--
2.24.1
- RFC: custom error messages, Akim Demaille, 2020/01/03
- Re: RFC: custom error messages, Christian Schoenebeck, 2020/01/03
- Re: RFC: custom error messages, Akim Demaille, 2020/01/05
- Re: RFC: custom error messages, Christian Schoenebeck, 2020/01/09
- Re: RFC: custom error messages, Akim Demaille, 2020/01/10
- Re: RFC: custom error messages, Christian Schoenebeck, 2020/01/14
- Re: RFC: custom error messages, Akim Demaille, 2020/01/14
- [PATCH 00/12] RFC: yyreport_error_message, Akim Demaille, 2020/01/16
- [PATCH 02/12] yacc.c: store token numbers, not token strings, Akim Demaille, 2020/01/16
- [PATCH 03/12] yacc.c: style: avoid macros, Akim Demaille, 2020/01/16
- [PATCH 01/12] yacc.c: extract yyerror_message_arguments,
Akim Demaille <=
- [PATCH 04/12] yacc.c: add custom error message generation, Akim Demaille, 2020/01/16
- [PATCH 06/12] tests: compute verbose error messages from the custom ones, Akim Demaille, 2020/01/16
- [PATCH 05/12] yacc.c: check custom error messages, Akim Demaille, 2020/01/16
- [PATCH 07/12] yacc.c: isolate yyexpected_tokens, Akim Demaille, 2020/01/16
- [PATCH 08/12] yacc.c: let custom error messages see the location, Akim Demaille, 2020/01/16
- [PATCH 09/12] yacc.c: check custom error messages with parse-params, Akim Demaille, 2020/01/16
- [PATCH 10/12] tests: a clearer test for parse-params, Akim Demaille, 2020/01/16
- [PATCH 12/12] yacc.c: portability to G++ 4.8, Akim Demaille, 2020/01/16
- [PATCH 11/12] yacc.c: pass the parse-params to yyreport_syntax_error, Akim Demaille, 2020/01/16
- Re: RFC: custom error messages, Christian Schoenebeck, 2020/01/16