I was able to sidestep this problem when manually setting up the order in which header files are read by the compiler. In this case, I'm able to spoof the default "pearl" with the correct definition, but when I have no control of the order in which headers are included, this... genius of engineering surfaces:
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
/* %if-c-only Standard (non-C++) definition */
extern int yylex \
(YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
#define YY_DECL int yylex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
/* %endif */
/* %if-c++-only C++ definition */
/* %endif */
#endif /* !YY_DECL */
This is defined in the header file, but my definition of YY_DECL
is copied into *.c
file.
The documentation says:
(If your environment supports function prototypes, then it will be "int yylex( void )".) This definition may be changed by defining the "YY_DECL" macro. For example, you could use:
#define YY_DECL float lexscan( a, b ) float a, b;
to give the scanning routine the name lexscan, returning a float, and taking two floats as arguments. Note that if you give arguments to the scanning routine using a K&R-style/non-prototyped function declaration, you must terminate the definition with a semi-colon (`;').
Yes, right, just what I was missing! How would I live without being able to use non-standard C syntax that died in the seventies? Yet, the documentation blatantly lies about what happens if you declare YY_DECL
: in reality it gets ignored, unless you manage to spoof a different header to the compiler before any of the code generated by Flex would have been compiled.
I'm at the point now where I'd just write a sed
call to patch the output of Flex. Please tell me it is actually possible to fix it without this kind of "instrumentation".
YY_DECL
is not the ideal way of configuring theyylex
prototype, not least because once you have parameters toyylex
(as you do with reentrant lexers and parsers) then you need to get their names right, and the correct names aren't documented. But it would be useful to know why you want to change the prototype. To add extra state, it's usually easier to use yyextra. If you just want to change the name, then#define yylex my_name
is crude but effective. – riciyyextra
- didn't know about this one. Will report back today. And yes, my goal is to add an extra parameter since the parser is reentrant, I need to pass the state. – wvxvwyyextra
for that, although it is sometimes convenient to allocate the parse state at the top of yylex and delete it after sendimg the END token. – rici