我很难跟踪一个相当大的flex / bison解析器中的错误(1000个语法规则,1500个状态,400个终端)。扫描仪匹配在该特定点不应出现的终端,并且不存在于数据文件中。
我想解析的输入是
<el Re="1.0" Im="-1.0"/>
并且输出的最后几行是
Reading a token: Next token is token ELEMENTTEXT (1.1-1.1: )
matched 4 characters: Re=
matched 1 characters: "
matched 6 characters: -1 Im=
这看起来像是内存损坏,因为源中没有“-1 Im”。我希望下一个标记为'1.0',它与标记aNumber
匹配。
我已经检查了我能想到的一切,我打开了野牛调试---这使我更加困惑,现在我正试图通过扫描仪的内部一次一个角色。是否有任何工具可以提供我的输出:
next character matched "x" - possible terminals
ONE
TWO
SEVEN
...
答案 0 :(得分:1)
我认为显示的调试输出是在解析器中生成的,而不是从扫描器生成的。在扫描仪中查看调试输出的最佳方法是使用-d
或--debug
命令行选项生成扫描程序,或将%option debug
放入Flex扫描程序定义中。这将为每个匹配的规则打印一行到stderr。
基于DFA的正则表达式识别不提供有意义的逐字符调试输出;从理论上讲,国家机器的进展可以追溯,但很难解释,可能并非一切有用。
解析器中调试输出中明显损坏的信息很可能是扫描仪操作的结果,如下所示:
{some_pattern} { /* DO NOT DO THIS */ yylval.str = yytext;
return SOME_TOKEN;
}
yytext
的值及其指向的内存对扫描程序yylex
是私有的,值可能会更改,恕不另行通知。特别是,一旦再次调用yylex
来扫描先行标记,缓冲区很可能会以不可预测的方式移动。
相反,您必须复制令牌字符串(并记住在不再需要时释放该副本):
{some_pattern} { yylval.str = strdup(yytext);
return SOME_TOKEN;
}
注意:如果您不想使用strdup
(可能因为您的令牌可能包含NUL字符),那么一个不错的选择是:
char* buf = malloc(yyleng + 1); /* No need to call strlen */
memcpy(buf, yytext, yyleng); /* Works even if there is a NUL in the token */
buf[yyleng] = 0; /* Remember to NUL-terminate the copy */
参考文献:flex manual note on yytext / bison FAQ on destroyed strings