It’s been many years [around 40] since I last wrangled with (yacc) .
I had a need for a relatively simple parser. I started to code as a recursive decent , but it turned out it was a little more complex than I at first thought. So I pulled out flex(1) and bison(1) . It was relatively quick to knock up a working grammar , but the syntax error messages were awful … When I last had to do this I overrode input() [ pretty sure it was call yyinput() but C++ had yet to see the light of day …I was working on the ANSI C compiler at the time 🙂 ] .so I could track the location precisely. Anyhow after reading many suggestions and guides of various ages and provenance , I got pointed at: bison/examples/c/bistromathic in the bison source tree , to quote
This example demonstrates best practices when using Bison
Right , so the way to go (and recent) . However examining it I noted (as it said) it uses a hand written scanner. Now I really wanted to use flex and bison together. So I took to extracting “scanner ” (lexer) from the parse.y file…I got most of the way there when I realised, the signature of the hand written lexer (scanner) was:
yytoken_kind_t yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc, const user_context *uctx)
i.e. 4 arguments, whereas the one generated by flex was:
extern int yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param );
2 arguments. (the middle 2 from the 1st version)
Now, I know I can just define YY_DECL to anything I like, but there is little point as the yylex generated by flex(1) only uses these 2 arguments . Now the hand written lexer coded in the bistromathic example need not have been called yylex() they could have just called it get_token(arg1,arg2,arg3,arg4) , but they did not, they called it yylex() so I assume they intended it to work with flex(1)/lex(1).
So are there some “magic runes” I can put the lexer.l file to persuade flex(1) to generate the 4 args style.
AFYI: I currently have:
%option noyywrap
%option bison-bridge bison-locations
It’s a little frustrating as those extra args look like the key to getting better location information in the error messages.