C++ 使用Bison解析char*字符串

C++ 使用Bison解析char*字符串,c++,parsing,bison,flex-lexer,C++,Parsing,Bison,Flex Lexer,如何使yyparse函数从C字符串读取其输入 已尝试使用yy扫描缓冲区(使用“fp”前缀而不是“yy”): 但是: 尝试使用yy_delete_buffer,相同的结果:未在此范围内声明 fp.y %{ #包括“英尺高” #包括 #包括 int fplex(); int fperror(字符*p); int fperror(char*p){} 使用名称空间std; 结构fs*AST; bool fpworking=true; %} %联合{ 结构fs*f; 结构ts*t; std::list*t

如何使yyparse函数从C字符串读取其输入

已尝试使用yy扫描缓冲区(使用“fp”前缀而不是“yy”):

但是:

尝试使用yy_delete_buffer,相同的结果:未在此范围内声明

fp.y

%{
#包括“英尺高”
#包括
#包括
int fplex();
int fperror(字符*p);
int fperror(char*p){}
使用名称空间std;
结构fs*AST;
bool fpworking=true;
%}
%联合{
结构fs*f;
结构ts*t;
std::list*tl;
std::string*s;
}
%令牌结束\u文件的\u
更多令牌在这里。。。
%%
s:公式'\n'{AST=$1;fpworking=true;yyapt;}
这里有更多规则。。。
fp.l

%{
#包括
#包括
使用名称空间std;
#包括“fp.tab.h”
%}
%选项No yywrap
%%
[a-z][a-zA-Z0-9]*{fplval.s=new std::string(fptext);return(TERM_ID);}
这里有更多的图案。。。
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...
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“英尺高”
int fpparse();
int signparse();
外部工作;
外部结构fs*AST;
int main(int argc,字符**argv)
{
更多代码在这里。。。
}

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

flex
bison
(或者通常是
lex
yacc
的派生)的传统用法严重依赖于全局状态变量,这使得很难将多个解析器和/或扫描程序集成到单个可执行文件中。修改
yy
前缀并不能真正解决这个问题,但它允许多个单例。较新版本的代码生成器允许生成
解析器和扫描器,它们将包含状态的结构作为附加参数。可以将您自己的状态添加到这些结构中,甚至可以将它们组合到单个结构中。这可以产生一个更优雅的界面,但是这些工具在API设计方面帮不了你多少忙。在任何情况下,使用纯解析器和扫描仪,外部可用的状态访问甚至更少


简而言之,您可能应该将自己的缓冲区管理API添加到
flex
文件中,将其接口导出到自己的头文件中,然后将该文件导入扫描仪、解析器及其使用者中

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

flex
bison
(或者通常是
lex
yacc
的派生)的传统用法严重依赖于全局状态变量,这使得很难将多个解析器和/或扫描程序集成到单个可执行文件中。修改
yy
前缀并不能真正解决这个问题,但它允许多个单例。较新版本的代码生成器允许生成
解析器和扫描器,它们将包含状态的结构作为附加参数。可以将您自己的状态添加到这些结构中,甚至可以将它们组合到单个结构中。这可以产生一个更优雅的界面,但是这些工具在API设计方面帮不了你多少忙。在任何情况下,使用纯解析器和扫描仪,外部可用的状态访问甚至更少


简而言之,您可能应该将自己的缓冲区管理API添加到
flex
文件中,将其接口导出到自己的头文件中,然后将该文件导入扫描仪、解析器及其使用者中

为了使用各种flex定义的符号(如
YY_BUFFER_STATE
YY_scan_BUFFER
),必须将这样做的代码放在.l文件的第3部分

问题在于,这些符号仅在lex.yy.c文件中定义,而不在任何头文件中定义,您可以在其他地方包含这些头文件


因此,您所需要做的就是将
parse
代码(上面的第一个块)放在.l文件的末尾(在第二行
%%
之后),并从
main
调用它,它应该可以正常工作。

为了使用各种flex定义的符号(例如
YY\u BUFFER\u STATE
YY\u scan\u BUFFER
),这样做的代码必须放在.l文件的第3部分

问题在于,这些符号仅在lex.yy.c文件中定义,而不在任何头文件中定义,您可以在其他地方包含这些头文件


因此,您只需将
parse
代码(上面的第一个块)放在.l文件的末尾(在第二行
%%
之后),然后从
main
调用它,它应该可以正常工作。

注意正确的标记。Flex用于Adobe/ApacheUI框架。Flex lexer用于词法分析器。问题在于您显示的代码和未显示的代码之间的交互。请构造一个完整的、自包含的、精简的.y文件来演示相同的问题。请注意正确的标记。Flex用于Adobe/ApacheUI框架。Flex lexer用于词法分析器。问题在于您显示的代码和未显示的代码之间的交互。请构造一个完整的、独立的切割
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
%{
#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...
%{
#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...
#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...
}