Как я могу заставить функцию yyparse читать ее ввод из строки C?
Tried 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...
}
Чтобы использовать различные гибкие символы (такие как YY_BUFFER_STATE
и yy_scan_buffer
), код, который делает это, должен быть помещен в 3-й раздел файла.l.
Проблема в том, что эти символы определены только в файле lex.yy.c, а не в любом заголовочном файле, который можно #include
другом месте.
Итак, все, что вам нужно сделать, это поместить ваш parse
(первый блок выше) в конец.l файла (после второй строки %%
) и вызвать его из main
и он должен работать нормально.
Парсер, созданный bison
не выполняет ввода-вывода. Ответственность за считывание (или иное получение) вводится сканеру, который часто генерируется (f)lex
. Функции управления буфером, которые вы называете, являются частью flex
структуры. Они не экспортируются ни в какой заголовок, поэтому вам нужно либо использовать их в коде, вставленном в файл ввода flex
, либо явно добавить его в свой собственный заголовочный файл.
Традиционное использование flex
и bison
(или, вообще, производных lex
и yacc
) в значительной степени основывалось на глобальных переменных состояния, что затрудняло интеграцию нескольких парсеров и/или сканеров в один исполняемый файл. Изменение префикса yy
самом деле не решает эту проблему, но позволяет разрешить несколько синглетонов. Более поздние версии генераторов кода позволяют генерировать pure
парсеры и сканеры, которые в качестве дополнительного аргумента принимают структуру, содержащую состояние. Можно добавить свое собственное состояние в эти структуры или даже объединить их в единую структуру. Это может создать более элегантный интерфейс, но инструменты не помогут вам в разработке API. В любом случае, с чистыми анализаторами и сканерами, доступ к внешнему виду может быть менее доступным.
Короче говоря, вы, вероятно, должны добавить свой собственный API управления буфером в свой файл flex
, экспортировать его интерфейсы в свой собственный заголовочный файл и импортировать этот файл в свой сканер, ваш парсер и своих потребителей.