开发者

Interfacing a Yacc/Bison Parser with a C++ program

开发者 https://www.devze.com 2023-03-18 06:20 出处:网络
This is not a duplicate of this question because the solution was not to use a parser! I have a Bison parser I can run by doing ./parser < file_to_parse.I want to call the Bison parser from within

This is not a duplicate of this question because the solution was not to use a parser!

I have a Bison parser I can run by doing ./parser < file_to_parse. I want to call the Bison parser from within my C++ program. What I don't want is to do system(./parser < file_to_parse) because that would assume the parser is pre-compiled and then my whole program would not be platform independant.

If I have a function:

void foo(file_name) {
   //开发者_如何学JAVA call parser on file_name
}

then how can this be done? Any ideas? I think it's the case of calling yyparse or something but I'm not getting anywhere with it!

Thank you :).


Are you using a version that is adapted to C++?

I use the one by Alain Coetmeur.

At the moment, I only have code handy for employing flex++, but it should show you how this goes.

When you run flex++ it will output a header file and an implementation file for a new class to do the parsing. Add these to your project, then write:

// Construct new instance of parser
::lex * plex = new lex();

// tell parser what file to parse
plex->yyin = _wfopen(L"C:/Documents and Settings/All Users/Application Data/QuietWake/eCrew/new_rules_to_be_parsed.txt",L"r");

// run the parser
int lex_return = plex->yylex();


That's precisely what you do -- you call yyparse(). You write yylex() such that your main program can specify its input. Presumably your current yylex() calls getchar() or something to read a character; instead you'll presumably need to write it to take input from some place specified by your main program.


This is C Code but I guess it will be an indicative case for C++ too.
When we had to make a compiler in the university we had to define the YY_DECL in a .l file like this:

#define YY_DECL int alpha_yylex(yylval_) void *yylval_;

The int alpha_yylex(yylval_) is the function and the void *yylval is the parameter type.
Clearly, you need this so for the parser to know where to start from aka which function is the one that parsing should be done from.

You also need to extern this function prototype (extern int alpha_yylex(void *yylval_); ) in your .y file.
After that the Flex/Bison utilities will autogenerate the relevant .c files for you.

In general, .l is for the lexical rules and .y is for grammatical rules. Therefore if you need to get the value from somewhere you must define a union in .y like this (an example):

%union {

   union {
      int Integer;
      double Double;
      char Character;
      char* String;
   } value;

}

Then, depending on your syntactical and rules, you can do yylval.value.String = strdup(yytext) in your .l file and, depending on your grammatical rules, $$.Double = $1.Double + $3.Double in your .y file.

I don't remember a lot since it's been a while that I've done that but I guess you can try and you can refer to the documentation or ask here :)

P.S: (I had a good FAQ somewhere but can't remember where the heck it is -> will post later if I am lucky enough to find it xD :D xD)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号