I am trying to write a pretty printer for my input language. In java, I read in the source, convert to the AST, then use a tree grammar to call the StringTemplates, and everything works fine. However, I need to use C as the target language, and there isn't a StringTemplate implementation in C.
I looked at the examples that are available on the antlr.org website, but the only ones that pretty print are toy examples, and simple append the character strings to the text contained in the token literals. This isn't really a feasible approach in my language. So, what I've ended up doing is following a pattern more or less like the following:
However, I've encountered a few problems with this approach. First, when I call factory->close(..) at the end of my program, I get a double free problem, and I don't see in the API where I can call remove on the string from the factory. However, more troubling is that when the return of one of the rules like anotherRule is composed of only small literal strings (like "()"), then calling destroy on the result sometimes frees too much memory, so that I cause problems for "thirdRule". Moreover, this just seems like an awkward way to build up my output string.
Since this seems like a pretty common task, I was wondering if there is a common, recommended way of doing this?
> I am trying to write a pretty printer for my input language. In java, > I read in the source, convert to the AST, then use a tree grammar > to call the StringTemplates, and everything works fine. However, > I need to use C as the target language, and there isn't a StringTemplate > implementation in C.
> I looked at the examples that are available on the antlr.org website, > but the only ones that pretty print are toy examples, and simple append > the character strings to the text contained in the token literals. This > isn't really a feasible approach in my language. So, what I've ended up > doing is following a pattern more or less like the following:
> However, I've encountered a few problems with this approach. First, > when I call factory->close(..) at the end of my program, I get a double > free problem,
You should not be calling the factory->destroy. Just close the factory, and if you use the parsers factory, you don't need to do that. When you are done, just memcpy (or strdup) the chars pointer from teh final string. All the other memory will be discarded for you. If you are just going to write out the result, then fwrite the chars pointer and close as normal - all memmory will be freed for you. You are trying to do too much:
fwrite(... $result->chars ...); factory->close(factory); // But only if this is your own factory, which there is no need for really.
and I don't see in the API where I can call remove on
> the string from the factory. However, more troubling is that when the > return of one of the rules like anotherRule is composed of only > small literal strings (like "()"), then calling destroy on the result > sometimes > frees too much memory,
You don't use destroy() like this, so next time you try to use it, you have already corrupted the memory.
so that I cause problems for "thirdRule".
> Moreover, this just seems like an awkward way to build up my output > string.
That is because you are sassuming that you have to do oall the management. You don't do that, you just let the factory take care of it all. When you close, it has trcked all the mmemory and it frees it all for you. You just use teh strings and forget about them as if they were Java objects. Use the factory in the parser (see C examples for poly for instance), and you don't even need to close your own factory.
> Since this seems like a pretty common task, I was wondering if > there is a common, recommended way of doing this?
Read the API docs for more info :-) However, not that you do not NEED to use teh string factory stuff it is really just a convenience. You can copy the input text yourself suign teh token supplied offests.
At 15:37 16/12/2008, Jim Idle wrote: >You don't do that, you just let the factory take care of >it all. When you close, it has trcked all the mmemory and >it frees it all for you. You just use teh strings and forget >about them as if they were Java objects. Use the factory in >the parser (see C examples for poly for instance), and you >don't even need to close your own factory.
What if you've got lots of temporary strings though (or a big input file)? Wouldn't the memory usage add up quickly?
You could start with plain Java code that prints a Java AST: http://www.jazillian.com/antlr/emitter.html ...and just change the "case" statements in JavaEmitter.print() to their C equivalents.
> I am trying to write a pretty printer for my input language. In java, > I read in the source, convert to the AST, then use a tree grammar > to call the StringTemplates, and everything works fine. However, > I need to use C as the target language, and there isn't a StringTemplate > implementation in C.
> I looked at the examples that are available on the antlr.org website, > but the only ones that pretty print are toy examples, and simple append > the character strings to the text contained in the token literals. This > isn't really a feasible approach in my language. So, what I've ended up > doing is following a pattern more or less like the following:
> However, I've encountered a few problems with this approach. First, > when I call factory->close(..) at the end of my program, I get a double > free problem, and I don't see in the API where I can call remove on > the string from the factory. However, more troubling is that when the > return of one of the rules like anotherRule is composed of only > small literal strings (like "()"), then calling destroy on the result sometimes > frees too much memory, so that I cause problems for "thirdRule". > Moreover, this just seems like an awkward way to build up my output > string.
> Since this seems like a pretty common task, I was wondering if > there is a common, recommended way of doing this?
On Mon, 15 Dec 2008 23:35:11 -0800, Gavin Lambert <AN...@mirality.co.nz> wrote:
> At 15:37 16/12/2008, Jim Idle wrote: > >You don't do that, you just let the factory take care of > >it all. When you close, it has trcked all the mmemory and > >it frees it all for you. You just use teh strings and forget > >about them as if they were Java objects. Use the factory in > >the parser (see C examples for poly for instance), and you > >don't even need to close your own factory.
> What if you've got lots of temporary strings though (or a big input > file)? Wouldn't the memory usage add up quickly?
Depends how you use it, but of course this isn't the most efficient way.
That is why it is only a convenience thing and if you have megabytes of text to build up and cannot afford the memory space then you should use the tokens and extract the strings yourself.
To be honest though, my experience has been that it is relatively small beer for an average size program.