2013-10-05 92 views
0

如何使yyparse函数从C字符串读取其输入?使用Bison从char *字符串解析

试图yy_scan_buffer(使用 “FP” 的前缀,而不是 “YY”):

extern YY_BUFFER_STATE fs_scan_string (const char *str); 

struct fs *parse(char *s) 
{ 
fp_scan_buffer(s); 
int r = fpparse(); 
return r == 0 ? AST : NULL; 

} 

但是:

h1.cpp:27: error: ‘YY_BUFFER_STATE’ does not name a type 
h1.cpp: In function ‘fs* parse(char*)’: 
h1.cpp:32: error: ‘fp_scan_buffer’ was not declared in this scope 

使用yy_delete_buffer,同样的结果尝试:在未声明这个范围。

fp.y

%{ 
#include "ft.h" 
#include <map> 
#include <iostream> 

int fplex(); 
int fperror(char *p); 
int fperror(char *p) { } 

using namespace std; 

struct fs *AST; 
bool fpworking = true; 
%} 

%union { 
    struct fs *f; 
    struct ts *t; 
    std::list<struct ts *> *tl; 
    std::string *s; 
} 

%token END_OF_FILE 
MORE TOKEN HERE... 

%% 

s : formula '\n' { AST = $1; fpworking = true; YYACCEPT; } 
MORE RULE HERE... 

FP.L

%{ 
#include <iostream> 
#include <list> 
using namespace std; 
#include "fp.tab.h" 
%} 

%option noyywrap 

%% 
[a-z][a-zA-Z0-9]*  { fplval.s = new std::string(fptext); return (TERM_ID); } 
MORE PATTERN HERE... 

h1.cpp

#include <iostream> 
#include <list> 
#include <string> 
#include <map> 
#include <stdlib.h> 
#include <fstream> 
#include "ft.h" 

int fpparse(); 
int signparse(); 

extern bool fpworking; 
extern struct fs *AST; 

int main(int argc, char **argv) 
{ 
    MORE CODE HERE... 
} 
+0

请注意正确的标记。 Flex用于Adobe/Apache UI框架。 Flex-lexer用于词法分析器。 – JeffryHouser

+0

问题出在您显示的代码与您未显示的代码之间的交互中。请构建一个完整的,自包含的,精简的.y文件,演示相同的问题。 – zwol

回答

1

为了使用各种灵活定义的符号(如YY_BUFFER_STATEyy_scan_buffer),代码必须放在.l文件的第三部分。

问题是这些符号只能在lex.yy.c文件中定义,而不能在任何其他地方可以使用的头文件中定义。

因此,所有你需要做的就是把你的parse代码(上面的第一个块)在.L文件的末尾(第二%%行之后),并从main调用它,它应该工作的罚款。

2

通过bison产生的解析器不进行I/O。读取(或以其他方式获取)输入的责任由扫描仪提供,通常由(f)lex生成。您所指的缓冲区管理功能是flex框架的一部分。它们不会被导出到任何头文件中,因此您需要在插入到flex输入文件的代码中使用它们,或者将它们明确地添加到您自己的头文件中。

传统使用的flexbison(的lexyacc或,一般地,衍生物)很大程度上依赖于全局状态变量,使得难以多个语法分析器和/或扫描仪集成到单个可执行文件。修改yy前缀并不能真正解决这个问题,但它确实允许多个单身人士。代码生成器的更新版本允许生成pure解析器和扫描器,它们将包含该状态的结构作为附加参数。可以将这些状态添加到这些结构中,甚至可以将它们组合到一个单一结构中。这可以产生一个更优雅的界面,但这些工具对API设计无助。无论如何,使用纯粹的解析器和扫描器,更少的状态访问是外部可用的。简而言之,您应该将自己的缓冲区管理API添加到您的flex文件中,将其接口导出到您自己的头文件中,然后在扫描程序,解析器和消费者中导入该文件。