Okay, I figured it out. The reason is that there is a particularly nasty (and poorly documented) interaction going on between flex and lemon.
In an attempt to save memory, lemon will hold onto a token without copying, and push it on to an internal token stack. However, flex also tries to save memory by changing the value that yyget_text
points to as it lexes the input. The offending line in my example is:
// in the do loop of main.c...
Parse(parser, token, yyget_text(lexer));
This should be:
Parse(parser, token, strdup(yyget_text(lexer)));
which will ensure that the value that lemon points to when it reduces the token stack later is the same as what you originally passed in.
(Note: Don't forget, strdup
means you'll have to free that memory at some point later. Lemon will let you write token "destructors" that can do this, or if you're building an AST tree you should wait until the end of the AST lifetime.)