help-bison
[Top][All Lists]
Advanced

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

Re: [Fwd: question about error handling]


From: David Durham
Subject: Re: [Fwd: question about error handling]
Date: Tue, 12 Jun 2001 21:17:02 +0200

I'm not following you, but I'll respond anyway  ;)

The use of the base class is only to let all the parse tree nodes have
the functionality that they do the following:
    1) add themselves to the global list of parse tree nodes
    2) upon destruction remove themselves from that list

It's only a memory accounting thing...

And, in fact I do use the %union feature... All (most really) of the
elements in the union are pointers to derivations of that base class,
that because, of course, I need parse tree nodes to have a certain
semantic value.

For instance here is a subset of what I do:

- The base class is called SDPSNode
- I derive from SDPSNode: ADPSExpression ADPSStatement
- Then I derive from ADPSExpression: CDPSLiteralExpression,
CDPSBinaryExpression and CDPSUnaryExpression
- And I derive from ADPSStatement: CDPSIfStatement, CDPSLoopStatement,
and others...

in the union I have:
{
   int literal_integer;
   ADPSExpression *expr;
   ADPSStatement *stmt;
}

later I have rules...

expr
    : literal_integer
    {
        $$=new CDPSLiteralExpression(...)
    }
    | expr '+' expr
    {
        $$=CDPSBinaryExpression($1,'+',$3);
    }
    | '-' expr
    {
        $$=new CDPSUnaryExpression('-',$2);
    }
    ...
    ;

stmt
    : expr ';'
    {
        $$=new ...
    }
    | FOR '(' ... ')' stmt
    {
        $$=new CDPSLoopStatement(...) // passing child nodes to parent
        node
    }
    | IF '(' expr ')' stmt
    {
        /*
            Note: even tho $3 is an ADPSExpression * it is actually a
            pointer to a CDPSBinaryExpression, CDPSUnaryExpression,
            etc...
            Likewise, for $5.. it's a pointer to a ADPSStatement but is
            actually a pointer to some derivation of it...
        */
        $$=new CDPSIfStatement($3,$5);
    }
    ...
    ;


I do also, pass line number information and stuff also to the
constructor of the parse tree nodes..

Now, everytime I instantiate a parse tree node with 'new' it's adding
itself to the global list of pointers.  Then when/if I have a parse
error I just delete all the pointers in the list... I couldn't possibly
have a memory leak (short of an exception occuring within SDPSNodes
constructor)

Does this make any sense?

--Davy


On 11 Jun 2001 22:51:10 +0200, Hans Aberg wrote:
> At 10:52 -0500 2001/06/11, David Durham wrote:
> >As far as cleaning up memory upon parse errors... Here's what I did..
> >I'm using C++, but I'm sure something like this could be done with C if
> >you try really really hard ;)
> >
> >Anyway, all my parse tree nodes are C++ classes and they are all derived
> >from a base class.  This base class's constructor adds the this pointer
> >to a static data-member list of parse tree node pointers.  And the
> >virtual destructor of this base class removes itself from the list.
> >Then if I have an error, then I just delete all the pointers in this
> >list.
>
> I am curious, if you use C++ , why do you have to do all that; are you
> using the "%union" option?
>
> I use definitions of the type:
>
>   class parser_type {
>     // Automatic data
>   };
>
>   #define YYSTYPE parser_type
>
> It is not then possible to use the %union option if the automatic data
> contains classes with user defined constructors ("non-POD's"), as Bison
> uses a C/C++ union for that implementation, and only POD's are (currently)
> allowed in such unions.
>
> But if one does not like definitions like
>   class parser_type {
>     std::string name;
>     float number;
>   };
> which duplicates data, and thus is memory inefficient, in addition to the
> default constructors, then one can define a generic class
>   class object;
>
>   class object_root { ... };
>
>   class object {
>     object_root* data_;
>   public:
>     object(object_root* x = 0) : data_(x) { }
>     ...
>   };
> with say a ref count in object_root in order to avoid unneeded copying.
>
> Other data classes are derived from object_root:
>   class A : public virtual object_root { ... };
> The class object becomes a polymorphic data class for all available data.
> And then one defines:
>   class parser_type {
>     object value_;
>   };
>
> The disadvantage is that one gets dynamic allocations, but not so much if a
> ref count is used. And I cannot use the "%union" option. But on the other
> hand, I do not have to worry about resource management.
>
> I guess that this style is not for heavily optimized code. So the style to
> choose depends on what application one has at hand, I figure.
>
>   Hans Aberg
>
>
>
> _______________________________________________
> Help-bison mailing list
> address@hidden
> http://mail.gnu.org/mailman/listinfo/help-bison





reply via email to

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