bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: user destructor for unresolved GLR semantic value


From: Joel E. Denny
Subject: Re: user destructor for unresolved GLR semantic value
Date: Thu, 25 Aug 2005 15:45:49 -0400 (EDT)

On Wed, 24 Aug 2005, Joel E. Denny wrote:

> 3. Although my patch prevents the potential seg fault, I believe there's
> still a potential memory leak that it does not address.  That is, if
> !yyresolved, the yyGLRState stores a list of yySemanticOption's.  Each
> yySemanticOption has a yystate member.  That yystate is the last state in
> a RHS potentially containing many semantic values.  For this case of an
> error during a split stack, I cannot find where the user destructors are
> called for those semantic values.  Based on the `well-formed' comment at
> `yyreturn:', I wonder if this might be a conscious decision.  I'll
> continue to explore this, but does anyone already know what's going on?

The test case below should write `Destructor called.' to stdout exactly
once in order to pass.  Before applying the patch below, it doesn't write
anything to stdout.  Exit status should be 0.

I believe it is true that, at any point during a split GLR parse, a single
candidate parse tree can be identified by choosing one stack, one semantic
option from each of the stack's unresolved states, and one semantic option
from each of the unresolved states on the RHS of each semantic option.
Moreover, each such parse tree contains all semantic values produced by
user actions before the split.  Thus, after an error during the split
parse, it should be sufficient to traverse only one of these trees in
order to call user destructors on all existing semantic values.  Does this
makes sense?

I went ahead and renamed yydestroyStackItem() to yydestroyGLRState().

Joel

---------------------------------------------------------------------
%{
  #include <stdio.h>
  #include <stdlib.h>
  static void yyerror (char const *);
  static int yylex (void);
%}

%glr-parser
%union { int value; }
%type <value> 'a'

%destructor {
  printf ("Destructor called.\n");
} 'a'

%%

start: 'a' | 'a' ;

%%

static int
yylex (void)
{
  static char const *input = "a";
  return *input++;
}

static void
yyerror (char const *msg)
{
  fprintf (stderr, "%s\n", msg);
}

int
main (void)
{
  return yyparse () != 1;
}
---------------------------------------------------------------------

Index: data/glr.c
===================================================================
RCS file: /cvsroot/bison/bison/data/glr.c,v
retrieving revision 1.116
diff -p -u -r1.116 glr.c
--- data/glr.c  25 Aug 2005 17:57:23 -0000      1.116
+++ data/glr.c  25 Aug 2005 19:18:06 -0000
@@ -886,8 +886,15 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYST

 ]b4_yydestruct_generate([b4_c_ansi_function_def])[

+/** Number of symbols composing the right hand side of rule #RULE. */
+static inline int
+yyrhsLength (yyRuleNum yyrule)
+{
+  return yyr2[yyrule];
+}
+
 static void
-yydestroyStackItem (char const *yymsg, yyGLRState *yys)
+yydestroyGLRState (char const *yymsg, yyGLRState *yys)
 {
   if (yys->yyresolved)
     yydestruct (yymsg, yystos[yys->yylrState],
@@ -903,16 +910,20 @@ yydestroyStackItem (char const *yymsg, y
          YYFPRINTF (stderr, "\n");
        }
 #endif
+
+      if (yys->yysemantics.yyfirstVal)
+        {
+          yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
+          yyGLRState *yyrhs;
+          int yyn;
+          for (yyrhs = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
+               yyn > 0;
+               yyrhs = yyrhs->yypred, --yyn)
+            yydestroyGLRState (yymsg, yyrhs);
+        }
     }
 }

-/** Number of symbols composing the right hand side of rule #RULE. */
-static inline int
-yyrhsLength (yyRuleNum yyrule)
-{
-  return yyr2[yyrule];
-}
-
 /** Left-hand-side symbol for rule #RULE. */
 static inline yySymbol
 yylhsNonterm (yyRuleNum yyrule)
@@ -2001,7 +2012,7 @@ yyrecoverSyntaxError (yyGLRStack* yystac
            }
        }
 ]b4_location_if([[      yystack->yyerror_range[1].yystate.yyloc = 
yys->yyloc;]])[
-      yydestroyStackItem ("Error: popping", yys);
+      yydestroyGLRState ("Error: popping", yys);
       yystack->yytops.yystates[0] = yys->yypred;
       yystack->yynextFree -= 1;
       yystack->yyspaceLeft += 1;
@@ -2201,7 +2212,7 @@ b4_syncline(address@hidden@], address@hidden@])])dnl
          {
            yyGLRState *yys = yystates[0];
 ]b4_location_if([[       yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
-)[         yydestroyStackItem ("Cleanup: popping", yys);
+)[         yydestroyGLRState ("Cleanup: popping", yys);
            yystates[0] = yys->yypred;
            yystack.yynextFree -= 1;
            yystack.yyspaceLeft += 1;







reply via email to

[Prev in Thread] Current Thread [Next in Thread]