Reputation: 241
How can I make the yyparse function read its input from a C string?
Tried yy_scan_buffer (using "fp" prefix instead of "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;
}
But:
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
Tried using yy_delete_buffer, same result: was not declared in this scope.
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...
}
Upvotes: 0
Views: 1580
Reputation: 126140
In order to use the various flex-defined symbols (such as YY_BUFFER_STATE
and yy_scan_buffer
), the code that does so must be placed in the 3rd section of the .l file.
The issue is that these symbols are only defined in the lex.yy.c file, and not in any header file that you can #include
elsewhere.
So all you need to do is put your parse
code (the first block above) at the end of the .l file (after the second %%
line) and call it from main
and it should work fine.
Upvotes: 1
Reputation: 241671
The parser generated by bison
does no I/O. The responsibility for reading (or otherwise acquiring) input is given to the scanner, which is often generated by (f)lex
. The buffer management functions you refer to are part of the flex
framework. They are not exported in any header, so you either need to use them within the code inserted into the flex
input file, or explicitly add them to your own header file.
The traditional use of flex
and bison
(or, in general, derivatives of lex
and yacc
) relied heavily on global state variables, making it difficult to integrate multiple parsers and/or scanners into a single executable. Modifying the yy
prefix does not really solve this problem, but it does allow multiple singletons. More recent versions of the code-generators allow the generation of pure
parsers and scanners which take as an additional argument a structure containing the state. It's possible to add your own state to these structures, or even to combine them into a single structure. This can produce a more elegant interface, but the tools don't help you very much with API design. In any event, with pure parsers and scanners, even less state access is externally available.
In short, you should probably add your own buffer management API to your flex
file, export its interface(s) in your own header file, and import that file in your scanner, your parser, and their consumers.
Upvotes: 2