I'm trying to use flex and bison to create a filter, because I want get certain grammar elements from a complex language. My plan is to use flex + bison to recognise the grammar, and dump out the location of elements of interest. (Then use a script to grab text according the locations dumped.)
I found flex can support a bison feature called bison-locations, but how it works in exactly. I tried the example in flex document, it seems the yylloc is not set automatically by flex, I always get (1,0)-(1,0)
. Could flex calculate each token's location automatically? If not, what interface function is defined for me to implement? Is there any example?
Any better solution regarding to tools?
Best Regards, Kevin
Edit:
Now the interface for yylex turn to:
int yylex(YYSTYPE * yylval_param,YYLTYPE * yylloc_param );
bison manual does not specify how lexer should implement to correctly set yylloc_param. For me it is hard to manually trace column number of each token.
The yylex declaration probably changed because you used a reentrant or pure-parser. Seems like many documents around the web suggest it's required if you want bison locations to work but it's not required.
I needed line numbers too and found the Bison documentation confusing in that regard. The simple solution (using the global var yylloc): In your Bison file just add the %locations directive:
%{
...
%}
%locations
...
%%
...
in your lexer:
%{
...
#include "yourprser.tab.h" /* This is where it gets the definition for yylloc from */
#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno;
%}
%option yylineno
...
%%
...
The YY_USER_ACTION macro is "called" before each of your token actions and updates yylloc. Now you can use the @N/@$ rules like this:
statement : error ';' { fprintf(stderr, "Line %d: Bad statement.\n", @1.first_line); }
, or use the yylloc global var:
void yyerror(char *s)
{
fprintf(stderr, "ERROR line %d: %s\n", yylloc.first_line, s);
}