如何让 yyparse 函数从C字符串中读取其输入?
尝试 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 :(得分:2)
由bison
生成的解析器不执行I / O.读取(或以其他方式获取)输入的责任被提供给扫描仪,其通常由(f)lex
生成。您引用的缓冲区管理功能是flex
框架的一部分。它们不会在任何标头中导出,因此您需要在插入flex
输入文件的代码中使用它们,或者将它们显式添加到您自己的头文件中。
flex
和bison
(或者,通常是lex
和yacc
的衍生物)的传统用法在很大程度上依赖于全局状态变量,因此难以集成多个解析器和/或扫描器成为单个可执行文件。修改yy
前缀并不能真正解决这个问题,但它确实允许多个单例。更新版本的代码生成器允许生成pure
解析器和扫描器,它们将包含状态的结构作为附加参数。可以将自己的状态添加到这些结构中,甚至可以将它们组合成单个结构。这可以产生更优雅的界面,但这些工具对API设计没有太大帮助。无论如何,使用纯粹的解析器和扫描仪,可以从外部获得更少的状态访问。
简而言之,您应该将自己的缓冲区管理API添加到flex
文件中,将其界面导出到您自己的头文件中,然后将该文件导入扫描仪,解析器及其使用者。
答案 1 :(得分:1)
为了使用各种flex定义的符号(例如YY_BUFFER_STATE
和yy_scan_buffer
),执行此操作的代码必须放在.l文件的第3部分中。
问题是这些符号只在lex.yy.c文件中定义,而不是在其他地方#include
的任何头文件中定义。
所以你需要做的就是将你的parse
代码(上面的第一个块)放在.l文件的末尾(在第二个%%
行之后)并从{{1}调用它它应该可以正常工作。