代码之家  ›  专栏  ›  技术社区  ›  gornvix

分析多个文件时出现错误的lex状态

  •  2
  • gornvix  · 技术社区  · 9 年前

    我试图用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";
    

    解析时发生的情况是,第二个文件(“hello.txt”)解析正常,没有问题,但返回到第一个文件时出现了问题。读取行末尾的引号和分号,但lex处于INITIAL状态。所以lex不匹配我期望它匹配的规则。我知道这一点,因为如果我添加以下规则(它匹配):

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

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

    2 回复  |  直到 9 年前
        1
  •  2
  •   Jens    9 年前

    看起来它会转到INITIAL,因为这是你打电话后告诉它要做的 yypush_buffer_state() 。它怎么会和第二个相匹配 <include_state> 如果你这样做?如果删除状态更改会发生什么?

        2
  •  1
  •   rici    9 年前

    启动条件为 全球的 。它不是缓冲状态的一部分。推动和弹出缓冲状态 不要 改变它。你必须自己管理它。

    您可以将启动条件恢复为 include_state 在你完成 yypop_buffer_state 您甚至可以将自己的lexer状态堆栈保留在缓冲区堆栈的一侧。但最简单的解决方案似乎是阅读 #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 */ }