@settitle The Flex Manual
@c %**end of header
@include version.texi
+@c Define new index types for "Examples" and "macro hooks".
@defindex ex
+@defindex hk
@c This file is part of flex.
@cindex terminating with yyterminate()
@cindex exiting with yyterminate()
@cindex halting with yyterminate()
+@findex yyterminate
@code{yyterminate()}
can be used in lieu of a return statement in an action. It terminates
@node Generated Scanner
@chapter The Generated Scanner
+@cindex yylex(), in generated scanner
The output of @code{flex} is the file @file{lex.yy.c}, which contains
the scanning routine @code{yylex()}, a number of tables used by it for
matching tokens, and a number of auxiliary routines and macros. By
@end verbatim
@end example
+@cindex yylex(), overriding
(If your environment supports function prototypes, then it will
be
@code{int yylex( void )}.) This definition may be changed by defining
the scanning routine using a K&R-style/non-prototyped function
declaration, you must terminate the definition with a semi-colon (;).
+@cindex stdin, default for yyin
Whenever @code{yylex()} is called, it scans tokens from the global input
file @file{yyin} (which defaults to stdin). It continues until it
either reaches an end-of-file (at which point it returns the value 0) or
one of its actions executes a @code{return} statement.
+@cindex EOF and yyrestart()
If the scanner reaches an end-of-file, subsequent calls are undefined
unless either @file{yyin} is pointed at a new input file (in which case
scanning continues from that file), or @code{yyrestart()} is called.
@code{yyrestart()} does @emph{not} reset the start condition to
@code{INITIAL} (@pxref{Start Conditions}).
+@cindex returning from within an action
If
@code{yylex()}
stops scanning due to executing a
systems) to indicate @samp{EOF}. The default @code{YY_INPUT} reads from
the global file-pointer @file{yyin}.
+@cindex YY_INPUT, overriding
Here is a sample definition of @code{YY_INPUT} (in the definitions
section of the input file):
This definition will change the input processing to occur
one character at a time.
+@cindex yywrap(), explanation
When the scanner receives an end-of-file indication from YY_INPUT, it
then checks the @code{yywrap()} function. If @code{yywrap()} returns
false (zero), then it is assumed that the function has gone ahead and
though @code{yywrap()} returned 1), or you must link with @samp{-lfl} to
obtain the default version of the routine, which always returns 1.
-Three routines are available for scanning from in-memory buffers rather
-than files:
-@code{yy_scan_string()}, @code{yy_scan_bytes()},
-and
-@code{yy_scan_buffer()}.
+For scanning from in-memory buffers (e.g., scanning strings), see
+@ref{Scanning Strings}
@xref{Multiple}.
The scanner writes its
@node Start Conditions
@chapter Start Conditions
+@cindex start conditions, explanation
@code{flex}
provides a mechanism for conditionally activating rules. Any rule
whose pattern is prefixed with @samp{<sc>} will only be active when
will be active only when the current start condition is either
@code{INITIAL}, @code{STRING}, or @code{QUOTE}.
+@cindex start conditions, inclusive v.s. exclusive
Start conditions are declared in the definitions (first) section of the
input using unindented lines beginning with either @samp{%s} or
@samp{%x} followed by a list of names. The former declares
it's active in both, because in the first example the @code{example}
start condition is an inclusive @code{(%s)} start condition.
+@cindex start conditions, special wildcard condition
Also note that the special start-condition specifier
@code{<*>}
matches every start condition. Thus, the above example could also
@end verbatim
@end example
+@cindex BEGIN(), explanation
+@findex BEGIN
+@vindex INITIAL
@code{BEGIN(0)} returns to the original state where only the rules with
no start conditions are active. This state can also be referred to as
the start-condition @code{INITIAL}, so @code{BEGIN(INITIAL)} is
@end verbatim
@end example
+@cindex comments, example of scanning C comments
Here is a scanner which recognizes (and discards) C comments while
maintaining a count of the current input line.
can be stored as such. Thus, the above could be extended in the
following fashion:
+@cindex start conditions, integer values
@exindex using integer values of start condition names
@example
@verbatim
@end verbatim
@end example
+@cindex YY_START, example
Furthermore, you can access the current start condition using the
integer-valued @code{YY_START} macro. For example, the above
assignments to @code{comment_caller} could instead be written
@end verbatim
@end example
+@vindex YY_START
Flex provides @code{YYSTATE} as an alias for @code{YY_START} (since that
is what's used by AT&T @code{lex}).
@end verbatim
@end example
+@cindex start condition, applying to multiple patterns
Often, such as in some of the examples above, you wind up writing a
whole bunch of rules all preceded by the same start condition(s). Flex
makes this a little easier and cleaner by introducing a notion of start
Start condition scopes may be nested.
+@cindex stacks, routines for manipulating
+@cindex start conditions, use of a stack
+
The following routines are available for manipulating stacks of start conditions:
@deftypefun void yy_push_state ( int @code{new_state} )
returns the top of the stack without altering the stack's contents.
@end deftypefun
+@cindex memory, for start condition stacks
The start condition stack grows dynamically and so has no built-in size
limitation. If memory is exhausted, program execution aborts.
@node Multiple
@chapter Multiple Input Buffers
+@cindex multiple input streams
Some scanners (such as those which support ``include'' files) require
reading from several input streams. As @code{flex} scanners do a large
amount of buffering, one cannot control where the next input will be
for creating and switching between multiple input buffers. An input
buffer is created by using:
+@cindex memory, allocating input buffers
@deftypefun YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size )
@end deftypefun
associated with the given file and large enough to hold @code{size}
characters (when in doubt, use @code{YY_BUF_SIZE} for the size). It
returns a @code{YY_BUFFER_STATE} handle, which may then be passed to
-other routines (see below). The @code{YY_BUFFER_STATE} type is a
+other routines (see below).
+@tindex YY_BUFFER_STATE
+The @code{YY_BUFFER_STATE} type is a
pointer to an opaque @code{struct yy_buffer_state} structure, so you may
safely initialize @code{YY_BUFFER_STATE} variables to @code{((YY_BUFFER_STATE)
0)} if you wish, and also refer to the opaque structure in order to
that switching input sources via either @code{yy_switch_to_buffer()} or
@code{yywrap()} does @emph{not} change the start condition.
+@cindex memory, deleting input buffers
@deftypefun void yy_delete_buffer ( YY_BUFFER_STATE buffer )
@end deftypefun
can be nil, in which case the routine does nothing.) You can also clear
the current contents of a buffer using:
+@cindex clearing an input buffer
+@cindex flushing an input buffer
@deftypefun void yy_flush_buffer ( YY_BUFFER_STATE buffer )
@end deftypefun
provided for compatibility with the C++ use of @code{new} and
@code{delete} for creating and destroying dynamic objects.
+@cindex YY_CURRENT_BUFFER, and multiple buffers
Finally, the macro @code{YY_CURRENT_BUFFER} macro returns a
@code{YY_BUFFER_STATE} handle to the current buffer.
+@cindex EOF, example using multiple input buffers
Here is an example of using these features for writing a scanner
which expands include files (the
@code{<<EOF>>}
@end verbatim
@end example
+@anchor{Scanning Strings}
+@cindex strings, scanning strings instead of files
The following routines are available for setting up input buffers for
scanning in-memory strings instead of files. All of them create a new
input buffer for scanning the string, and return a corresponding
the contents of the buffer it is scanning.) You can avoid the copy by
using:
+@vindex YY_END_OF_BUFFER_CHAR
@deftypefun void yy_scan_buffer (char *base, yy_size_t size)
which scans in place the buffer starting at @code{base}, consisting of
@code{size} bytes, the last two bytes of which @emph{must} be
@node EOF
@chapter End-of-File Rules
+@cindex EOF, explanation
The special rule @code{<<EOF>>} indicates
actions which are to be taken when an end-of-file is
encountered and @code{yywrap()} returns non-zero (i.e., indicates
@itemize
@item
+@findex YY_NEW_FILE (now obsolete)
assigning @file{yyin} to a new input file (in previous versions of
@code{flex}, after doing the assignment you had to call the special
action @code{YY_NEW_FILE}. This is no longer necessary.)
@node Misc Macros
@chapter Miscellaneous Macros
+@hkindex YY_USER_ACTION
The macro @code{YY_USER_ACTION} can be defined to provide an action
which is always executed prior to the matched rule's action. For
example, it could be #define'd to call a routine to convert yytext to
@end verbatim
@end example
+@vindex YY_NUM_RULES
where @code{ctr} is an array to hold the counts for the different rules.
Note that the macro @code{YY_NUM_RULES} gives the total number of rules
(including the default rule), even if you use @samp{-s)}, so a correct
@end verbatim
@end example
+@hkindex YY_USER_INIT
The macro @code{YY_USER_INIT} may be defined to provide an action which
is always executed before the first scan (and before the scanner's
internal initializations are done). For example, it could be used to
call a routine to read in a data table or open a logging file.
+@findex yy_set_interactive
The macro @code{yy_set_interactive(is_interactive)} can be used to
control whether the current buffer is considered @dfn{interactive}. An
interactive buffer is processed more slowly, but must be used when the
@code{yy_set_interactive()} must be invoked prior to beginning to scan
the buffer that is (or is not) to be considered interactive.
+@cindex BOL, setting it
+@findex yy_set_bol
The macro @code{yy_set_bol(at_bol)} can be used to control whether the
current buffer's scanning context for the next token match is done as
though at the beginning of a line. A non-zero macro argument makes
rules anchored with @samp{^} active, while a zero argument makes
@samp{^} rules inactive.
+@cindex BOL, checking the BOL flag
+@findex YY_AT_BOL
The macro @code{YY_AT_BOL()} returns true if the next token scanned from
the current buffer will have @samp{^} rules active, false otherwise.
+@cindex actions, redefining YY_BREAK
+@hkindex YY_BREAK
In the generated scanner, the actions are all gathered in one large
switch statement and separated using @code{YY_BREAK}, which may be
redefined. By default, it is simply a @code{break}, to separate each
rule actions.
@table @code
+@vindex yytext
@item char *yytext
holds the text of the current token. It may be modified but not
lengthened (you cannot append characters to the end).
+@cindex yytext, default array size
+@cindex array, default size for yytext
+@vindex YYLMAX
If the special directive @code{%array} appears in the first section of
the scanner description, then @code{yytext} is instead declared
@code{char yytext[YYLMAX]}, where @code{YYLMAX} is a macro definition
a character pointer. The opposite of @code{%array} is @code{%pointer},
which is the default.
+@cindex C++ and %array
You cannot use @code{%array} when generating C++ scanner classes (the
@samp{-+} flag).
+@vindex yyleng
@item int yyleng
holds the length of the current token.
+@vindex yyin
@item FILE *yyin
is the file which by default @code{flex} reads from. It may be
redefined but doing so only makes sense before scanning begins or after
end-of-file has been seen, you can assign @file{yyin} at the new input
file and then call the scanner again to continue scanning.
+@findex yyrestart
@item void yyrestart( FILE *new_file )
may be called to point @file{yyin} at the new input file. The
switch-over to the new file is immediate (any previously buffered-up
as an argument thus throws away the current input buffer and continues
scanning the same input file.
+@vindex yyout
@item FILE *yyout
is the file to which @code{ECHO} actions are done. It can be reassigned
by the user.
+@vindex YY_CURRENT_BUFFER
@item YY_CURRENT_BUFFER
returns a @code{YY_BUFFER_STATE} handle to the current buffer.
+@vindex YY_START
@item YY_START
returns an integer value corresponding to the current start condition.
You can subsequently use this value with @code{BEGIN} to return to that
@node Yacc
@chapter Interfacing with Yacc
+@cindex yacc, interface
+
+@vindex yylval, with yacc
One of the main uses of @code{flex} is as a companion to the @code{yacc}
parser-generator. @code{yacc} parsers expect to call a routine named
@code{yylex()} to find the next input token. The routine is supposed to
@node Invoking Flex
@chapter Invoking Flex
+@cindex command-line options
+@cindex options, command-line
+@cindex arguments, command-line
+
@code{flex}
has the following options.
@node Performance
@chapter Performance Considerations
+@cindex performance, considerations
The main design goal of @code{flex} is that it generate high-performance
scanners. It has been optimized for dealing well with large sets of
rules. Aside from the effects on scanner speed of the table compression
@samp{-C} options outlined above, there are a number of options/actions
which degrade performance. These are, from most expensive to least:
+@cindex REJECT, performance costs
+@cindex yylineno, performance costs
+@cindex trailing context, performance costs
@example
@verbatim
REJECT
@code{REJECT} should be avoided at all costs when performance is
important. It is a particularly expensive option.
+@cindex patterns, tuning for performance
+@cindex performance, backing up
+@cindex backing up, example of eliminating
Getting rid of backing up is messy and often may be an enormous amount
of work for a complicated scanner. In principal, one begins by using
the @samp{-b} flag to generate a @file{lex.backup} file. For example,
on the input:
-@exindex backing up, getting rid of
+@exindex backing up, eliminating
@example
@verbatim
%%
@samp{-Cf} or @samp{-CF}, since there's no performance gain doing so
with compressed scanners.
+@cindex error rules, to eliminate backing up
The way to remove the backing up is to add ``error'' rules:
@exindex backing up, eliminating by adding error rules
at the beginning of this section) how complicated the rules are with
regard to operators such as @samp{*} and @samp{|}.
+@cindex keywords, for performance
+@cindex performance, using keywords
A final example in speeding up a scanner: suppose you want to scan
through a file containing identifiers and keywords, one per line
and with no other extraneous characters, and recognize all the
@node Cxx
@chapter Generating C++ Scanners
+@cindex C++
+@cindex member functions in C++
+@cindex methods
@code{flex} provides two different ways to generate scanners for use
with C++. The first way is to simply compile a scanner generated by
@code{flex} using a C++ compiler instead of a C compiler. You should
interface. It provides the following member functions:
@table @code
+@findex YYText (C++ only)
@item const char* YYText()
returns the text of the most recently matched token, the equivalent of
@code{yytext}.
+@findex YYLeng (C++ only)
@item int YYLeng()
returns the length of the most recently matched token, the equivalent of
@code{yyleng}.
+@findex lineno (C++ only)
@item int lineno() const
returns the current input line number (see @code{%option yylineno)}, or
@code{1} if @code{%option yylineno} was not used.
+@findex set_debug (C++ only)
@item void set_debug( int flag )
sets the debugging flag for the scanner, equivalent to assigning to
@code{yy_flex_debug} (@pxref{Invoking Flex}). Note that you must build
the scannerusing @code{%option debug} to include debugging information
in it.
+@findex debug (C++ only)
@item int debug() const
returns the current setting of the debugging flag.
@end table
@code{yyrestart()} (again, the first argument is a @code{istream*}
object pointer).
+@tindex yyFlexLexer (C++ only)
+@tindex FlexLexer (C++ only)
The second class defined in @file{FlexLexer.h} is @code{yyFlexLexer},
which is derived from @code{FlexLexer}. It defines the following
additional member functions:
@table @code
+@findex yyFlexLexer constructor (C++ only)
@item yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 )
constructs a @code{yyFlexLexer} object using the given streams for input
and output. If not specified, the streams default to @code{cin} and
@code{cout}, respectively.
+@findex yylex (C++ version)
@item virtual int yylex()
performs the same role is @code{yylex()} does for ordinary @code{flex}
scanners: it scans the input stream, consuming tokens, until a rule's
(and also generates a dummy @code{yyFlexLexer::yylex()} that calls
@code{yyFlexLexer::LexerError()} if called).
+@findex switch_streams (C++ only)
@item virtual void switch_streams(istream* new_in = 0, ostream* new_out = 0)
reassigns @code{yyin} to @code{new_in} (if non-nil) and @code{yyout} to
@code{new_out} (if non-nil), deleting the previous input buffer if
scanner:
@table @code
+@findex LexerInput (C++ only)
@item virtual int LexerInput( char* buf, int max_size )
reads up to @code{max_size} characters into @code{buf} and returns the
number of characters read. To indicate end-of-input, return 0
scanning an interactive input source, you can test for the presence of
this name via @code{#ifdef} statements.
+@findex LexerOutput (C++ only)
@item virtual void LexerOutput( const char* buf, int size )
writes out @code{size} characters from the buffer @code{buf}, which, while
@code{NUL}-terminated, may also contain internal @code{NUL}s if the
scanner's rules can match text with @code{NUL}s in them.
+@cindex error reporting, in C++
+@findex LexerError (C++ only)
@item virtual void LexerError( const char* msg )
reports a fatal error message. The default version of this function
writes the message to the stream @code{cerr} and exits.
@end verbatim
@end example
+@cindex C++, multiple different scanners
If you want to create multiple (different) lexer classes, you use the
@samp{-P} flag (or the @code{prefix=} option) to rename each
@code{yyFlexLexer} to some other @samp{xxFlexLexer}. You then can
include @file{FlexLexer.h>} in your other sources once per lexer class,
first renaming @code{yyFlexLexer} as follows:
+@cindex include files, with C++
+@cindex header files, with C++
@exindex C++ scanners, including multiple scanners
@example
@verbatim
@node Reentrant
@chapter Reentrant C Scanners
+@cindex reentrant, explanation
@code{flex} has the ability to generate a reentrant C scanner. This is
accomplished by specifying @code{%option reentrant} (@samp{-R}) or
@code{%option reentrant-bison} (@samp{-Rb}). The generated scanner is
@node Reentrant Overview
@section An Overview of the Reentrant API
+@cindex reentrant, API explanation
The API for reentrant scanners is different than for non-reentrant
scanners. Here is a quick overview of the API:
@item
All global variables are replaced by their macro equivalents.
+(We tell you this because it may be important to you during debugging.)
@item
@code{yylex_init} and @code{yylex_destroy} must be called before and
@section Reentrant Example
First, an example of a reentrant scanner:
-
+@cindex reentrant, example of
@example
@verbatim
/* This scanner prints "//" comments. */
@node Extra Reentrant Argument
@subsection The Extra Argument
+@cindex reentrant, calling functions
+@vindex yy_globals (reentrant only)
All functions take one additional argument: @code{yy_globals}.
Notice that the calls to @code{yy_push_state} and @code{yy_pop_state}
@node Global Replacement
@subsection Global Variables Replaced By Macros
+@cindex reentrant, accessing flex variables
All global variables are replaced by macro equivalents.
Note that in the above example, @code{yyout} and @code{yytext} are
@node Init and Destroy Functions
@subsection Init and Destroy Functions
+@cindex memory, considerations for reentrant scanners
+@cindex reentrant, initialization
+@findex yylex_init
+@findex yylex_destroy
+
@code{yylex_init} and @code{yylex_destroy} must be called before and
after @code{yylex}, respectively.
@node Accessor Methods
@subsection Accessing Variables with Reentrant Scanners
+@cindex reentrant, accessor functions
Accessor methods (get/set functions) provide access to common
@code{flex} variables.
@node Extra Data
@subsection Extra Data
+@cindex reentrant, extra data
+@vindex yyextra
User-specific data can be stored in @code{yyextra}.
In a reentrant scanner, it is unwise to use global variables to
@code{yyextra}
from within the scanner itself. They are defined as follows:
+@tindex YY_EXTRA_TYPE (reentrant only)
+@findex yyget_extra
+@findex yyset_extra
@example
@verbatim
#define YY_EXTRA_TYPE void*
- YY_EXTRA_TYPE yyget_extra ( yyscan_t scanner ) ;
- void yyset_extra ( YY_EXTRA_TYPE arbitrary_data , yyscan_t scanner) ;
+ YY_EXTRA_TYPE yyget_extra ( yyscan_t scanner );
+ void yyset_extra ( YY_EXTRA_TYPE arbitrary_data , yyscan_t scanner);
@end verbatim
@end example
@node About yyscan_t
@subsection About yyscan_t
+@tindex yyscan_t (reentrant only)
@code{yyscan_t} is defined as:
@example
@node Bison Pure
@section Reentrant C Scanners with Bison Pure Parsers
+@cindex bison, with reentrant
+@vindex yylval
+@vindex yylloc
+@tindex YYLTYPE
+@tindex YYSTYPE
+
This section describes the @code{flex} features useful when integrating
@code{flex} with @code{bison}. Skip this section if you are not using
@code{bison} with your scanner. Here we discuss only the @code{flex}
@code{yyset_lloc}, defined below, and the corresponding macros
@code{yylval} and @code{yylloc}, for use within actions.
-@example
-@verbatim
- YYSTYPE * yyget_lval ( yyscan_t scanner ) ;
- void yyset_lval ( YYSTYPE * lvalp, yyscan_t scanner );
+@deftypefun YYSTYPE* yyget_lval ( yyscan_t scanner )
+@end deftypefun
+@deftypefun YYLTYPE* yyget_lloc ( yyscan_t scanner )
+@end deftypefun
- YYLTYPE * yyget_lloc ( yyscan_t scanner ) ;
- void yyset_lloc ( YYLTYPE * llocp, yyscan_t scanner );
-@end verbatim
-@end example
+@deftypefun void yyset_lval ( YYSTYPE* lvalp, yyscan_t scanner )
+@end deftypefun
+@deftypefun void yyset_lloc ( YYLTYPE* llocp, yyscan_t scanner )
+@end deftypefun
Accordingly, the declaration of yylex becomes one of the following:
+@findex yylex (reentrant version)
@example
@verbatim
int yylex ( YYSTYPE * lvalp, yyscan_t scanner );
The following Functions are available in a reentrant scanner:
+@findex yyget_text
+@findex yyget_leng
+@findex yyget_in
+@findex yyget_out
+@findex yyget_lineno
+@findex yyset_in
+@findex yyset_out
+@findex yyset_lineno
+
@example
@verbatim
char *yyget_text ( yyscan_t scanner );
FILE *yyget_out ( yyscan_t scanner );
int yyget_lineno ( yyscan_t scanner );
YY_EXTRA_TYPE yyget_extra ( yyscan_t scanner );
+
void yyset_in ( FILE * in_str , yyscan_t scanner );
void yyset_out ( FILE * out_str , yyscan_t scanner );
void yyset_lineno ( int line_number , yyscan_t scanner );
@end verbatim
@end example
+@cindex yylineno, in a reentrant scanner
In a reentrant C scanner, support for yylineno is always present
(i.e., you may access yylineno), but the value is never modified by
@code{flex} unless @code{%option yylineno} is enabled. This is to allow
@node Lex and Posix
@chapter Incompatibilities with Lex and Posix
+@cindex POSIX and lex
+@cindex lex (traditional) and POSIX
+
@code{flex} is a rewrite of the AT&T Unix @emph{lex} tool (the two
implementations do not share any code, though), with some extensions and
incompatibilities, both of which are of concern to those who wish to
respectively).
@end itemize
+@cindex POSIX, non-POSIX features of flex
+
The following @code{flex} features are not included in @code{lex} or the
POSIX specification:
@node Diagnostics
@chapter Diagnostics
+@cindex error reporting, diagnostic messages
+@cindex warnings, diagnostic messages
+
The following is a list of @code{flex} diagnostic messages:
@itemize
@node Limitations
@chapter Limitations
+@cindex limitations of flex
+
Some trailing context patterns cannot be properly matched and generate
warning messages (@samp{dangerous trailing context}). These are
patterns where the ending of the first part of the rule matches the
@node Copyright
@chapter Copyright
+@cindex copyright of flex
+@cindex distributing flex
+
The flex manual is placed under the same licensing conditions as the
rest of flex:
@node Reporting Bugs
@chapter Reporting Bugs
+@cindex bugs, reporting
+
If you have problems with @code{flex} or think you have found a bug,
please send mail detailing your problem to
@email{help-flex@@gnu.org}. Patches are always welcome.
@menu
* Concept Index::
* Index of Functions and Macros::
-* Index of Examples::
* Index of Variables::
* Index of Data Types::
+* Index of Hooks::
+* Index of Examples::
@end menu
@node Concept Index
@cindex end of file -- see EOF
@cindex regular expressions -- see Patterns
@cindex macros, see preprocessor macros
+@cindex freeing memory -- see memory
+@cindex allocating memory see memory
+@cindex malloc -- see memory
+@cindex bison, see also yacc
@printindex cp
@node Index of Functions and Macros
@unnumberedsec Index of Functions and Macros
-@printindex fn
-@node Index of Examples
-@unnumberedsec Index of Examples
-@printindex ex
+This is an index of functions and preprocessor macros that look like functions.
+For macros that expand to variables or constants, see @ref{Index of Variables}.
+
+@printindex fn
@node Index of Variables
@unnumberedsec Index of Variables
+
+This is an index of variables, constants, and preprocessor macros
+that expand to variables or constants.
+
@printindex vr
@node Index of Data Types
@unnumberedsec Index of Data Types
@printindex tp
+@node Index of Hooks
+@unnumberedsec Index of Hooks
+
+This is an index of "hooks" that the user may define. These hooks typically correspond
+to specific locations in the generated scanner, and may be used to insert arbitrary code.
+
+@printindex hk
+
+@node Index of Examples
+@unnumberedsec Index of Examples
+@printindex ex
+
@bye