Location are created by lexer and "reduced" by the parser, so you have
to create them using the lexer:
#define YY_USER_ACTION {yylloc.first_line = yylineno;
yylloc.first_column = colnum; colnum=colnum+yyleng;
yylloc.last_column=colnum; yylloc.last_line = yylineno;}
this macro is executed at each token recognized by lex. Insert it in
bug.l inside %{}%; you have to define and manage colnum, yylineno is
automatically defined by flex.
You can access to location using @ from parser actions, or using yylloc
from flex.
You can also redefine, if you need, YYLTYPE (user custom locations, for
example to add a field to the struct to track also file location),
YYLLOC_DEFAULT (to merge locations) and YY_LOCATION_PRINT (to print
locations) without any trouble.
You have to redefine those macro BEFORE to include y.tab.h otherwise
the compiler will complain.
Luca
Kynn Jones ha scritto:
Hi. I'm working with Bison (and Flex) for the first time, and it's rough going.
I can't get Bison locations to work. The following toy parser
illustrates the problem.
Here's the file for Flex, bug.l:
-------------------------------------------------------------------------------
%{
#include "bug.tab.h"
%}
%option noyywrap nounput outfile="bug.yy.c" header-file="bug.yy.h"
%%
/* skip over whitespace */
[ \t\r\n]+
/* bomb anywhere else */
<*>. { return TINVALID; }
%%
-------------------------------------------------------------------------------
Here's the file for Bison, bug.y:
-------------------------------------------------------------------------------
%{
#include "bug.tab.h"
#include "bug.yy.h"
void yyerror ( char const *s ) {}
%}
%defines
%token TINVALID
%%
bug: error {
fprintf( stderr,
"@$: %d:%d-%d:%d\n",
@$.first_line,
@$.first_column,
@$.last_line,
@$.last_column );
return -1;
}
;
%%
-------------------------------------------------------------------------------
Here's the file parsebug.c:
-------------------------------------------------------------------------------
#include <stdio.h>
#include "bug.tab.h"
#include "bug.yy.h"
extern int yyparse();
int main (int argc, char **argv) {
yyout = fopen( "/dev/null", "w" );
yyin = argc > 1 ? fopen( argv[ 1 ], "r" ) : stdin;
return yyparse();
}
-------------------------------------------------------------------------------
Here's what I run:
% bison bug.y
% flex bug.l
% gcc -Wall --pedantic bug.tab.c bug.yy.c parsebug.c -o bug
% ( echo "\n\nfoo\n\n" | bug ) || echo "exited with error"
@$: 1:1-1:1
exited with error
So the parser fails, as expected, but no matter what the input is, the
first line of the output is always "@$: 1:1-1:1\n". This makes no
sense to me. If the "location" is going to be of any use, I'd expect
that it would reflect the position in the input where the parser
and/or scanner first got stuck. I.e. I expect that, with the input
above, at least one of the fields in @$ would be greater than 1.
Am I misunderstanding the meaning of Bisons "locations"? If not, what
am I doing wrong?
BTW, what's the standard way of implementing the handling of a
"scanner error" condition (i.e. to cover cases when the scanner finds
something that it does not expect).
Thanks!
kynn
_______________________________________________
help-bison@gnu.org http://lists.gnu.org/mailman/listinfo/help-bison
_______________________________________________
help-bison@gnu.org http://lists.gnu.org/mailman/listinfo/help-bison