解析多个文件时错误的lex状态

时间:2015-01-29 14:20:46

标签: c bison yacc lex

我试图用win flex和bison解析两个文件,但是我遇到了一个问题,即lex不在我期待的状态。在lex文件中:

include[ \t]+\" { BEGIN(include_state); }
<include_state>([^\\\"\n]|\\.)+ {
    yyin = fopen(yytext, "r");
    if (!yyin) {
        printf("Error opening include file: %s\n", yytext);
        return 1;
    }
    yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
        yyscanner);
    BEGIN(INITIAL);
}
<include_state>\"[ \t]*";" { BEGIN(INITIAL); }
<<EOF>> {
    yypop_buffer_state(yyscanner);
    if (!YY_CURRENT_BUFFER)
        yyterminate();
}

正在解析的第一个文件包括第二个文件,如下所示:

include "hello.txt";

解析时会发生第二个文件(&#34; hello.txt&#34;)解析后没有问题,但返回第一个文件时出现问题。读取行尾的引号和半冒号,但是lex处于INITIAL状态。因此,lex与我期望匹配的规则不匹配。我肯定知道这一点,因为如果我添加以下规则(匹配):

<INITIAL>\"[ \t]*";" { printf("Right matching, wrong state.\n"); return 1; }

为什么不返回include_state,我该如何解决?

2 个答案:

答案 0 :(得分:2)

看起来它是INITIAL,因为这是你在调用 yypush_buffer_state()后告诉它的。如果你这样做,它将如何匹配第二个<include_state>?如果删除状态更改会发生什么?

答案 1 :(得分:1)

开始条件是全球。它不是缓冲状态的一部分。推送和弹出缓冲区状态不会更改它。你必须自己管理它。

执行include_state后,您可以将开始条件恢复为yypop_buffer_state。您甚至可以在缓冲区堆栈旁边保留自己的词法分析器堆栈。但最简单的解决方案似乎是在执行#include之前阅读#include语句中的结束标点符号,以便在更改缓冲区时始终处于INITIAL状态:

<include_state>[^\n"]+\" {
    yytext[yyleng - 1] = 0; // Get rid of the close quote.
    yyin = fopen(yytext, "r");
    if (!yyin) {
        printf("Error opening include file: %s\n", yytext);
        return 1;
    }
    yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
                        yyscanner);
    BEGIN(INITIAL);
}
<include_state>.|\n   { /* Handle syntax error in #include */ }