]> git.saurik.com Git - bison.git/commitdiff
glr.cc, yacc.c: initialize yylloc properly
authorAkim Demaille <akim@lrde.epita.fr>
Tue, 6 Nov 2012 14:34:51 +0000 (15:34 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Tue, 6 Nov 2012 16:35:38 +0000 (17:35 +0100)
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.

NEWS
data/c.m4
data/glr.c
data/glr.cc
data/yacc.c
tests/actions.at

diff --git a/NEWS b/NEWS
index 37b8e2c02dbdae7675d7149740ee23492973f22b..3d21470a0685fa0c929a3ae1508c0b3c1e15d7ba 100644 (file)
--- a/NEWS
+++ b/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.
index a1013ccceb1e0ab9d3808df9d9268db78a78ec95..8bd96b8573f728b0bbf35c593ef33ddea5a082f8 100644 (file)
--- a/data/c.m4
+++ b/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
-])
+]])
index a2992e089e9bd0171a7c8961bdb874bbd73ecd80..9bd95228da6e0615a627d416f338f7b6b54a1e4e 100644 (file)
@@ -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
index 826bc80e76b1bbe72811fa534c215cb89ac08d95..104bf785b66d5fd9d20c51124a011b8e4306ac3c 100644 (file)
@@ -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)
index e82264ffaad30e6df45a8e69ae561cf1a031c9d7..b9a4fb182ff92c578a1fb83ba372a0b7d3d37686 100644 (file)
@@ -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;
 
 /*------------------------------------------------------------.
index fc70f48a6219e43681562354f163f33ce948e984..0e02239f4eb4126b65e5b9a14149bd0e528f75b1 100644 (file)
@@ -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])