为了重新创建缩进定义的Python块,我在开始时偶然发现了这一点。
当我单独尝试我的词法分析器/扫描仪时,它会使用我所做的开始条件正确地返回预期结果。但是当它与Bison解析器耦合时,不会保留正确的状态,并且我会从意外状态接收令牌。
对我来说,预期的行为是在行的开头返回标签/空格的“INDENT”标记,并在找到另一个符号(不是标签/空格)后为每个符号返回“OTHER”标记,直到开始新的线。
scanner.l
%{
#include <iostream>
%}
%option noyywrap
%x INDENT
%%
BEGIN(INDENT);
<INDENT>[ \t] { std::cout << "INDENT "; }
<INDENT>.|\n { yyless(0); BEGIN(INITIAL); }
\n { std::cout << std::endl; BEGIN(INDENT); }
. { std::cout << "OTHER "; }
%%
int main(){
yylex();
return 0;
}
输入“ test ”(“test”之前和之后的两个空格)返回“其他其他指标”。
scanner.l
%{
#include <iostream>
#include "parser.h"
%}
%option noyywrap
%x INDENT
%%
BEGIN(INDENT);
<INDENT>[ \t] { return T_INDENT; }
<INDENT>.|\n { yyless(0); BEGIN(INITIAL); }
\n { BEGIN(INDENT); return T_NEWLINE; }
. { return T_OTHER; }
%%
parser.y
%{
#include <iostream>
extern int yylex();
void yyerror(const char *s);
%}
%define parse.error verbose
%token T_INDENT T_OTHER T_NEWLINE
%%
program : program symbol
| %empty
;
symbol : T_INDENT { std::cout << "INDENT "; }
| T_NEWLINE { std::cout << std::endl; }
| T_OTHER { std::cout << "OTHER "; }
;
%%
void yyerror(const char *s){
std::cout << s;
}
int main(){
yyparse();
return 0;
}
输入“ test ”(与之前相同)返回“其他其他其他非本地人”。虽然预期结果与上述相同。
Bison解析器似乎收到了错误的令牌,好像它不符合启动条件。我已经读过一些关于解析器由于超前行为而弄乱了启动条件的事情,但是我不确定问题是在这个范围内还是我如何反击它。
答案 0 :(得分:0)
因为你有
BEGIN(INDENT)
规则部分没有模式,这是逐字复制到yylex函数的顶部,因此每次调用yylex时它都会运行。因此,每次野牛调用yylex获取新令牌时,状态都会重置为INDENT
并获得T_INDENT
令牌。
在你的“第一种情况”示例中,词法分析器在EOF之前不会返回,所以你只需要调用一次,它只设置一次INDENT
状态。
如果您希望此代码仅在您第一次调用yylex时运行,则需要将其设置为仅运行一次。类似的东西:
{ static bool not_first_time;
if (!not_first_time) {
BEGIN(INDENT);
not_first_time = true; } }
或者,进行设置以使INITIAL
成为预期的初始状态。