C++ 使用Bison解析char*字符串
如何使yyparse函数从C字符串读取其输入 已尝试使用yy扫描缓冲区(使用“fp”前缀而不是“yy”): 但是: 尝试使用yy_delete_buffer,相同的结果:未在此范围内声明 fp.yC++ 使用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
%{
#包括“英尺高”
#包括
#包括
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...
}