[antlr-interest] C target - initialization of return/scope structures

Cristian Târşoagă cristian.tarsoaga at gmail.com
Thu May 20 00:04:09 PDT 2010


Hi Jim, that is not my problem, let me show you an example

I want to have a scoped value which is a structure, and my structure holds
some std::strings

struct MyStruct
{
  std::string s1;
  std::string s2;
};

//this is part of my grammar
myrule
scope {MyStruct s;} //scoped VALUE
@init{}
@after{}
: rulegoeshere....;

As you can see, there is no pointer here, the scoped variable is a 'value'.
The code generated by antlr creates a scoped wrapper structure that holds
MyStruct, something like:

ctx->pMyParser_myruleTop = pMyParser_myrulePush(ctx); // this will create a
wrapper for the scoped value by calling ANTLR3_MALLOC

the wrapper looks like this:

typedef struct  MyParser_myrule_SCOPE_struct
{
    void    (ANTLR3_CDECL *free)    (struct MyParser_myrule_SCOPE_struct *
frame);
    MyStruct s;
}

As you can see my struct is inside this structure. The problem is that to
create the wrapper (see pMyParser_myrulePush above)
antlr calls ANTLR3_MALLOC (which does malloc of course).

THIS MEANS I'M GONNA GET A CRASH!

Why? because std::string is a c++ class, which HAS to be created/destroyed
using new/delete, not malloc/free.

That means, I cannot use a scoped VALUE, I have to use a scoped POINTER
instead, as suggested here:

http://www.mail-archive.com/il-antlr-interest@googlegroups.com/msg02614.html



Suggested Solution 1: local new/delete allocation/deallocation
------------------------------
-----------------------------------------------------------
So my rule will now look like this:

myrule
scope {MyStruct* s;} //scoped POINTER
@init{ $myrule::s = new MyStruct();} //explicit allocation using new
@after{ delete $myrule::s; } //explicit deallocation using delete
: rulegoeshere....;

Looks good? Well, I think not!
Because when the rule fails, the @after action is NOT called, and I'm gonna
get a nice memory leak.

Solution 1': the scoped wrapper has a member called free that can hold a
'deleter', but I couldn't find a way to set that.


Suggested Solution2: override antlr macros ANTLR3_MALLOC and ANTLR3_FREE
------------------------------------------------------------------------------------------------------------------------

Nice try, but ANTLR3_MALLOC is currently defined like this:
#define    ANTLR3_MALLOC(request)                    malloc
((size_t)(request))

As you can see, the 'request' argument is a SIZE, not a type, which means
that if I want to override it to make it use 'new' instead of malloc, I
cannot use it.
>From the given size I cannot deduce the type (this could work the other way
around if you change the define, to pass it the type you could get the size,
and it could be possible to override the default way of antlr's
allocations/deallocations)



That is my problem and those are the options I have. Maybe with some
adjustment some of them will work, but right now, I'm not happy with any of
them: first one leaks, second one is not usable.

Maybe you have some hints for me :-)

Thanks a lot for your answer

   Chris


More information about the antlr-interest mailing list