Normalmente no es aceptable que un programa termine ante un error de análisis. Por ejemplo, un compilador debería recuperarse lo suficiente como para que analice el resto del archivo de entrada y comprobar sus errores; una calculadora debería aceptar otra expresión.
En un analizador de comandos interactivo sencillo donde cada entrada es una línea, podría ser suficiente con permitir a yyparse devolver un 1 ante un error y hacer que la función invocadora ignore el resto de la línea de entrada cuando suceda (y entonces llamar a yyparse de nuevo). Pero esto es inadecuado para un compilador, porque olvida todo el contexto sintáctico desde el comienzo hasta donde se encontró el error. Un error de sintaxis profundo dentro de una función del fichero de entrada del compilador no debería provocar que el compilador trate la línea siguiente como el principio de un fichero fuente.
Puede definir cómo recuperarse de un error de sintaxis escribiendo reglas para reconocer el token especial error. Este es un símbolo terminal que siempre se define (no necesita declararlo) y reservado para tratamiento de errores. El analizador de Bison genera un token error siempre que ocurra un error de sintaxis; si ha facilitado una regla que reconozca este token en el contexto actual, el analizador puede continuar.
Por ejemplo:
stmnts: /* cadena vacía */
| stmnts '\n'
| stmnts exp '\n'
| stmnts error '\n'
La cuarta regla en este ejemplo dice que un error seguido de una nueva línea forma una adición válida a cualquier stmnts.
¿Qué sucede si aparece un error de sintaxis en medio de una exp? La regla de recuperación de errores, interpretada estrictamente, se aplica a la secuencia precisa de una stmnts, un error y una nueva línea. Si aparece un error en medio de una exp, probablemente existan tokens adicionales y subexpresiones por leer antes de la nueva línea. De manera que la regla no es aplicable de la forma habitual.
Pero Bison puede forzar la situación para que se ajuste a la regla, descartando parte del contexto semántico y parte de la entrada. Primero descarta estados y objetos de la pila hasta que regrese a un estado en el que el token error sea aceptable. (Esto quiere decir que las subexpresiones ya analizadas son descartadas, retrocediendo hasta el último stmnts completo.) En este punto el token error puede desplazarse. Entonces, si el antiguo token de preanálisis no es aceptable para ser desplazado, el analizador lee tokens y los descarta hasta que encuentre un token que sea aceptable. En este ejemplo, Bison lee y descarta entrada hasta la siguiente línea de manera que la cuarta regla puede aplicarse.
La elección de reglas de error en la gramática es una elección de estrategias para la recuperación de errores. Una estrategia simple y útil es sencillamente saltarse el resto de la línea de entrada actual o de la sentencia actual si se detecta un error:
stmnt: error ';' /* ante un error, saltar hasta que se lea ';' */
También es útil recuperar el delimitador de cierre que empareja con un un delimitador de apertura que ya ha sido analizado. De otra manera el delimitador de cierre probablemente aparecerá como sin emparejar, y generará otro, espúreo mensaje de error:
primary: '(' expr ')'
| '(' error ')'
...
;
Las estrategias de recuperación de errores son por fuerza adivinanzas. Cuando estas adivinan mal, un error de sintaxis a menudo provoca otro. En el ejemplo anterior, la regla de recuperación de errores sospecha que el error es debido a una mala entrada en un stmnt. Suponga que en su lugar se inserta un punto y coma accidental en medio de un stmt válido. Después de recuperarse del primer error con la regla de recuperación de errores, se encontrará otro error de sintaxis directamente, ya que el texto que sigue al punto y coma accidental también es una stmnt inválida.
Para prevenir una cascada de mensajes de error, el analizador no mostrará mensajes de error para otro error de sintaxis que ocurra poco después del primero; solamente después de que se hayan desplazado con éxito tres tokens de entrada consecutivos se reanudarán los mensajes de error.
Note que las reglas que aceptan el token error podrían tener acciones, al igual que cualquiera de las otras reglas pueden tenerlas.
Puede hacer que los mensajes de error se reanuden inmediatamente usando la macro yyerrok en una acción. Si lo hace en la acción de la regla de error, no se suprimirá ningún mensaje de error. Esta macro no requiere ningún argumento; `yyerrok;' es una sentencia válida de C.
El token de preanálisis anterior se reanaliza inmediatamente después de un error. Si este no es aceptable, entonces la macro yyclearin podría utilizarse para limpiar ese token. Escriba la sentencia `yyclearin;' en la acción de la regla de error.
Por ejemplo, suponga que ante un error de análisis, se llama a una rutina de manejo de errores que avanza el flujo de entrada en algún punto donde el análisis prodría comenzar de nuevo. El próximo símbolo devuelto por el analizador léxico será probablemente correcto. El token de preanálisis anterior convendría que se descartara con `yyclearin;'.
La macro YYRECOVERING representa una expresión que tiene el valor 1 cuando el analizador se está recuperando de un error de sintaxis, y 0 durante el resto del tiempo. Un valor de 1 indica que actualmente los mensajes de error se están suprimiendo para nuevos errores de sintaxis.