Next: Enabling Debug Traces for mfcalc
, Up: Tracing Your Parser [Contents][Index]
There are several means to enable compilation of trace facilities, in decreasing order of preference:
Add the ‘%define parse.trace’ directive (see %define Summary), or pass the -Dparse.trace option (see Tuning the Parser). This is a Bison extension. Unless POSIX and Yacc portability matter to you, this is the preferred solution.
Use the -t option when you run Bison (see Invoking Bison). With
‘%define api.prefix {c}’, it defines CDEBUG
to 1, otherwise it
defines YYDEBUG
to 1.
Add the %debug
directive (see Bison Declaration Summary). This Bison
extension is maintained for backward compatibility; use %define
parse.trace
instead.
YYDEBUG
(C/C++ only) ¶Define the macro YYDEBUG
to a nonzero value when you compile the
parser. This is compliant with POSIX Yacc. You could use
-DYYDEBUG=1 as a compiler option or you could put ‘#define
YYDEBUG 1’ in the prologue of the grammar file (see The prologue).
If the %define
variable api.prefix
is used (see Multiple Parsers in the Same Program), for instance ‘%define
api.prefix {c}’, then if CDEBUG
is defined, its value controls the
tracing feature (enabled if and only if nonzero); otherwise tracing is
enabled if and only if YYDEBUG
is nonzero.
In C++, where POSIX compliance makes no sense, avoid this option, and prefer
‘%define parse.trace’. If you #define
the YYDEBUG
macro
at the wrong place (e.g., in ‘%code top’ instead of ‘%code
require’), the parser class will have two different definitions, thus
leading to ODR violations and happy debugging times.
We suggest that you always enable the trace option so that debugging is always possible.
In C the trace facility outputs messages with macro calls of the form
YYFPRINTF (stderr, format, args)
where format and
args are the usual printf
format and variadic arguments. If
you define YYDEBUG
to a nonzero value but do not define
YYFPRINTF
, <stdio.h>
is automatically included and
YYFPRINTF
is defined to fprintf
.
Once you have compiled the program with trace facilities, the way to request
a trace is to store a nonzero value in the variable yydebug
. You can
do this by making the C code do it (in main
, perhaps), or you can
alter the value with a C debugger.
Each step taken by the parser when yydebug
is nonzero produces a line
or two of trace information, written on stderr
. The trace messages
tell you these things:
yylex
, what kind of token was read.
To make sense of this information, it helps to refer to the automaton description file (see Understanding Your Parser). This file shows the meaning of each state in terms of positions in various rules, and also what each state will do with each possible input token. As you read the successive trace messages, you can see that the parser is functioning according to its specification in the listing file. Eventually you will arrive at the place where something undesirable happens, and you will see which parts of the grammar are to blame.
The parser implementation file is a C/C++/D/Java program and you can use debuggers on it, but it’s not easy to interpret what it is doing. The parser function is a finite-state machine interpreter, and aside from the actions it executes the same code over and over. Only the values of variables show where in the grammar it is working.
Next: Enabling Debug Traces for mfcalc
, Up: Tracing Your Parser [Contents][Index]