Reputation: 439
I want to teach flex & bison to detect the macro definitions in pure C. Actually i'am adding this function to the existing parser form here. The parser itself is good, but it lacks macro functionality. So i did add successfully the #include
and pragma
macros detection, but with the selection macroses i have the problems, this is the code in the parser:
macro_selection_variants
: macro_compound_statement
| include_statement
| pragma_statement
| macro_selection_statement
| statement
;
macro_selection_statement
: MACRO_IFDEF IDENTIFIER macro_selection_variants MACRO_ENDIF
| MACRO_IFDEF IDENTIFIER macro_selection_variants MACRO_ELSE macro_selection_variants MACRO_ENDIF
| MACRO_IFNDEF IDENTIFIER macro_selection_variants MACRO_ENDIF
| MACRO_IFNDEF IDENTIFIER macro_selection_variants MACRO_ELSE macro_selection_variants MACRO_ENDIF
;
statement
is declared like so:
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
And the lexer part for those macroses is:
"#ifdef" { count(); return(MACRO_IFDEF); }
"#ifndef" { count(); return(MACRO_IFNDEF); }
"#else" { count(); return(MACRO_ELSE); }
"#endif" { count(); return(MACRO_ENDIF); }
So the problem is i get the 2 reduce/reduce
errors because i'm trying to use statement
in my macro_selection_statement
. I need to use statement
in the macro selection block, because those blocks can have variables definitions likes so:
#ifdef USER
#include "user.h"
int some_var;
char some_text[]="hello";
#ifdef ONE
int two=0;
#endif
#endif
What would be the right move here? because i read that %expect -rr N
is a really bad thing to do with the reduce
warnings.
Upvotes: 0
Views: 1300
Reputation: 241731
You cannot really expect to implement a preprocessor (properly) inside of a C grammar. It needs to be a *pre*processor; that is, it reads the program text, and its output is sent to the C grammar.
It is possible to (mostly) avoid doing a second lex pass, since (in theory) the preprocessor can output tokens rather than a stream of characters. That would probably work well with a bison 2.7-or-better "push parser", so you might want to give it a try. But the traditional approach is just a stream of characters, which may well be easier.
It's important to remember that the replacement text of a macro, as well as the arguments to the macro, have no syntactic constraints. (Or almost no constraints.) The following is entirely legal:
#define OPEN {
#define CLOSE }
#define SAY(whatever) puts(#whatever);
#include <stdio.h>
int main(int argc, char** argv) OPEN SAY(===>) return 0; CLOSE
And that's just a start :)
Upvotes: 1