Friday, April 17, 2009

An updated template for the Lemon Parser Generator

I have always been fond of the Lemon Parser Generator. Ever since I became interested in compilers, Lemon has always been my default choice when considering parser generators. Hyacc is also a good choice, if you need a cannonical LR(1) generator, but - like most parser generators - it carries too much baggage trying to be compatible with yacc.

However, during the construction of my NuBASIC grammar, I discovered a couple of minor problems with the default template (lempar.c), packaged with the source code.

The first problem was minor - lempar.c didn't #include , even though it used assert(). A simple fix.

The second problem was more serious. Lemon uses a directive, %extra_argument, to allow the user to supply an extra argument to the parser, which is of user-defined type. This is in keeping with Lemons philospohy of being a fully reentrant parser. The documentation for Lemon states:

The %extra_argument directive instructs Lemon to add a 4th parameter to the parameter list of the Parse() function it generates. Lemon doesn't do anything itself with this extra argument, but it does make the argument available to C-code action routines, destructors, and so forth. For example, if the grammar file contains:


Unfortunately, this is not the case when using the default template. The %extra_argument is not available to destructor code. If you take a look at yy_destructor(), there is simply nothing there to make it available.

I have repaired both of these problems by modifying lempar.c. I would have been more elegant to modify the source code itself, but I was in a hurry - and it works.

My modification adds an extra argument to yy_destructor(). The original looks like this:

static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor)

and the modified version:

static void yy_destructor(yyParser * yypParser, YYCODETYPE yymajor, YYMINORTYPE *yypminor)

The yypParser parameter is required, since it contains the value of the %extra_argument. After the definition of yy_destructor(), it is redefined as a macro to ensure the following code passes a (yyParser *) o the function. I also did some identifier renaming to ensure the macro worked throughout the code.

Finally, an added ParseARG_FETCH; is inserted into yy_destructor(), making %extra_argument available to the destructor code.

The modified lempar.c can be downloaded here.

No comments:

Post a Comment