yacc.c: support "%define api.pure full"

This makes the interface for yyerror() pure without the need for a spurious
parse_param.

* data/yacc.c (b4_pure_if, b4_pure_flag): New definition, accept three states.
(b4_yacc_pure_if): Rename as...
(b4_yyerror_arg_loc_if): This, and use b4_pure_flag.
* tests/actions.at (%define api.pure): Modernize.
* test/calc.at (Simple LALR Calculator): Modernize.
* tests/local.at (AT_YYERROR_ARG_LOC_IF): Adjust.
This commit is contained in:
Theophile Ranquet
2012-11-23 17:30:47 +00:00
parent dbb998364f
commit 6428a8a4a5
4 changed files with 38 additions and 23 deletions

View File

@@ -65,24 +65,36 @@ m4_define_default([b4_stack_depth_init], [200])
## ------------------------ ## ## ------------------------ ##
b4_percent_define_default([[api.pure]], [[false]]) b4_percent_define_default([[api.pure]], [[false]])
b4_define_flag_if([pure]) b4_percent_define_check_values([[[[api.pure]],
m4_define([b4_pure_flag], [[false]], [[true]], [[]], [[full]]]])
[b4_percent_define_flag_if([[api.pure]], [[1]], [[0]])])
# b4_yacc_pure_if(IF-TRUE, IF-FALSE) m4_define([b4_pure_flag], [[0]])
# ---------------------------------- m4_case(b4_percent_define_get([[api.pure]]),
# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise. [false], [m4_define([b4_pure_flag], [[0]])],
m4_define([b4_yacc_pure_if], [true], [m4_define([b4_pure_flag], [[1]])],
[b4_pure_if([m4_ifset([b4_parse_param], [], [m4_define([b4_pure_flag], [[1]])],
[$1], [$2])], [full], [m4_define([b4_pure_flag], [[2]])])
[$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 # b4_yyerror_args
# --------------- # ---------------
# Arguments passed to yyerror: user args plus yylloc. # Arguments passed to yyerror: user args plus yylloc.
m4_define([b4_yyerror_args], 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_c_args(b4_parse_param), ])]) m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])

View File

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

View File

@@ -604,8 +604,8 @@ AT_CHECK_CALC_LALR([%verbose])
AT_CHECK_CALC_LALR([%yacc]) AT_CHECK_CALC_LALR([%yacc])
AT_CHECK_CALC_LALR([%error-verbose]) AT_CHECK_CALC_LALR([%error-verbose])
AT_CHECK_CALC_LALR([%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 %locations]) AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
AT_CHECK_CALC_LALR([%error-verbose %locations]) AT_CHECK_CALC_LALR([%error-verbose %locations])
AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
@@ -615,8 +615,8 @@ AT_CHECK_CALC_LALR([%debug])
AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%define api.pure full %verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])

View File

@@ -168,6 +168,7 @@ m4_pushdef([AT_API_PREFIX],
m4_pushdef([AT_YYERROR_ARG_LOC_IF], m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3], [AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
m4_quote(m4_join([\|], m4_quote(m4_join([\|],
[%define api.pure "?full"?],
[%glr-parser], [%glr-parser],
[%parse-param], [%parse-param],
[%skeleton "?glr.c"?])), [%skeleton "?glr.c"?])),
@@ -355,6 +356,7 @@ static
}]dnl }]dnl
]) ])
# AT_YYERROR_FORMALS
# AT_YYERROR_PROTOTYPE # AT_YYERROR_PROTOTYPE
# AT_YYERROR_DECLARE_EXTERN # AT_YYERROR_DECLARE_EXTERN
# AT_YYERROR_DECLARE # AT_YYERROR_DECLARE