glr.c: add support for parse.error=detailed

* data/skeletons/glr.c (yystrlen, yysymbol_name): New.
Implement parse.error detailed.
* tests/calc.at: Check it.
This commit is contained in:
Akim Demaille
2020-01-29 07:17:38 +01:00
parent 50fb1e6e0c
commit c4a08d1899
2 changed files with 74 additions and 30 deletions

View File

@@ -368,15 +368,6 @@ static const ]b4_int_type_for([b4_rline])[ yyrline[] =
}; };
#endif #endif
#if ]b4_error_verbose_if([[1]], [b4_api_PREFIX[DEBUG || ]b4_token_table_flag])[
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
]b4_tname[
};
#endif
#define YYPACT_NINF (]b4_pact_ninf[) #define YYPACT_NINF (]b4_pact_ninf[)
#define YYTABLE_NINF (]b4_table_ninf[) #define YYTABLE_NINF (]b4_table_ninf[)
@@ -616,13 +607,47 @@ yyMemoryExhausted (yyGLRStack* yystackp)
YYLONGJMP (yystackp->yyexception_buffer, 2); YYLONGJMP (yystackp->yyexception_buffer, 2);
} }
#if ]b4_error_verbose_if([[1]], [b4_api_PREFIX[DEBUG]])[ #if ]b4_error_verbose_if([[1]], [b4_api_PREFIX[DEBUG || ]b4_token_table_flag])[
/** A printable representation of TOKEN. */ /* The user-facing name of the symbol whose (internal) number is
static inline const char* YYSYMBOL. No bounds checking. */
yysymbol_name (yySymbol yytoken) static const char *yysymbol_name (yySymbol yysymbol) YY_ATTRIBUTE_UNUSED;
]m4_bmatch(b4_percent_define_get([[parse.error]]),
[simple\|verbose],
[[/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{ {
return yytoken == YYEMPTY ? "" : yytname[yytoken]; ]b4_tname[
} };
static const char *
yysymbol_name (yySymbol yysymbol)
{
return yytname[yysymbol];
}]],
[[/* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */
static const char *yysymbol_name (yySymbol yysymbol) YY_ATTRIBUTE_UNUSED;
static const char *
yysymbol_name (yySymbol yysymbol)
{
static const char *const yy_sname[] =
{
]b4_symbol_names[
};]m4_ifdef([b4_translatable], [[
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YYTNAME[SYMBOL-NUM] is
internationalizable. */
static ]b4_int_type_for([b4_translate])[ yytranslatable[] =
{
]b4_translatable[
};
return (yysymbol < YYNTOKENS && yytranslatable[yysymbol]
? _(yy_sname[yysymbol])
: yy_sname[yysymbol]);]], [[
return yy_sname[yysymbol];]])[
}]])[
#endif #endif
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
@@ -680,11 +705,19 @@ static void yypdumpstack (yyGLRStack* yystackp)
#endif /* !]b4_api_PREFIX[DEBUG */ #endif /* !]b4_api_PREFIX[DEBUG */
]m4_case(b4_percent_define_get([parse.error]), [verbose], ]m4_case(b4_percent_define_get([[parse.error]]),
[[# ifndef yystpcpy [simple],
# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE [[]],
# define yystpcpy stpcpy [[#ifndef yystrlen
# else # define yystrlen(S) (YY_CAST (ptrdiff_t, strlen (S)))
#endif
]m4_bmatch(b4_percent_define_get([[parse.error]]),
[detailed\|verbose],
[[#ifndef yystpcpy
# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */ YYDEST. */
static char * static char *
@@ -698,10 +731,12 @@ yystpcpy (char *yydest, const char *yysrc)
return yyd - 1; return yyd - 1;
} }
# endif
# endif # endif
#endif]])[
# ifndef yytnamerr ]m4_case(b4_percent_define_get([[parse.error]]),
[verbose],
[[#ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string heuristic is that double-quoting is unnecessary unless the string
@@ -748,10 +783,10 @@ yytnamerr (char *yyres, const char *yystr)
if (yyres) if (yyres)
return yystpcpy (yyres, yystr) - yyres; return yystpcpy (yyres, yystr) - yyres;
else else
return YY_CAST (ptrdiff_t, strlen (yystr)); return yystrlen (yystr);
} }
# endif #endif
]])[ ]])])[
/** Fill in YYVSP[YYLOW1 .. YYLOW0-1] from the chain of states starting /** Fill in YYVSP[YYLOW1 .. YYLOW0-1] from the chain of states starting
* at YYVSP[YYLOW0].yystate.yypred. Leaves YYVSP[YYLOW1].yystate.yypred * at YYVSP[YYLOW0].yystate.yypred. Leaves YYVSP[YYLOW1].yystate.yypred
@@ -2151,9 +2186,11 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
if (yystackp->yyerrState != 0) if (yystackp->yyerrState != 0)
return; return;
]m4_case(b4_percent_define_get([parse.error]), ]m4_case(b4_percent_define_get([parse.error]),
[custom],
[[ if (yyreport_syntax_error (yystackp]b4_user_args[))
yyMemoryExhausted (yystackp);]],
[simple], [simple],
[[ yyerror (]b4_lyyerror_args[YY_("syntax error"));]], [[ yyerror (]b4_lyyerror_args[YY_("syntax error"));]],
[verbose],
[[ { [[ {
yybool yysize_overflow = yyfalse; yybool yysize_overflow = yyfalse;
char* yymsg = YY_NULLPTR; char* yymsg = YY_NULLPTR;
@@ -2169,6 +2206,8 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/* Actual size of YYARG. */ /* Actual size of YYARG. */
int yycount int yycount
= yysyntax_error_arguments (yystackp, yyarg, YYERROR_VERBOSE_ARGS_MAXIMUM); = yysyntax_error_arguments (yystackp, yyarg, YYERROR_VERBOSE_ARGS_MAXIMUM);
if (yycount == -2)
yyMemoryExhausted (yystackp);
switch (yycount) switch (yycount)
{ {
@@ -2188,12 +2227,15 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/* Compute error message size. Don't count the "%s"s, but reserve /* Compute error message size. Don't count the "%s"s, but reserve
room for the terminator. */ room for the terminator. */
yysize = YY_CAST (ptrdiff_t, strlen (yyformat)) - 2 * yycount + 1; yysize = yystrlen (yyformat) - 2 * yycount + 1;
{ {
int yyi; int yyi;
for (yyi = 0; yyi < yycount; ++yyi) for (yyi = 0; yyi < yycount; ++yyi)
{ {
ptrdiff_t yysz = yytnamerr (YY_NULLPTR, yysymbol_name (yyarg[yyi])); ptrdiff_t yysz
= ]m4_case(b4_percent_define_get([[parse.error]]),
[verbose], [[yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]])]],
[[yystrlen (yysymbol_name (yyarg[yyi]))]]);[
if (YYSIZEMAX - yysize < yysz) if (YYSIZEMAX - yysize < yysz)
yysize_overflow = yytrue; yysize_overflow = yytrue;
else else
@@ -2211,8 +2253,9 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
while ((*yyp = *yyformat)) while ((*yyp = *yyformat))
{ {
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{ {]m4_case(b4_percent_define_get([[parse.error]]), [verbose], [[
yyp += yytnamerr (yyp, yysymbol_name (yyarg[yyi++])); yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);]], [[
yyp = yystpcpy (yyp, yysymbol_name (yyarg[yyi++]));]])[
yyformat += 2; yyformat += 2;
} }
else else

View File

@@ -878,6 +878,7 @@ AT_CHECK_CALC_GLR([%define api.pure %locations])
AT_CHECK_CALC_GLR([%define parse.error verbose %locations]) AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%define parse.error detailed %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%debug]) AT_CHECK_CALC_GLR([%debug])
AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])