mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-19 09:13:04 +00:00
yacc.c: isolate yyexpected_tokens
Provide users with a means to query for the currently allowed tokens. Could be used for autocompletion for instance. * data/skeletons/yacc.c (yyexpected_tokens): New, extracted from yysyntax_error_arguments. * examples/c/calc/calc.y (PRINT_EXPECTED_TOKENS): New. Use it.
This commit is contained in:
@@ -895,7 +895,7 @@ do { \
|
|||||||
{ \
|
{ \
|
||||||
YYDPRINTF ((stderr, \
|
YYDPRINTF ((stderr, \
|
||||||
"LAC: initial context established for %s\n", \
|
"LAC: initial context established for %s\n", \
|
||||||
yysymbol_name(yytoken))); \
|
yysymbol_name (yytoken))); \
|
||||||
yy_lac_established = 1; \
|
yy_lac_established = 1; \
|
||||||
{ \
|
{ \
|
||||||
int yy_lac_status = \
|
int yy_lac_status = \
|
||||||
@@ -948,7 +948,7 @@ yy_lac (yy_state_t *yyesa, yy_state_t **yyes,
|
|||||||
yy_state_t *yyes_prev = yyssp;
|
yy_state_t *yyes_prev = yyssp;
|
||||||
yy_state_t *yyesp = yyes_prev;
|
yy_state_t *yyesp = yyes_prev;
|
||||||
/* Reduce until we encounter a shift and thereby accept the token. */
|
/* Reduce until we encounter a shift and thereby accept the token. */
|
||||||
YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yysymbol_name(yytoken)));
|
YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yysymbol_name (yytoken)));
|
||||||
if (yytoken == YYUNDEFTOK)
|
if (yytoken == YYUNDEFTOK)
|
||||||
{
|
{
|
||||||
YYDPRINTF ((stderr, " Always Err\n"));
|
YYDPRINTF ((stderr, " Always Err\n"));
|
||||||
@@ -1056,6 +1056,62 @@ yy_lac (yy_state_t *yyesa, yy_state_t **yyes,
|
|||||||
YYPTRDIFF_T *yyes_capacity_p;]])[
|
YYPTRDIFF_T *yyes_capacity_p;]])[
|
||||||
} yyparse_context_t;
|
} yyparse_context_t;
|
||||||
|
|
||||||
|
/* Put in YYARG at most YYARGN of the expected tokens given
|
||||||
|
the current YYCTX, and return the number of tokens stored
|
||||||
|
in YYARG.
|
||||||
|
If YYARG is null, return the number of expected tokens. */
|
||||||
|
static int
|
||||||
|
yyexpected_tokens (const yyparse_context_t *yyctx,
|
||||||
|
int yyarg[], int yyargn)
|
||||||
|
{
|
||||||
|
/* Actual size of YYARG. */
|
||||||
|
int yycount = 0;
|
||||||
|
]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;
|
||||||
|
}
|
||||||
|
if (!yyarg)
|
||||||
|
++yycount;
|
||||||
|
else if (yycount == yyargn)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
yyarg[yycount++] = yyx;
|
||||||
|
}]],
|
||||||
|
[[ int yyn = yypact[+*yyctx->yyssp];
|
||||||
|
if (!yypact_value_is_default (yyn))
|
||||||
|
{
|
||||||
|
/* 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 (!yyarg)
|
||||||
|
++yycount;
|
||||||
|
else if (yycount == yyargn)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
yyarg[yycount++] = yyx;
|
||||||
|
}
|
||||||
|
}]])[
|
||||||
|
return yycount;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
yysyntax_error_arguments (const yyparse_context_t *yyctx,
|
yysyntax_error_arguments (const yyparse_context_t *yyctx,
|
||||||
int yyarg[], int yyargn)
|
int yyarg[], int yyargn)
|
||||||
@@ -1092,45 +1148,16 @@ yysyntax_error_arguments (const yyparse_context_t *yyctx,
|
|||||||
*/
|
*/
|
||||||
if (yyctx->yytoken != YYEMPTY)
|
if (yyctx->yytoken != YYEMPTY)
|
||||||
{
|
{
|
||||||
int yyn = yypact[+*yyctx->yyssp];]b4_lac_if([[
|
int yyn;]b4_lac_if([[
|
||||||
YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
|
YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
|
||||||
yyarg[yycount++] = yyctx->yytoken;
|
yyarg[yycount++] = yyctx->yytoken;
|
||||||
if (!yypact_value_is_default (yyn))
|
yyn = yyexpected_tokens (yyctx, yyarg ? yyarg + 1 : yyarg, yyargn - 1);
|
||||||
{]b4_lac_if([[
|
if (yyn == -2)
|
||||||
int yyx;
|
return -2;]b4_lac_if([[
|
||||||
for (yyx = 0; yyx < YYNTOKENS; ++yyx)
|
else if (yyn == 0)
|
||||||
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++] = yyx;
|
|
||||||
}
|
|
||||||
}]b4_lac_if([[
|
|
||||||
else
|
|
||||||
YYDPRINTF ((stderr, "No expected tokens.\n"));]])[
|
YYDPRINTF ((stderr, "No expected tokens.\n"));]])[
|
||||||
|
else
|
||||||
|
yycount += yyn;
|
||||||
}
|
}
|
||||||
return yycount;
|
return yycount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,35 @@
|
|||||||
%code top {
|
%code top {
|
||||||
#include <ctype.h> /* isdigit. */
|
#include <ctype.h> /* isdigit. */
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h> /* For printf, etc. */
|
#include <stdio.h> /* For printf, etc. */
|
||||||
#include <string.h> /* strcmp. */
|
#include <string.h> /* strcmp. */
|
||||||
|
|
||||||
int yylex (void);
|
int yylex (void);
|
||||||
void yyerror (char const *);
|
void yyerror (char const *);
|
||||||
|
|
||||||
|
bool show_expected = false;
|
||||||
|
|
||||||
|
#define PRINT_EXPECTED_TOKENS() \
|
||||||
|
do { \
|
||||||
|
if (show_expected) \
|
||||||
|
{ \
|
||||||
|
yyparse_context_t ctx \
|
||||||
|
= {yyssp, yytoken, yyesa, &yyes, &yyes_capacity}; \
|
||||||
|
int tokens[YYNTOKENS]; \
|
||||||
|
int cnt = yyexpected_tokens (&ctx, tokens, YYNTOKENS); \
|
||||||
|
fprintf (stderr, "expected tokens in state %d rule %d (%d):", \
|
||||||
|
*yyssp, yyn - 1, cnt); \
|
||||||
|
for (int i = 0; i < cnt; ++i) \
|
||||||
|
fprintf (stderr, " %s", yysymbol_name(tokens[i])); \
|
||||||
|
fprintf (stderr, "\n"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
}
|
}
|
||||||
|
|
||||||
%define api.header.include {"calc.h"}
|
%define api.header.include {"calc.h"}
|
||||||
%define api.value.type union /* Generate YYSTYPE from these types: */
|
%define api.value.type union /* Generate YYSTYPE from these types: */
|
||||||
%define parse.error custom
|
%define parse.error custom
|
||||||
|
%define parse.lac full
|
||||||
%token <double> NUM "number"
|
%token <double> NUM "number"
|
||||||
%type <double> expr term fact
|
%type <double> expr term fact
|
||||||
|
|
||||||
@@ -23,8 +43,8 @@
|
|||||||
|
|
||||||
%% /* The grammar follows. */
|
%% /* The grammar follows. */
|
||||||
input:
|
input:
|
||||||
%empty
|
%empty { PRINT_EXPECTED_TOKENS (); }
|
||||||
| input line
|
| input line { PRINT_EXPECTED_TOKENS (); }
|
||||||
;
|
;
|
||||||
|
|
||||||
line:
|
line:
|
||||||
@@ -46,8 +66,8 @@ term:
|
|||||||
;
|
;
|
||||||
|
|
||||||
fact:
|
fact:
|
||||||
"number"
|
"number" { PRINT_EXPECTED_TOKENS (); }
|
||||||
| '(' expr ')' { $$ = $2; }
|
| '(' expr { PRINT_EXPECTED_TOKENS (); } ')' { $$ = $expr; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -110,7 +130,9 @@ main (int argc, char const* argv[])
|
|||||||
{
|
{
|
||||||
/* Enable parse traces on option -p. */
|
/* Enable parse traces on option -p. */
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
if (!strcmp (argv[i], "-p"))
|
if (!strcmp (argv[i], "-e"))
|
||||||
|
show_expected = 1;
|
||||||
|
else if (!strcmp (argv[i], "-p"))
|
||||||
yydebug = 1;
|
yydebug = 1;
|
||||||
return yyparse ();
|
return yyparse ();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user