help-bison
[Top][All Lists]
Advanced

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

Re: How to free symbols during error recovery


From: Laurence Finston
Subject: Re: How to free symbols during error recovery
Date: Thu, 7 Oct 2004 17:13:51 +0200 (MEST)

I haven't started to implement recovery from parse errors in
my project yet, but I have decided not to use the `error'
token, precisely because it's not possible to control what
happens when the parser stack is unwound.

The following explains an alternative approach.  Please be
warned that I haven't tested it.  It could be simplified by
using C++ instead of C.

If you're generating a reentrant parser, which I always
recommend, you can pass a parameter to `yyparse()'
via a `void*'.
Let `struct Parameter_Type* p' be the parameter.
You said you are using a pointer to a C struct as your value
type.  If we call this type `A', then you could define
another type as follows:

struct A_Node
{
  struct A* a;
  struct A_Node* next;
};

`Parameter_Type' could contain a data member `struct A_Node* head'.
`p->head->a' must be 0.

At the end of the action for each rule containing symbols
that reference dynamically allocated objects of type `A',
a new `A_Node' is created for each object and a pointer to it is
pushed onto the linked list on `p':

struct A_Node* new_a_node = (struct A_Node*) malloc(size_of(struct A_Node));
new_a_node->a = $1; // or whatever.
new_a_node->next = p->head;
p->head = new_a_node;

If you reach the beginning of a rule action, then obviously
no parse error has occurred.  You must clear the linked list
of `A_Node' pointers before filling it up again:

while (p->head->a)
  {
     struct A_Node* temp_a_node = p->head->next;
     free(p->head);
     p->head = temp_a_node;
  }

The `A' pointers should not be freed!

Since `yyparse()' returns 1 upon error, you can wrap calls
to it in a loop like this:

int r;

do
   {
      r = yyparse((void*) p);

      if (r != 0)
        {
            /* Error recovery.  */

           while (p->head->a)  /* Here, `p->head->a' should be
                                  freed.  */
              {
                 struct A_Node* temp_a_node = p->head->next;
                 free(p->head->a);
                 free(p->head);
                 p->head = temp_a_node;
              }


           /* More error recovery, or `break', if it's hopeless.  */

       } // if

   }  // do

while (r != 0);

Laurence




reply via email to

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