help-bison
[Top][All Lists]
Advanced

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

Re: Re[2]: bison %union and C++


From: Hans Aberg
Subject: Re: Re[2]: bison %union and C++
Date: Tue, 8 Oct 2002 16:03:06 +0200

At 14:55 +0200 2002/10/08, Akim Demaille wrote:
>| It may happen can handle it by the use of a construct
>|   try {
>|     // Bison generated code.
>|   } catch (...) {
>|     // Bison destructor code
>|     throw; // re-throw the exception.
>|   }
>|
>| Then any C++ exception out of the Bison parser will be able to execute
>| resource deallocating before passing the exception on to the program
>| calling the parser.
>|
>| Some may use an "embedded C++" subset which does not admit C++ exceptions.
>| So Bison should support that, then that try-catch construct above must be
>| an option.
>
>I agree in a perfect world that's the way things should probably be
>done.  But in this very material world, for the time being, I'm afraid
>we will just tell the user not to use exceptions.

The most obvious thing under C++ is to not use %union or your Bison
destructors:

Then the C++ exceptions system will clean up the memory via normal C++
calls destructors.

For a while, I used a variation of %union that I called %typed, which does
all type checking that %union does, but does not require a C/C++ YYSTYPE
union, plus some additional macros admitting one to do some polymorphic
typecasting.

However, I did not find the type checking feature that essential, so I
stopped using it, instead using a single YYSTYPE C++ class:
  my_yystype {
    std::string text_;
    long number_;
    object object_; // C++ polymorphic variable.
  };
Here, text_ is most often needed to give the names of what the lexer finds
(like in future error messages). The number_ is also sometimes needed to
communicate extra information about the parsing. The overhead of these two
always carried along is not that big (I hope). Then object_ holds a pointer
to all other objects created in the parsing.

Right now, I experiment with an implementation of Prolog in the form of a
metalogic inference system for theorem proof verification. -- The
construction above suffices for my purposes.

As for the exceptions, I rarely use any rule that as such throws an
exception. But I think it may happen that exceptions are thrown through the
parser, if one say hooks up the parser to parse a stream that may throw an
exception.

So exception safety for general (not restricted to embedded) C++ use, I
think will be a must.

>BTW, I'm not sure we can find a means to use try/catch to recover the
>memory thrown away during a successful error recovery.

I am not sure why you think not:

All that the C++ exception handler does is to call the C++ destructors of
the destroyed objects in a suitable order, until returning the execution at
a suitable catch point.

The object registered with your Bison cleanup system should be such that
they are not seen by the C++ exception handler system (which happens if
they are allocated with malloc or "new"). Then, when you arrive at the
catch (...) above, there should be no problem merely invoking your Bison
destructor: If the objects registered with it, they should not interfere
with the C++ exception handling or vice versa.

>%destructor { delete $$; } expr stmt etc...
>%destructor { free ($$); } C_STRING

I guess hat this assumes that you know what is on each entry in the stack,
so that one can use the right destructor.

But what should the problem otherwise be?

  Hans Aberg






reply via email to

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