parse.error: document and diagnose the incompatibility with %token-table

* doc/bison.texi (Tokens from Literals): Move to code using
%token-table to...
(Decl Summary: %token-table): here.
* data/skeletons/bison.m4: Implement mutual exclusion.
* tests/input.at: Check it.
* doc/local.mk: Be robust to the removal of doc/.
This commit is contained in:
Akim Demaille
2020-02-10 18:38:42 +01:00
parent 57647bb656
commit 77bdcc6f0c
4 changed files with 65 additions and 26 deletions

View File

@@ -1118,3 +1118,11 @@ b4_percent_define_ifdef([api.value.type],
# api.value.union.name. # api.value.union.name.
b4_percent_define_check_kind([api.value.union.name], [keyword]) b4_percent_define_check_kind([api.value.union.name], [keyword])
# parse.error (custom|detailed) >< token-table.
b4_token_table_if(
[b4_parse_error_bmatch([custom\|detailed],
[b4_complain_at(b4_percent_define_get_loc([parse.error]),
[['%s' and '%s' cannot be used together]],
[%token-table],
[%define parse.error (custom|detailed)])])])

View File

@@ -5780,6 +5780,8 @@ This is similar to how most shells resolve commands.
@end deffn @end deffn
@deffn {Directive} %token-table @deffn {Directive} %token-table
This feature is obsolescent, avoid it in new projects.
Generate an array of token names in the parser implementation file. The Generate an array of token names in the parser implementation file. The
name of the array is @code{yytname}; @code{yytname[@var{i}]} is the name of name of the array is @code{yytname}; @code{yytname[@var{i}]} is the name of
the token whose internal Bison token code number is @var{i}. The first the token whose internal Bison token code number is @var{i}. The first
@@ -5809,6 +5811,29 @@ The number of grammar rules,
@item YYNSTATES @item YYNSTATES
The number of parser states (@pxref{Parser States}). The number of parser states (@pxref{Parser States}).
@end table @end table
Here's code for looking up a multicharacter token in @code{yytname},
assuming that the characters of the token are stored in @code{token_buffer},
and assuming that the token does not contain any characters like @samp{"}
that require escaping.
@example
for (int i = 0; i < YYNTOKENS; i++)
if (yytname[i]
&& yytname[i][0] == '"'
&& ! strncmp (yytname[i] + 1, token_buffer,
strlen (token_buffer))
&& yytname[i][strlen (token_buffer) + 1] == '"'
&& yytname[i][strlen (token_buffer) + 2] == 0)
break;
@end example
This method is discouraged: the primary purpose of string aliases is forging
good error messages, not describing the spelling of keywords. In addition,
looking for the token type at runtime incurs a (small but noticeable) cost.
Finally, @code{%token-table} is incompatible with the @code{custom} and
@code{detailed} values of the @code{parse.error} @code{%define} variable.
@end deffn @end deffn
@deffn {Directive} %verbose @deffn {Directive} %verbose
@@ -7089,29 +7114,6 @@ forging good error messages, not describing the spelling of keywords. In
addition, looking for the token type at runtime incurs a (small but addition, looking for the token type at runtime incurs a (small but
noticeable) cost. noticeable) cost.
The index of the token in the table is the token type's code. The name of a
multicharacter token is recorded in @code{yytname} with a double-quote, the
token's characters, and another double-quote. The token's characters are
escaped as necessary to be suitable as input to Bison.
Here's code for looking up a multicharacter token in @code{yytname},
assuming that the characters of the token are stored in @code{token_buffer},
and assuming that the token does not contain any characters like @samp{"}
that require escaping.
@example
for (int i = 0; i < YYNTOKENS; i++)
@{
if (yytname[i]
&& yytname[i][0] == '"'
&& ! strncmp (yytname[i] + 1, token_buffer,
strlen (token_buffer))
&& yytname[i][strlen (token_buffer) + 1] == '"'
&& yytname[i][strlen (token_buffer) + 2] == 0)
break;
@}
@end example
The @code{yytname} table is generated only if you use the The @code{yytname} table is generated only if you use the
@code{%token-table} declaration. @xref{Decl Summary}. @code{%token-table} declaration. @xref{Decl Summary}.
@end itemize @end itemize

View File

@@ -110,14 +110,15 @@ EXTRA_DIST += $(top_srcdir)/doc/bison.help
if ! CROSS_COMPILING if ! CROSS_COMPILING
MAINTAINERCLEANFILES += $(top_srcdir)/doc/bison.help MAINTAINERCLEANFILES += $(top_srcdir)/doc/bison.help
$(top_srcdir)/doc/bison.help: src/bison$(EXEEXT) $(top_srcdir)/doc/bison.help: src/bison$(EXEEXT)
$(AM_V_GEN)LC_ALL=C tests/bison --version >doc/bison.help.tmp $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at) LC_ALL=C tests/bison --version >%D%/bison.help.tmp
$(AM_V_at) LC_ALL=C tests/bison --help | \ $(AM_V_at) LC_ALL=C tests/bison --help | \
## Avoid depending on the path to Bison. ## Avoid depending on the path to Bison.
sed -e 's,^Usage: .*/bison \[OPTION\],Usage: bison [OPTION],g' \ sed -e 's,^Usage: .*/bison \[OPTION\],Usage: bison [OPTION],g' \
## Avoid variations in the output depending on whether we are ## Avoid variations in the output depending on whether we are
## on a glibc system. ## on a glibc system.
-e '/translation bugs/d' >>doc/bison.help.tmp -e '/translation bugs/d' >>%D%/bison.help.tmp
$(AM_V_at)$(top_srcdir)/build-aux/move-if-change doc/bison.help.tmp $@ $(AM_V_at)$(top_srcdir)/build-aux/move-if-change %D%/bison.help.tmp $@
endif ! CROSS_COMPILING endif ! CROSS_COMPILING

View File

@@ -2888,3 +2888,31 @@ input.y:9.1-21: definition of api.token.raw
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
## ------------------------------ ##
## %token-table and parse.error. ##
## ------------------------------ ##
AT_SETUP([[%token-table and parse.error]])
# AT_TEST(DIRECTIVES, ERROR-LOCATION)
# -----------------------------------
m4_pushdef([AT_TEST],
[AT_DATA([[input.y]],
[[$1
%%
exp: %empty;
]])
AT_BISON_CHECK([[input.y]], [[1]], [[]],
[$2: error: '%token-table' and '%define parse.error (custom|detailed)' cannot be used together
])
])
AT_TEST([%define parse.error custom %token-table], [[input.y:1.1-26]])
AT_TEST([%define parse.error detailed %token-table],[[input.y:1.1-28]])
m4_popdef([AT_TEST])
AT_CLEANUP