柔性扫描仪的逐字符描述

时间:2015-10-14 17:22:42

标签: debugging flex-lexer

我很难跟踪一个相当大的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
...

1 个答案:

答案 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