html2
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A.1 Makefiles and Flex | ||
A.2 C Scanners with Bison Parsers | ||
A.3 M4 Dependency |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In this appendix, we provide tips for writing Makefiles to build your scanners.
In a traditional build environment, we say that the `.c' files are the
sources, and the `.o' files are the intermediate files. When using
flex
, however, the `.l' files are the sources, and the generated
`.c' files (along with the `.o' files) are the intermediate files.
This requires you to carefully plan your Makefile.
Modern make
programs understand that `foo.l' is intended to
generate `lex.yy.c' or `foo.c', and will behave
accordingly(4). The
following Makefile does not explicitly instruct make
how to build
`foo.c' from `foo.l'. Instead, it relies on the implicit rules of the
make
program to build the intermediate file, `scan.c':
# Basic Makefile -- relies on implicit rules # Creates "myprogram" from "scan.l" and "myprogram.c" # LEX=flex myprogram: scan.o myprogram.o scan.o: scan.l |
For simple cases, the above may be sufficient. For other cases,
you may have to explicitly instruct make
how to build your scanner.
The following is an example of a Makefile containing explicit rules:
# Basic Makefile -- provides explicit rules # Creates "myprogram" from "scan.l" and "myprogram.c" # LEX=flex myprogram: scan.o myprogram.o $(CC) -o $@ $(LDFLAGS) $^ myprogram.o: myprogram.c $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ scan.o: scan.c $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ scan.c: scan.l $(LEX) $(LFLAGS) -o $@ $^ clean: $(RM) *.o scan.c |
Notice in the above example that `scan.c' is in the clean
target.
This is because we consider the file `scan.c' to be an intermediate file.
Finally, we provide a realistic example of a flex
scanner used with a
bison
parser(5).
There is a tricky problem we have to deal with. Since a flex
scanner
will typically include a header file (e.g., `y.tab.h') generated by the
parser, we need to be sure that the header file is generated BEFORE the scanner
is compiled. We handle this case in the following example:
# Makefile example -- scanner and parser. # Creates "myprogram" from "scan.l", "parse.y", and "myprogram.c" # LEX = flex YACC = bison -y YFLAGS = -d objects = scan.o parse.o myprogram.o myprogram: $(objects) scan.o: scan.l parse.c parse.o: parse.y myprogram.o: myprogram.c |
In the above example, notice the line,
scan.o: scan.l parse.c |
, which lists the file `parse.c' (the generated parser) as a dependency of
`scan.o'. We want to ensure that the parser is created before the scanner
is compiled, and the above line seems to do the trick. Feel free to experiment
with your specific implementation of make
.
For more details on writing Makefiles, see (make)Top section `Top' in The GNU Make Manual.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section describes the flex
features useful when integrating
flex
with GNU bison
(6).
Skip this section if you are not using
bison
with your scanner. Here we discuss only the flex
half of the flex
and bison
pair. We do not discuss
bison
in any detail. For more information about generating
bison
parsers, see (bison)Top section `Top' in the GNU Bison Manual.
A compatible bison
scanner is generated by declaring `%option
bison-bridge' or by supplying `--bison-bridge' when invoking flex
from the command line. This instructs flex
that the macro
yylval
may be used. The data type for
yylval
, YYSTYPE
,
is typically defined in a header file, included in section 1 of the
flex
input file. For a list of functions and macros
available, See bison-functions.
The declaration of yylex becomes,
int yylex ( YYSTYPE * lvalp, yyscan_t scanner ); |
If %option bison-locations
is specified, then the declaration
becomes,
int yylex ( YYSTYPE * lvalp, YYLTYPE * llocp, yyscan_t scanner ); |
Note that the macros yylval
and yylloc
evaluate to pointers.
Support for yylloc
is optional in bison
, so it is optional in
flex
as well. The following is an example of a flex
scanner that
is compatible with bison
.
/* Scanner for "C" assignment statements... sort of. */ %{ #include "y.tab.h" /* Generated by bison. */ %} %option bison-bridge bison-locations % [[:digit:]]+ { yylval->num = atoi(yytext); return NUMBER;} [[:alnum:]]+ { yylval->str = strdup(yytext); return STRING;} "="|";" { return yytext[0];} . {} % |
As you can see, there really is no magic here. We just use
yylval
as we would any other variable. The data type of
yylval
is generated by bison
, and included in the file
`y.tab.h'. Here is the corresponding bison
parser:
/* Parser to convert "C" assignments to lisp. */ %{ /* Pass the argument to yyparse through to yylex. */ #define YYPARSE_PARAM scanner #define YYLEX_PARAM scanner %} %locations %pure_parser %union { int num; char* str; } %token <str> STRING %token <num> NUMBER %% assignment: STRING '=' NUMBER ';' { printf( "(setf %s %d)", $1, $3 ); } ; |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The macro processor m4
(7) must be installed wherever flex is installed.
flex
invokes `m4', found by searching the directories in the
PATH
environment variable. Any code you place in section 1 or in the
actions will be sent through m4. Please follow these rules to protect your
code from unwanted m4
processing.
m4
macro names.
x[y[z]]
.
m4
is only required at the time you run flex
. The generated
scanner is ordinary C or C++, and does not require m4
.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by root on May, 8 2006 using texi2html 1.76.