mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-22 18:53:04 +00:00
glr.cc, yacc.c: initialize yylloc properly
There are several issues to address here. One is that yylloc should be initialized when possible. Another is that the push parser needs to update yypushed_loc when the user modified it. And if the parser starts by a reduction of an empty, it uses the first location on the stack, which, therefore, must also be initialized to this initial location. This is getting complex, especially since because initializing a global (impure interface) is different from initializing a local variable. To simplify, the local yylloc is not initialized during its definition. * data/c.m4 (b4_yyloc_default_define): Replace by... (b4_yyloc_default): this. Adjust dependencies. * data/glr.cc: Initialize yylloc. * data/yacc.c (b4_declare_scanner_communication_variables): Initialize yylloc during its definition. Don't define yyloc_default. (yypush_parse): The location formal is not const, as we might initialize it. (yyparse): Define yyloc_default. Use it before running the user initial action. Possibly update the first location on the stack, and the pushed location after the user initial action. * tests/actions.at (Initial locations): Check that the initial location is correct.
This commit is contained in:
3
NEWS
3
NEWS
@@ -16,6 +16,9 @@ GNU Bison NEWS
|
||||
|
||||
Nul characters are correctly displayed in error messages.
|
||||
|
||||
When possible, yylloc is correctly initialized before calling yylex. It
|
||||
is no longer necessary to initialize it in the %initial-action.
|
||||
|
||||
* Noteworthy changes in release 2.6.4 (2012-10-23) [stable]
|
||||
|
||||
Bison 2.6.3's --version was incorrect. This release fixes this issue.
|
||||
|
||||
14
data/c.m4
14
data/c.m4
@@ -673,12 +673,11 @@ m4_define([b4_yy_location_print_define],
|
||||
#endif]])
|
||||
])
|
||||
|
||||
# b4_yyloc_default_define
|
||||
# -----------------------
|
||||
# Define yyloc_default, which can be used to initialize location
|
||||
# variables.
|
||||
m4_define([b4_yyloc_default_define],
|
||||
[[static YYLTYPE yyloc_default
|
||||
# b4_yyloc_default
|
||||
# ----------------
|
||||
# Expand to a possible default value for yylloc.
|
||||
m4_define([b4_yyloc_default],
|
||||
[[
|
||||
# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
|
||||
= { ]m4_join([, ],
|
||||
m4_defn([b4_location_initial_line]),
|
||||
@@ -686,5 +685,4 @@ m4_define([b4_yyloc_default_define],
|
||||
m4_defn([b4_location_initial_line]),
|
||||
m4_defn([b4_location_initial_column]))[ }
|
||||
# endif
|
||||
;]dnl
|
||||
])
|
||||
]])
|
||||
|
||||
@@ -226,8 +226,8 @@ b4_percent_code_get([[top]])[
|
||||
right-hand sides. Unlike the standard yacc.c template, here we set
|
||||
the default value of $$ to a zeroed-out value. Since the default
|
||||
value is undefined, this behavior is technically correct. */
|
||||
static YYSTYPE yyval_default;]b4_locations_if([
|
||||
b4_yyloc_default_define])[
|
||||
static YYSTYPE yyval_default;]b4_locations_if([[
|
||||
static YYLTYPE yyloc_default][]b4_yyloc_default;])[
|
||||
|
||||
/* Copy the second part of user declarations. */
|
||||
]b4_user_post_prologue
|
||||
|
||||
@@ -87,12 +87,17 @@ m4_define([b4_yy_symbol_print_generate],
|
||||
]b4_parse_param_use[]dnl
|
||||
[ yyparser.yy_symbol_print_ (yytype, yyvaluep]b4_locations_if([, yylocationp])[);
|
||||
}
|
||||
]])
|
||||
]])[
|
||||
|
||||
# Hijack the initial action to initialize the locations.
|
||||
]b4_locations_if([b4_percent_define_ifdef([[location_type]], [],
|
||||
[m4_define([b4_initial_action],
|
||||
[yylloc.initialize ();]m4_ifdef([b4_initial_action], [
|
||||
m4_defn([b4_initial_action])]))])])[
|
||||
|
||||
# Hijack the post prologue to insert early definition of YYLLOC_DEFAULT
|
||||
# and declaration of yyerror.
|
||||
m4_append([b4_post_prologue],
|
||||
]m4_append([b4_post_prologue],
|
||||
[b4_syncline([@oline@], [@ofile@])[
|
||||
]b4_yylloc_default_define[
|
||||
#define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
|
||||
|
||||
21
data/yacc.c
21
data/yacc.c
@@ -181,8 +181,7 @@ int yychar;
|
||||
#else
|
||||
/* Default value used for initialization, for pacifying older GCCs
|
||||
or non-GCC compilers. */
|
||||
static YYSTYPE yyval_default;]b4_locations_if([
|
||||
b4_yyloc_default_define])[
|
||||
static YYSTYPE yyval_default;
|
||||
# define YY_INITIAL_VALUE(Value) = Value
|
||||
#endif]])[
|
||||
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
||||
@@ -197,7 +196,8 @@ b4_yyloc_default_define])[
|
||||
YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);]b4_locations_if([[
|
||||
|
||||
/* Location data for the lookahead symbol. */
|
||||
YYLTYPE yylloc YY_INITIAL_VALUE(yyloc_default);]])b4_pure_if([], [[
|
||||
YYLTYPE yylloc][]b4_yyloc_default[;
|
||||
]])b4_pure_if([], [[
|
||||
|
||||
/* Number of syntax errors so far. */
|
||||
int yynerrs;]])])
|
||||
@@ -265,7 +265,7 @@ typedef struct ]b4_prefix[pstate ]b4_prefix[pstate;
|
||||
[[b4_prefix[pstate *ps]], [[ps]]]b4_pure_if([,
|
||||
[[[int pushed_char]], [[pushed_char]]],
|
||||
[[b4_api_PREFIX[STYPE const *pushed_val]], [[pushed_val]]]b4_locations_if([,
|
||||
[[b4_api_PREFIX[LTYPE const *pushed_loc]], [[pushed_loc]]]])])m4_ifset([b4_parse_param], [,
|
||||
[[b4_api_PREFIX[LTYPE *pushed_loc]], [[pushed_loc]]]])])m4_ifset([b4_parse_param], [,
|
||||
b4_parse_param]))
|
||||
b4_pull_if([b4_c_function_decl([b4_prefix[pull_parse]], [[int]],
|
||||
[[b4_prefix[pstate *ps]], [[ps]]]m4_ifset([b4_parse_param], [,
|
||||
@@ -1409,7 +1409,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
|
||||
yypstate *yyps_local;]b4_pure_if([[
|
||||
int yychar;
|
||||
YYSTYPE yylval;]b4_locations_if([[
|
||||
YYLTYPE yylloc;]])])[
|
||||
YYLTYPE yylloc][]b4_yyloc_default[;]])])[
|
||||
if (yyps)
|
||||
yyps_local = yyps;
|
||||
else
|
||||
@@ -1489,7 +1489,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
|
||||
[[[yypstate *yyps]], [[yyps]]]b4_pure_if([,
|
||||
[[[int yypushed_char]], [[yypushed_char]]],
|
||||
[[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([,
|
||||
[[[YYLTYPE const *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param], [,
|
||||
[[[YYLTYPE *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param], [,
|
||||
b4_parse_param]))], [[
|
||||
|
||||
|
||||
@@ -1556,16 +1556,17 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
|
||||
yyerrstatus = 0;
|
||||
yynerrs = 0;
|
||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||
]m4_ifdef([b4_initial_action],[
|
||||
]m4_ifdef([b4_initial_action], [
|
||||
b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [],
|
||||
[m4_define([b4_at_dollar_used])yylloc])dnl
|
||||
[m4_define([b4_at_dollar_used])dnl
|
||||
b4_push_if([b4_pure_if([*])yypushed_loc], [yylloc])])dnl
|
||||
/* User initialization code. */
|
||||
b4_user_initial_action
|
||||
b4_dollar_popdef[]dnl
|
||||
m4_ifdef([b4_dollar_dollar_used],[[ yyvsp[0] = yylval;
|
||||
]])dnl
|
||||
m4_ifdef([b4_at_dollar_used], [[ yylsp[0] = yylloc;
|
||||
]])])dnl
|
||||
b4_locations_if([[ yylsp[0] = ]b4_push_if([b4_pure_if([*])yypushed_loc], [yylloc])[;
|
||||
]])dnl
|
||||
[ goto yysetstate;
|
||||
|
||||
/*------------------------------------------------------------.
|
||||
|
||||
@@ -69,6 +69,76 @@ AT_PARSER_CHECK([./input], 0,
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------ ##
|
||||
## Initial location. ##
|
||||
## ------------------ ##
|
||||
|
||||
# AT_TEST(SKELETON-NAME, DIRECTIVES)
|
||||
# ----------------------------------
|
||||
# Check the the initial location is correct.
|
||||
m4_pushdef([AT_TEST],
|
||||
[AT_SETUP([Initial location: $1 $2])
|
||||
|
||||
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2 %parse-param { int x }])
|
||||
AT_DATA_GRAMMAR([[input.y]],
|
||||
[[%defines /* FIXME: Required by lalr1.cc in Bison 2.6. */
|
||||
%locations
|
||||
%debug
|
||||
%skeleton "$1"
|
||||
$2
|
||||
%parse-param { int x } // Useless, but used to force yyerror purity.
|
||||
%code
|
||||
{
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h> // getenv
|
||||
]AT_YYERROR_DECLARE[
|
||||
]AT_YYLEX_DECLARE[
|
||||
}
|
||||
%%
|
||||
exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
|
||||
[[YY_LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
|
||||
%%
|
||||
]AT_YYERROR_DEFINE[
|
||||
|
||||
]AT_YYLEX_PROTOTYPE[
|
||||
{]AT_PURE_IF([
|
||||
YYUSE(lvalp);
|
||||
YYUSE(llocp);], [AT_SKEL_CC_IF([
|
||||
YYUSE(lvalp);
|
||||
YYUSE(llocp);])])[
|
||||
return 'x';
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{]AT_SKEL_CC_IF([[
|
||||
yy::parser p (0);
|
||||
p.set_debug_level (!!getenv("YYDEBUG"));
|
||||
return p.parse ();]], [[
|
||||
yydebug = !!getenv("YYDEBUG");
|
||||
return !!yyparse (0);]])[
|
||||
}
|
||||
]])
|
||||
|
||||
AT_FULL_COMPILE([input])
|
||||
AT_PARSER_CHECK([./input], 1, [],
|
||||
[[1.1
|
||||
1.1: syntax error
|
||||
]])
|
||||
AT_BISON_OPTION_POPDEFS
|
||||
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.push-pull both])
|
||||
AT_TEST([yacc.c], [%define api.push-pull both %define api.pure])
|
||||
AT_TEST([glr.c])
|
||||
AT_TEST([lalr1.cc])
|
||||
AT_TEST([glr.cc])
|
||||
|
||||
m4_popdef([AT_TEST])
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user