我在使用(可重入)Flex + Lemon进行解析时遇到问题.我用一个简单的语法和词法这里.当我运行它时,我会输入一个数字后跟一个EOF标记(Ctrl-D).打印输出将显示:
89
found int of .
AST=0.
Run Code Online (Sandbox Code Playgroud)
第一行是我输入的数字.从理论上讲,AST值应该是我输入的所有内容的总和.
编辑:当我手动调用Parse()时,它正确运行.
此外,atom ::= INT即使令牌为0(停止令牌),柠檬似乎也会运行规则.为什么是这样?我对这种行为非常困惑,我找不到任何好的文档.
好的,我明白了.原因是在flex和lemon之间存在一种特别令人讨厌的(并且文档记录很少)的交互.
为了节省内存,lemon将保留一个令牌而不复制,并将其推送到内部令牌堆栈.但是,flex也会尝试通过更改yyget_text指向输入的值来节省内存.我的例子中的违规行是:
// in the do loop of main.c...
Parse(parser, token, yyget_text(lexer));
Run Code Online (Sandbox Code Playgroud)
这应该是:
Parse(parser, token, strdup(yyget_text(lexer)));
Run Code Online (Sandbox Code Playgroud)
这将确保柠檬在以后减少令牌堆栈时指向的值与您最初传入的值相同.
(注意:不要忘记,strdup意味着你必须在以后某个时候释放那个记忆.柠檬会让你写出可以做到这一点的令牌"析构函数",或者如果你正在构建一个AST树,你应该等到AST生命周期结束.)