所以,我正在制作一个使用f lex和bison解析器读取配置文件的巨型程序。
我需要在main.cpp程序中包含解析器的输出
使用
%output "config.cc"
%defines "config.h"
只是为"未识别的字符串"添加错误。其他选择没有'工作也很好。知道为什么这不起作用吗?
这是我的词法分析器和野牛文件
%{
#include <stdio.h>
#include <string>
#include <map>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "Monopoly.h"
using namespace std;
extern int yylex();
extern void yyerror(char*);
Monopoly game;
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
%}
%token LTOKEN INTEGER LOCATIONWORD WORD GTOKEN CURRENCYTOKEN JAILFINETOKEN STARTINGMONEYTOKEN RTOKEN COSTTOKEN RENTTOKEN FILEPATHTOKEN OBJEXTENSION MODELTOKEN TAXTOKEN PERCENTSIGN
%union{
std::string *str;
int number;
}
%token <number> INTEGER
%token <str> WORD
%%
commands: /* empty */
| command commands
;
command:
currency_set
|
location_set
|
startingMoney_set
|
jailFine_set
|
route_add
|
cost_set
|
rent_set
|
filepath_found
|
tax_set
;
filepath_found:MODELTOKEN LTOKEN INTEGER FILEPATHTOKEN WORD OBJEXTENSION
{
printf(" File %s HAS BEEN IMPORTED for location number %d \n",$5,$3 );
}
rent_set:RENTTOKEN LTOKEN INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER
{
printf("rent for house no 4 is %d \n",$7);
}
cost_set:COSTTOKEN LTOKEN INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER
{
printf("prices set to %d\n",$10 );
}
currency_set:CURRENCYTOKEN WORD
{
game.currency=($2);
printf("Currency set to %s",game.currency->c_str());
}
location_set:
LOCATIONWORD LTOKEN INTEGER WORD GTOKEN INTEGER
{
printf("location number %d set to %s in froup number %d",$3,$4,$6);
}
startingMoney_set:
STARTINGMONEYTOKEN INTEGER
{
printf("starting money set to %d \n",$2 );
}
jailFine_set:
JAILFINETOKEN INTEGER
{
printf("jailfine set to %d\n",$2);
}
route_add:
RTOKEN LTOKEN INTEGER LTOKEN INTEGER
{
printf("Route set up between location no %d and %d\n",$3,$5);
}
tax_set:
TAXTOKEN INTEGER PERCENTSIGN INTEGER
{
printf("tax set to %d percent\n",$2 );
}
%%
int yywrap()
{
return 1;
}
extern FILE * yyin;
int main()
{
yyin=fopen("config.txt","r");
yyparse();
string json="{ \"hello\" : \"world\"} ";
rapidjson::Document d;
d.Parse<0>(json.c_str());
printf("%s\n", d["hello"].GetString());
return 1;
}
%{
#include <stdio.h>
#include <string>
#include "bisoner.tab.h"
using namespace std;
%}
%%
"Tax" return TAXTOKEN;
"rent" return RENTTOKEN;
"cost" return COSTTOKEN;
"route" return RTOKEN;
"Currency" return CURRENCYTOKEN;
"StartingMoney" return STARTINGMONEYTOKEN;
"JailFine" return JAILFINETOKEN;
"location" return LOCATIONWORD;
"@l" return LTOKEN;
"@g" return GTOKEN;
"model" return MODELTOKEN;
"#"[a-zA-Z0-9.-_= ]+ printf("comment ignored\n");
[0-9]+ yylval.number=atoi(yytext);return INTEGER;
[a-zA-Z]+ yylval.str=new string(yytext);return WORD;
"./"([[a-zA-Z0-9]+"/"]*)? return FILEPATHTOKEN;
".obj" return OBJEXTENSION;
"%" return PERCENTSIGN;
%%
答案 0 :(得分:2)
现代C ++项目中适当的flex / bison设置是一个主要的PITA,因为示例质量相当差,生成的代码鼓励过时的实践,例如非重入代码和全局变量。这在#80;而不是2014年是可以的。
尝试调整我几周前制作的例子。该设置非常简单,因为它将Flex lexer和Bison解析器封装在单独的命名空间中的一个单独的类(称为Interpreter)中。它是可重入的,并与良好的旧C ++ 03兼容。
https://github.com/ezaquarii/bison-flex-cpp-example
唯一棘手的部分是重构类名以满足您的需求。一旦你编译它,你就可以开始使用* .y和* .l文件来实现你有趣的东西,而无需对抗Bison / Flex设置特性。享受!
答案 1 :(得分:0)
我想出的解决方案是将文件一起编译。只需将yyparse()函数声明为其他cpp文件中的extern,以及任何其他变量。我将附上我的makefile
CFLAGS=-ll
CC=g++
all:example2
example2: main.cpp lex.yy.c bisoner.tab.c
$(CC) main.cpp lex.yy.c bisoner.tab.c Player.cpp Location.cpp Monopoly.cpp -o example2 -ll
bisoner.tab.c:bisoner.y
bison -d bisoner.y
lex.yy.c:lexer.l
lex lexer.l
clean:
rm -rf *o example2