解析多个文件时错误的 lex 状态
Wrong lex state when parsing multiple files
我正在尝试使用 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")解析正常,没有问题,但是returning到第一个文件时出现问题。读取行尾的引号和分号,但 lex 处于 INITIAL 状态。所以 lex 不符合我期望它匹配的规则。我肯定知道这一点,因为如果我添加以下规则(匹配):
<INITIAL>\"[ \t]*";" { printf("Right matching, wrong state.\n"); return 1; }
为什么它没有 return 到 include_state,我该如何解决这个问题?
看起来它进入了 INITIAL,因为这是你在调用 yypush_buffer_state() 后告诉它要做的事情。如果你这样做,它怎么会匹配第二个 <include_state>
呢?如果删除该状态更改会怎样?
开始条件是全局。它不是缓冲区状态的一部分。压入和弹出缓冲区状态不改变它。你必须自己管理它。
您可以在执行 yypop_buffer_state
后将开始条件恢复为 include_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 */ }
我正在尝试使用 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")解析正常,没有问题,但是returning到第一个文件时出现问题。读取行尾的引号和分号,但 lex 处于 INITIAL 状态。所以 lex 不符合我期望它匹配的规则。我肯定知道这一点,因为如果我添加以下规则(匹配):
<INITIAL>\"[ \t]*";" { printf("Right matching, wrong state.\n"); return 1; }
为什么它没有 return 到 include_state,我该如何解决这个问题?
看起来它进入了 INITIAL,因为这是你在调用 yypush_buffer_state() 后告诉它要做的事情。如果你这样做,它怎么会匹配第二个 <include_state>
呢?如果删除该状态更改会怎样?
开始条件是全局。它不是缓冲区状态的一部分。压入和弹出缓冲区状态不改变它。你必须自己管理它。
您可以在执行 yypop_buffer_state
后将开始条件恢复为 include_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 */ }