JavaCUP - Métodos para la personalización

Personalización del Parser

Existe una serie de métodos que permiten personalizar el parser generado, y se presentan en la siguiente tabla:

método acción
public void user_init() El cuerpo de este método, contiene el código de la cláusula init with de la especificación.
public java_cup.runtime.Symbol scan() El cuerpo de este método es reemplazado por el código de la cláusula scan with de la especificación. Este método encapsula el scanner y es invocada cada vez que el parser requiere un nuevo token.
public java_cup.runtime.Scanner
getScanner()
Retorna el scanner asociado al parser.
public void setScanner(java_cup.runtime.Scanner s) Asocia el scanner s al parser.
public void report_error(String message, Object info) Este método debe ser invocado siempre que se edite un mensaje de error. La implementación por defecto de este método consta de dos parámetros, donde el primero provee el texto del mensaje que se imprime en System.err, mientras que el segundo parámetro es ignorado. Es muy típico la sustitución de este método para proveer un mecanismo de reporte de errores más sofisticado.
public void report_fatal_error
(String message, Object info)
Este método debería invocarse si ocurre un error no recuperable. Responde llamando a report_error() y aborta el parsing invocando el método done_parsing()y finalmente lanza una excepción.
public void syntax_error(Symbol cur_token) Este método es invocado en cuanto se detecta un error de sintaxis, pero antes de intentar la recuperación. En la implementación invoca: report_error("Syntax error", null);.
public void unrecovered_syntax_error(Symbol cur_token) Este método es invocado por el parser si es incapaz de recuperarse de un error de sintaxis. En la implementación invoca:report_fatal_error("Couldn't repair and continue parse", null);.
protected int error_sync_size() Este método es invocado por el parser para determinar cuántos tokens deben parsearse exitosamente para considerar que la recuperación de un error fue exitosa. La implementación por defecto retorna 3. No son recomendables valores menores. Para más detalles ver la sección de control de errores

El parsing es llevado a cabo por el método public Symbol parse(). Este método comienza estableciendo referencias a cada una de las tablas de parsing, e inicializando un objeto CUP$action object (por medio de la invocación de protected void init_actions()). Luego invoca user_init(), y obtiene el primer token lookahead mediante una llamada a scan(). Finalmente, comienza el parsing, y continúa hasta que se llama done_parsing() automáticamente, por ejemplo, cuando el parser acepta. Como salida, retorna un Symbol con la variable value conteniendo el resultado de la producción inicial, o null, si no existe ningún valor.

En tiempo de ejecución, además del parsing normal, el sistema provee una versión de debuggin del parser, que opera exactamente de la misma manera en la que lo hace el parser normal, pero impreme mensages de debbug, mediante la invocación de public void debug_message(String mess) cuya implementación imprime un mensaje en System.err.

Basándose en estas rutinas, la invocación de un parser CUP, normalmente consta del siguiente código:

      /* creación de un objeto parser */
      parser parser_obj = new parser();

      /* apertura de archivos de entrada, etc.  */
      Symbol parse_tree = null;

      try {
        if (do_debug_parse)
          parse_tree = parser_obj.debug_parse();
        else
          parse_tree = parser_obj.parse();
      } catch (Exception e) {
        /* se realiza limpieza - - posiblemente se vuelve a lanzar e */
      } finally {
        /* cierre */
      }