Merge remote-tracking branch 'origin/maint'

* origin/maint:
  doc: minor fixes
  doc: improve the index
  doc: introduce api.pure full, rearrange some examples
  yacc.c: support "%define api.pure full"
  local.at: improvements

Conflicts:
	NEWS
	data/yacc.c
	doc/bison.texi
	tests/calc.at
This commit is contained in:
Akim Demaille
2012-11-29 14:54:37 +01:00
6 changed files with 146 additions and 95 deletions

11
NEWS
View File

@@ -242,6 +242,17 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?]
** New value for %define variable: api.pure full
The %define variable api.pure requests a pure (reentrant) parser. However,
for historical reasons, using it in a location-tracking Yacc parser resulted
in an yyerror function that did not take a location as a parameter. With this
new value, the user may request a better pure parser, where yyerror does take
a location as a parameter (in location-tracking parsers).
The use of "%define api.pure true" is deprecated in favor of this new
"%define api.pure full".
** Changes in the format of error messages
This used to be the format of many error reports:

View File

@@ -67,24 +67,36 @@ m4_define_default([b4_stack_depth_init], [200])
## ------------------------ ##
b4_percent_define_default([[api.pure]], [[false]])
b4_define_flag_if([pure])
m4_define([b4_pure_flag],
[b4_percent_define_flag_if([[api.pure]], [[1]], [[0]])])
b4_percent_define_check_values([[[[api.pure]],
[[false]], [[true]], [[]], [[full]]]])
# b4_yacc_pure_if(IF-TRUE, IF-FALSE)
# ----------------------------------
# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise.
m4_define([b4_yacc_pure_if],
[b4_pure_if([m4_ifset([b4_parse_param],
[$1], [$2])],
[$2])])
m4_define([b4_pure_flag], [[0]])
m4_case(b4_percent_define_get([[api.pure]]),
[false], [m4_define([b4_pure_flag], [[0]])],
[true], [m4_define([b4_pure_flag], [[1]])],
[], [m4_define([b4_pure_flag], [[1]])],
[full], [m4_define([b4_pure_flag], [[2]])])
m4_define([b4_pure_if],
[m4_case(b4_pure_flag,
[0], [$2],
[1], [$1],
[2], [$1])])
[m4_fatal([invalid api.pure value: ]$1)])])
# b4_yyerror_arg_loc_if(ARG)
# --------------------------
# Expand ARG iff yyerror is to be given a location as argument.
m4_define([b4_yyerror_arg_loc_if],
[b4_locations_if([m4_case(b4_pure_flag,
[1], [m4_ifset([b4_parse_param], [$1])],
[2], [$1])])])
# b4_yyerror_args
# ---------------
# Arguments passed to yyerror: user args plus yylloc.
m4_define([b4_yyerror_args],
[b4_yacc_pure_if([b4_locations_if([&yylloc, ])])dnl
[b4_yyerror_arg_loc_if([&yylloc, ])dnl
m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])

View File

@@ -4954,7 +4954,7 @@ declaration @samp{%define api.pure} says that you want the parser to be
reentrant. It looks like this:
@example
%define api.pure
%define api.pure full
@end example
The result is that the communication variables @code{yylval} and
@@ -5004,7 +5004,7 @@ compatibility with the impure Yacc pull mode interface. Unless you know
what you are doing, your declarations should look like this:
@example
%define api.pure
%define api.pure full
%define api.push-pull push
@end example
@@ -5508,9 +5508,41 @@ The parser namespace is @code{foo} and @code{yylex} is referenced as
@item Purpose: Request a pure (reentrant) parser program.
@xref{Pure Decl, ,A Pure (Reentrant) Parser}.
@item Accepted Values: Boolean
@item Accepted Values: @code{true}, @code{false}, @code{full}
The value may be omitted: this is equivalent to specifying @code{true}, as is
the case for Boolean values.
When @code{%define api.pure full} is used, the parser is made reentrant. This
changes the signature for @code{yylex} (@pxref{Pure Calling}), and also that of
@code{yyerror} when the tracking of locations has been activated, as shown
below.
The @code{true} value is very similar to the @code{full} value, the only
difference is in the signature of @code{yyerror} on Yacc parsers without
@code{%parse-param}, for historical reasons.
I.e., if @samp{%locations %define api.pure} is passed then the prototypes for
@code{yyerror} are:
@example
void yyerror (char const *msg); /* Yacc parsers. */
void yyerror (YYLTYPE *locp, char const *msg); /* GLR parsers. */
@end example
But if @samp{%locations %define api.pure %parse-param @{int *nastiness@}} is
used, then both parsers have the same signature:
@example
void yyerror (YYLTYPE *llocp, int *nastiness, char const *msg);
@end example
(@pxref{Error Reporting, ,The Error
Reporting Function @code{yyerror}})
@item Default Value: @code{false}
@item History: the @code{full} value was introduced in Bison 2.7
@end itemize
@c api.pure
@@ -5637,7 +5669,7 @@ remain in the parser tables. @xref{Unreachable States}.
@item Default Value: @code{false}
@end itemize
introduced as @code{lr.keep_unreachable_states} in 2.3b, renamed as
@code{lr.keep-unreachable-state} in 2.5, and as
@code{lr.keep-unreachable-states} in 2.5, and as
@code{lr.keep-unreachable-state} in 2.8.
@c lr.keep-unreachable-state
@@ -6073,6 +6105,27 @@ In the grammar actions, use expressions like this to refer to the data:
exp: @dots{} @{ @dots{}; *randomness += 1; @dots{} @}
@end example
@noindent
Using the following:
@example
%parse-param @{int *randomness@}
@end example
Results in these signatures:
@example
void yyerror (int *randomness, const char *msg);
int yyparse (int *randomness);
@end example
@noindent
Or, if both @code{%define api.pure full} (or just @code{%define api.pure})
and @code{%locations} are used:
@example
void yyerror (YYLTYPE *llocp, int *randomness, const char *msg);
int yyparse (int *randomness);
@end example
@node Push Parser Function
@section The Push Parser Function @code{yypush_parse}
@findex yypush_parse
@@ -6324,7 +6377,7 @@ The data type of @code{yylloc} has the name @code{YYLTYPE}.
@node Pure Calling
@subsection Calling Conventions for Pure Parsers
When you use the Bison declaration @samp{%define api.pure} to request a
When you use the Bison declaration @code{%define api.pure full} to request a
pure, reentrant parser, the global communication variables @code{yylval}
and @code{yylloc} cannot be used. (@xref{Pure Decl, ,A Pure (Reentrant)
Parser}.) In such parsers the two global variables are replaced by
@@ -6369,6 +6422,7 @@ Specify that @var{argument-declaration} are additional
declarations, which is equivalent to repeating @code{%param}.
@end deffn
@noindent
For instance:
@example
@@ -6385,7 +6439,7 @@ int yylex (scanner_mode *mode, environment_type *env);
int yyparse (parser_mode *mode, environment_type *env);
@end example
If @samp{%define api.pure} is added:
If @samp{%define api.pure full} is added:
@example
int yylex (YYSTYPE *lvalp, scanner_mode *mode, environment_type *env);
@@ -6393,7 +6447,8 @@ int yyparse (parser_mode *mode, environment_type *env);
@end example
@noindent
and finally, if both @samp{%define api.pure} and @code{%locations} are used:
and finally, if both @samp{%define api.pure full} and @code{%locations} are
used:
@example
int yylex (YYSTYPE *lvalp, YYLTYPE *llocp,
@@ -6458,50 +6513,16 @@ error recovery if you have written suitable error recovery grammar rules
immediately return 1.
Obviously, in location tracking pure parsers, @code{yyerror} should have
an access to the current location.
This is indeed the case for the GLR
parsers, but not for the Yacc parser, for historical reasons. I.e., if
@samp{%locations %define api.pure} is passed then the prototypes for
@code{yyerror} are:
an access to the current location. With @code{%define api.pure}, this is
indeed the case for the GLR parsers, but not for the Yacc parser, for
historical reasons, and this is the why @code{%define api.pure full} should be
prefered over @code{%define api.pure}.
When @code{%locations %define api.pure full} is used, @code{yyerror} has the
following signature:
@example
void yyerror (char const *msg); /* Yacc parsers. */
void yyerror (YYLTYPE *locp, char const *msg); /* GLR parsers. */
@end example
If @samp{%parse-param @{int *nastiness@}} is used, then:
@example
void yyerror (int *nastiness, char const *msg); /* Yacc parsers. */
void yyerror (int *nastiness, char const *msg); /* GLR parsers. */
@end example
Finally, GLR and Yacc parsers share the same @code{yyerror} calling
convention for absolutely pure parsers, i.e., when the calling
convention of @code{yylex} @emph{and} the calling convention of
@samp{%define api.pure} are pure.
I.e.:
@example
/* Location tracking. */
%locations
/* Pure yylex. */
%define api.pure
%lex-param @{int *nastiness@}
/* Pure yyparse. */
%parse-param @{int *nastiness@}
%parse-param @{int *randomness@}
@end example
@noindent
results in the following signatures for all the parser kinds:
@example
int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
int yyparse (int *nastiness, int *randomness);
void yyerror (YYLTYPE *locp,
int *nastiness, int *randomness,
char const *msg);
void yyerror (YYLTYPE *locp, char const *msg);
@end example
@noindent
@@ -7675,9 +7696,9 @@ mysterious behavior altogether. You simply need to activate a more powerful
parser table construction algorithm by using the @code{%define lr.type}
directive.
@deffn {Directive} {%define lr.type @var{TYPE}}
@deffn {Directive} {%define lr.type} @var{type}
Specify the type of parser tables within the LR(1) family. The accepted
values for @var{TYPE} are:
values for @var{type} are:
@itemize
@item @code{lalr} (default)
@@ -7865,9 +7886,9 @@ split the parse instead.
To adjust which states have default reductions enabled, use the
@code{%define lr.default-reduction} directive.
@deffn {Directive} {%define lr.default-reduction @var{WHERE}}
@deffn {Directive} {%define lr.default-reduction} @var{where}
Specify the kind of states that are permitted to contain default reductions.
The accepted values of @var{WHERE} are:
The accepted values of @var{where} are:
@itemize
@item @code{most} (default for LALR and IELR)
@item @code{consistent}
@@ -7905,7 +7926,7 @@ that solves these problems for canonical LR, IELR, and LALR without
sacrificing @code{%nonassoc}, default reductions, or state merging. You can
enable LAC with the @code{%define parse.lac} directive.
@deffn {Directive} {%define parse.lac @var{VALUE}}
@deffn {Directive} {%define parse.lac} @var{value}
Enable LAC to improve syntax error handling.
@itemize
@item @code{none} (default)
@@ -8001,9 +8022,9 @@ resolution because they are useless in the generated parser. However,
keeping unreachable states is sometimes useful when trying to understand the
relationship between the parser and the grammar.
@deffn {Directive} {%define lr.keep-unreachable-state @var{VALUE}}
@deffn {Directive} {%define lr.keep-unreachable-state} @var{value}
Request that Bison allow unreachable states to remain in the parser tables.
@var{VALUE} must be a Boolean. The default is @code{false}.
@var{value} must be a Boolean. The default is @code{false}.
@end deffn
There are a few caveats to consider:
@@ -10278,7 +10299,7 @@ depends whether you use unions, or variants.
@node Split Symbols
@subsubsection Split Symbols
Therefore the interface is as follows.
The interface is as follows.
@deftypemethod {parser} {int} yylex (semantic_type* @var{yylval}, location_type* @var{yylloc}, @var{type1} @var{arg1}, ...)
@deftypemethodx {parser} {int} yylex (semantic_type* @var{yylval}, @var{type1} @var{arg1}, ...)
@@ -10977,8 +10998,7 @@ You can create documentation for generated parsers using Javadoc.
Contrary to C parsers, Java parsers do not use global variables; the
state of the parser is always local to an instance of the parser class.
Therefore, all Java parsers are ``pure'', and the @code{%pure-parser}
and @samp{%define api.pure} directives does not do anything when used in
Java.
and @code{%define api.pure} directives do nothing when used in Java.
Push parsers are currently unsupported in Java and @code{%define
api.push-pull} have no effect.
@@ -11612,7 +11632,7 @@ or
@quotation
My parser includes support for an @samp{#include}-like feature, in
which case I run @code{yyparse} from @code{yyparse}. This fails
although I did specify @samp{%define api.pure}.
although I did specify @samp{%define api.pure full}.
@end quotation
These problems typically come not from Bison itself, but from

View File

@@ -79,7 +79,7 @@ AT_CLEANUP
m4_pushdef([AT_TEST],
[AT_SETUP([Initial location: $1 $2])
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2 %parse-param { int x }])
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
AT_DATA_GRAMMAR([[input.y]],
[[%defines /* FIXME: Required by lalr1.cc in Bison 2.6. */
%locations
@@ -87,7 +87,6 @@ AT_DATA_GRAMMAR([[input.y]],
%skeleton "$1"
]$2[
]$3[
%parse-param { int x } // Useless, but used to force yyerror purity.
%code
{
# include <stdio.h>
@@ -113,11 +112,11 @@ exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
int
main (void)
{]AT_SKEL_CC_IF([[
yy::parser p (0);
yy::parser p;
p.set_debug_level (!!getenv("YYDEBUG"));
return p.parse ();]], [[
yydebug = !!getenv("YYDEBUG");
return !!yyparse (0);]])[
return !!yyparse (]AT_PARAM_IF([0])[);]])[
}
]])
@@ -132,10 +131,12 @@ AT_CLEANUP
## FIXME: test Java, and iterate over skeletons.
AT_TEST([yacc.c])
AT_TEST([yacc.c], [%define api.pure])
AT_TEST([yacc.c], [%define api.pure full])
AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
AT_TEST([yacc.c], [%define api.push-pull both])
AT_TEST([yacc.c], [%define api.push-pull both %define api.pure])
AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
AT_TEST([glr.c])
AT_TEST([glr.c], [%define api.pure])
AT_TEST([lalr1.cc])
AT_TEST([glr.cc])
@@ -146,7 +147,7 @@ AT_TEST([glr.cc])
## Weirdly enough, to trigger the warning with GCC 4.7, we must not
## use fprintf, so run the test twice: once to check the warning
## (absence thereof), and another time to check the value.
AT_TEST([yacc.c], [%define api.pure],
AT_TEST([yacc.c], [%define api.pure full],
[[%{
# define YYLTYPE int
# define YY_LOCATION_PRINT(Stream, Loc) \
@@ -157,7 +158,7 @@ AT_TEST([yacc.c], [%define api.pure],
]],
[@&t@])
AT_TEST([yacc.c], [%define api.pure],
AT_TEST([yacc.c], [%define api.pure full],
[[%{
# define YYLTYPE int
# define YY_LOCATION_PRINT(Stream, Loc) \

View File

@@ -606,8 +606,8 @@ AT_CHECK_CALC_LALR([%verbose])
AT_CHECK_CALC_LALR([%yacc])
AT_CHECK_CALC_LALR([%define parse.error verbose])
AT_CHECK_CALC_LALR([%define api.pure %locations])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %locations])
AT_CHECK_CALC_LALR([%define api.pure full %locations])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %define api.prefix "calc" %verbose %yacc])
@@ -617,8 +617,8 @@ AT_CHECK_CALC_LALR([%debug])
AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure full %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])

View File

@@ -152,10 +152,6 @@ m4_pushdef([AT_PURE_IF],
[m4_bmatch([$3], [%define *api\.pure\|%pure-parser],
[m4_bmatch([$3], [%define *api\.pure *"?false"?], [$2], [$1])],
[$2])])
m4_pushdef([AT_PURE_AND_LOC_IF],
[m4_bmatch([$3], [%locations], [AT_PURE_IF($@)], [$2])])
m4_pushdef([AT_GLR_OR_PARAM_IF],
[m4_bmatch([$3], [%glr-parser\|%parse-param], [$1], [$2])])
m4_pushdef([AT_NAME_PREFIX],
[m4_bmatch([$3], [\(%define api\.prefix\|%name-prefix\) ".*"],
[m4_bregexp([$3], [\(%define api\.prefix\|%name-prefix\) "\([^""]*\)"], [\2])],
@@ -171,14 +167,26 @@ m4_pushdef([AT_API_prefix],
[yy])])
m4_pushdef([AT_API_PREFIX],
[m4_toupper(AT_API_prefix)])
# yyerror receives the location if %location & %pure & (%glr or %parse-param).
# yyerror receives the location if %location, and if the parser is pure. For
# historical reasons, with the "yacc.c" skeleton, the location is not passed
# unless an additional "%parse-param" is present, or if the purity is defined
# as "full".
m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
[AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
m4_quote(m4_join([\|],
[%define api.pure "?full"?],
[%glr-parser],
[%parse-param],
[%skeleton "?glr.c"?])),
[$1], [$2])],
[$2])],
[$2])])
# yyerror always sees the locations (when activated), except if
# (yacc & pure & !param). FIXME: This is wrong. See the manual.
# yyerror always sees the locations (when activated) if the parser is impure.
# When the parser is pure, yyerror sees the location if it is received as an
# argument.
m4_pushdef([AT_YYERROR_SEES_LOC_IF],
[AT_LOCATION_IF([AT_YACC_IF([AT_PURE_IF([AT_PARAM_IF([$1], [$2])],
[AT_LOCATION_IF([AT_YACC_IF([AT_PURE_IF([AT_YYERROR_ARG_LOC_IF([$1], [$2])],
[$1])],
[$1])],
[$2])])
@@ -254,8 +262,6 @@ m4_popdef([AT_API_prefix])
m4_popdef([AT_TOKEN_PREFIX])
m4_popdef([AT_TOKEN_CTOR_IF])
m4_popdef([AT_NAME_PREFIX])
m4_popdef([AT_GLR_OR_PARAM_IF])
m4_popdef([AT_PURE_AND_LOC_IF])
m4_popdef([AT_LOCATION_TYPE_IF])
m4_popdef([AT_LOCATION_IF])
m4_popdef([AT_PARSE_PARAMS])
@@ -360,6 +366,7 @@ static
}]dnl
])
# AT_YYERROR_FORMALS
# AT_YYERROR_PROTOTYPE
# AT_YYERROR_DECLARE_EXTERN
# AT_YYERROR_DECLARE
@@ -368,7 +375,7 @@ static
# Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair.
m4_define([AT_YYERROR_FORMALS],
[m4_case(AT_LANG,
[c], [AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE *llocp, ])AT_PARSE_PARAMS [const char *msg]])[]dnl
[c], [AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS [const char *msg]])[]dnl
])
m4_define([AT_YYERROR_PROTOTYPE],