Si una gramática de Bison compila adecuadamente pero no hace lo que quiere cuando se ejecuta, la propiedad de traza del analizador
yydebug puede ayudarle para darse cuenta del por qué.
Para activar la compilación de las facilidades de traza, debe definir la macro
YYDEBUG cuando compile el analizador. Podría utilizar `-DYYDEBUG=1' como una opción del compilador o podría poner `#define YYDEBUG 1' en la sección de declaraciones de C del archivo de la gramática (see section La Sección de Declaraciones en C). De forma alternativa, utilice la opción `-t' cuando ejecute Bison (see section Invocando a Bison). Siempre definiremos
YYDEBUG de manera que la depuración siempre es posible.
La facilidad de traza utiliza
stderr, de manera que debe añadir
#include <stdio.h> en la sección de declaraciones de C a menos que ya esté ahí.
Una vez que haya compilado el programa con las facilidades de traza, la manera de solicitar una traza es almacenar un valor distinto de cero en la variable
yydebug. Puede hacer esto poniendo código C que lo haga (en
main, tal vez), o puede alterar el valor con un depurador de C.
Cada paso tomado por el analizador cuando
yydebug no es cero produce una línea o dos de información de traza, escrita sobre
stderr. Los mensajes de traza le cuentan estas cosas:
- Cada vez que el analizador llama a yylex, qué tipo de token ha sido leido.
- Cada vez que un token se reduce, la profundidad y contenido completo de la pila de estados. (see section Estados del Analizador).
- Cada vez que se reduce una regla, qué regla es, y el contenido posterior completo de la pila de estados
Para hacerse una idea de esta información, ayuda el hacer referencia al listado del archivo producido por la opción `-v' de Bison (see section Invocando a Bison). Este archivo muestra el significado de cada estado en términos de posición en varias reglas, y también qué hará cada estado con cada token de entrada posible. A medida que lea los mensajes de traza sucesivos, puede ver que el analizador está fucionando de acuerdo a su especificación en el achivo del listado. Finalmente llegará al lugar donde sucede algo indeseable, y verá qué parte de la gramática es la culpable.
El archivo del analizador es un programa en C y puede utilizar depuradores de C con éste, pero no es fácil interpretar lo que está haciendo. La función del analizador es un intérprete de una máquina de estado finito, y aparte de las acciones éste ejecuta el mismo código una y otra vez. Solamente los valores de las variables muestran sobre qué lugar de la gramática se está trabajando.
La información de depuración normalmente da el tipo de token de cada token leído, pero no su valor semántico. Puede opcionalmente definir una macro llamada
YYPRINT para facilitar una manera de imprimir el valor. Si define
YYPRINT, esta debería tomar tres argumentos. El analizador pasará un flujo de entrada/salida estandar, el valor numérico del tipo de token, y el valor del token (de
yylval).
Aquí hay un ejemplo de
YYPRINT apropiado para la calculadora multifunción (see section Declaraciones para
mfcalc):
#define YYPRINT(file, type, value) yyprint (file, type, value)
static void
yyprint (file, type, value)
FILE *file;
int type;
YYSTYPE value;
{
if (type
VAR)
fprintf (file, " %s", value.tptr->name);
else if (type
NUM)
fprintf (file, " %d", value.val);
}