问题
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".
回答1:
If you want to change the prototype to add a parameter containing extra state, it's usually easier to use Flex's "extra data" feature, yyextra
. That avoids the irritations of YY_DECL
.
On the other hand, if you want to change the name of the generated lexer (because, for example, you want to export a wrapper called yylex
), then a crude but effective technique is to put
#define yylex my_name
In the prologue and
#undef yylex
in the epilogue. (Obviously these shouldn't be placed in header files.)
I agree that the YY_DECL
macro is far from an ideal way of configuring the yylex
prototype. My complaint has always been that once you have parameters to yylex
(as you do with reentrant lexers) then you need to get their names right, and the correct names aren't documented, and therefore are subject to change, making for a future incompatibility in waiting.
来源:https://stackoverflow.com/questions/49221106/remove-default-yy-decl-from-flex-output