【发布时间】:2016-10-19 00:24:30
【问题描述】:
在尝试重新创建由缩进定义的 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”前后两个空格)返回“INDENT INDENT INDENT OTHER OTHER OTHER OTHER OTHER OTHER”。
第二种情况,解析器返回意外结果
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 ”(与之前相同)返回“INDENT INDENT OTHER OTHER OTHER OTHER OTHER INDENT INDENT”。而预期的结果与上述相同。
Bison 解析器似乎接收到了错误的标记,就好像它不遵守开始条件一样。我读过一些关于解析器由于前瞻行为而弄乱启动条件的内容,但我不确定问题是否在此之内,也不确定我将如何解决它。
【问题讨论】:
-
这是一种非常奇怪的方法。我会有
^[ \t] BEGIN INDENT;,而不是从那个状态开始。
标签: bison flex-lexer