JavaCC

3 02 2011

JavaCC (Java Compiler Compiler) es un generador de analizadores sintácticos de código abierto para el lenguaje de programación Java. JavaCC es similar a Yacc en que genera un parser para una gramática presentada en notación BNF.

JavaCC genera analizadores descendentes (top-down), lo que lo limita a la clase de gramáticas LL(K).

El funcionamiento de la herramienta consiste en analizar un fichero de entrada, que contiene la descripción de una gramática, y generar un conjunto de ficheros de salida, escritos en Java, que contienen la especificación de un analizador léxico y de un analizador sintáctico para la gramática especificada.

Las características más importantes de esta herramienta son las siguientes:

  • Es la herramienta más utilizada en Java. Los propietarios estiman en cientos de miles el número de descargas de la herramienta y los foros de discusión congregan a miles de usuarios interesados en JavaCC.
  • Se basa en una análisis sintáctico descendente recursivo.
  • Por defecto JavaCC analiza gramáticas de tipo LL(1), pero permite fijar un Lookahead mayor (para analizar gramáticas LL(k)) e incluso utilizar un Lookahead adaptativo.
  • Las especificaciones léxica y sintáctica de la gramática a analizar se incluyen en un mismo fichero.
  • La especificación léxica se basa en expresiones regulares y la especificación sintáctica utiliza el formato EBNF.
  • Junto a la herramienta principal se incluyen dos utilidades: JJTree, para crear automáticamente un generador de árboles sintácticos, y JJDoc, para generar automáticamente la documentación de la gramática en formato HTML.
  • La distribución incluye numerosos ejemplos de gramáticas y existen repositorios en internet con la especificación de muchísimas gramáticas en el formato de JavaCC.
  • La gestión de errores léxicos y sintácticos está basada en excepciones y contiene información muy valiosa respecto al origen del error y su posición.
  • Existe un plugin para Eclipse que facilita la edición y ejecución de la herramienta dentro del desarrollo de cualquier aplicación en Java.

Características lexicográficas y sintácticas

Es la forma más frecuente de uso del generador; la especificación proporcionada define las característi­cas sintácticas y lexicográficas de un lenguaje y se genera un analizador léxico-sintáctico del lenguaje especificado.

Características lexicográficas

En la especificación proporcionada al generador sólo se definen características lexicográficas del lengua­je; con el código generado se puede obtener un analizador lexicográfico.

Características lexicográficas y sintácticas y comprobaciones semánticas también es posible completar una especificación léxico-sintáctica con la inclusión de código Java com­plementario para que el programa generado (que incorpora adecuadamente ese código auxiliar) pueda hacer un análisis completo (léxico, sintáctico y semántico) del lenguaje especificado.

Instalación

Dado que el código generado por JavaCC está escrito en Java, es necesario disponer de una versión del sis­tema Java (compilador de Java e intérprete de la Máquina Virtual Java). Son programas de libre distribu­ción y fáciles de conseguir.

El generador JavaCC también es un programa de libre distribución; se puede conseguir en:

(se tiene la versión  Java Compiler Compiler, version 5.0)

Se consigue un fichero empaquetado de nombre javacc-5.0.zip; tras desempaquetar (en un determi­nado directorio, que puede elegirse como convenga) dicho fichero, se tienen instalados, entre otros, los si­guientes ficheros (que son los que interesan para el sistema operativo windows):

···· \javacc-5.0\bin\javacc.bat

···· \javacc-5.0\bin\jjdoc.bat

···· \javacc-5.0\bin\jjtree.bat

los nombre de estos ficheros se corresponden con los nombres de los comandos para llamar a las herra­mientas instaladas

  1. javacc: generador de analizadores
  2. jjdoc:  productor de documentación
  3. jjtree: preprocesador de apoyo para tareas semánticas

Para que la llamada a estos comandos pueda realizarse desde cualquier directorio, ha de anotarse el camino (PATH) que lleve hasta ···· \javacc-5.0\bin. También ha de tenerse en cuenta si la instalación del sistema Java se tiene preparada para que el compilador (javac) y el intérprete (java) se puedan ejecutar desde cualquier directorio.

Para comprobar si la instalación del generador se ha realizado adecuadamente, se puede llamar desde la lí­nea de comandos al generador javacc, y aparecerá por pantalla una información sobre el uso de dicho comando; la primera línea de esa información es:

Java Compiler Compiler Version 5.0 (Parser Generator).

Estructura general:

JavaCC utiliza la extensión “.jj” para identificar los archivos de entrada que contienen la especificación de la gramática a analizar. La estructura de estos archivos se divide en cuatro partes.

  1. La primera permite seleccionar una serie de opciones, como el valor del Lookahead, si se van a generar métodos estáticos o no, si se va a distinguir entre mayúsculas y minúsculas, etcétera.
  2. La segunda parte permite definir el nombre del analizador e incluir el código Java que se va a añadir directamente a este analizador, como el nombre del paquete en el que se incluye, las claúsulas import, la cabecera de la definición de la clase, los constructores de la clase, las variables de instancia o los métodos que pueden ser utilizados en la definición de la semántica de la gramática.
  3. La tercera sección contiene la especificación léxica de la gramática.
  4. La última parte del archivo la ocupa la descripción de las reglas sintácticas de la gramática.

A continuación se muestra un ejemplo del contenido de un fichero de especificación gramatical:

/* opciones generales */

options {
IGNORE_CASE = true;
STATIC = false;

}

PARSER_BEGIN(MiGramatica) /* definición del nombre del analizador */

/* codigo Java utilizado en la descripción del analizador */

import java.io.*;

public class MiGramatica {

}

PARSER_END(MiGramatica)

/* especificación léxica de la gramática */

TOKEN: /* Identificadores */
{
< ID: ( <LETTER> )+ ( “_” | “$” | “#” | <DIGIT> | <LETTER> )* >
| < #LETTER: [“A”-“Z”, “a”-“z”] >
| < #DIGIT: [“0”-“9”] >
}

SKIP:
{
” “
| “\n”
| “\r”
| “\t”
}

/* especificación sintáctica de la gramática */

void CreateTable() :
{
Token token;
}
{
<CREATE> <TABLE>
token = <ID> { System.out.println(“Table: ” + token.image); }
“(” ColumnList() “)”
}

El nombre utilizado en las sentencias PARSER_BEGIN y PARSER_END (que en el ejemplo anterior sería MiGramatica) se utiliza como prefijo para generar tres archivos:

  • “MiGramatica.java”: desarrolla el analizador sintáctico
  • “MiGramaticaConstants.java”: almacena un conjunto de constantes relacionadas con las categorías léxicas.
  • “MiGramaticaTokenManager.java”.: archivo desarrolla el analizador léxico para la gramática.

Además de estos archivos, la herramienta genera otros cuatro archivos cuyo contenido es siempre el mismo:

  • “JavaCharStream.java” (que define un flujo de datos de entrada basado en caracteres ASCII).
  • “ParseException.java” (que define los errores sintácticos).
  • “Token.java” (que define una categoría léxica).
  • “TokenMgrError.java” (que define los errores léxicos).

Obtención de un analizador léxico-sintáctico

Pasos para la generación del analizador

  • Edición de la especificación (editor de texto plano)

vi | edit |∙ ∙ ∙  NombreFichero.jj

(el nombre del fichero puede tener cualquier extensión; suele usarse .jj)

  • Ejecución del generador

javacc NombreFichero.jj

  • Si el nombre elegido para la especificación es NombreDeLaEspecif (más adelante se indica la manera de dar un nombre a la especificación), como resultado de la generación se obtiene (además de otros ficheros auxiliares) el fichero

NombreDeLaEspecif.java

  • Compilación del analizador generado.

javac NombreDeLaEspecif.java

  • Como resultado de la compilación se obtiene (además de otras clases auxiliares) el fichero

NombreDeLaEspecif.class

Ejecución del analizador generado

Si el nombre del fichero donde se encuentra el texto fuente (escrito en el lenguaje para el que se ha genera­do el analizador) que se pretende analizar es  Programa.len

java NombreDeLaEspecif < Programa.len

Si se desea que los resultados del análisis, en vez de presentarse por pantalla, queden grabados en un fi­chero de nombre  Salida.dat

java NombreDeLaEspecif < Programa.len > Salida.dat

 

Ejemplo de presentación

  • Descripción del lenguaje

El lenguaje L está formado por las expresiones en las que pueden aparecer:

–  variables

–  constantes

–  operadores  +  y  *

Las variables son nombres formados por una única letra (minúscula o mayúscula); las constantes son nú­meros enteros de una o más cifras. El espacio y el tabulador pueden estar presentes, pero no tienen ningún significado; los finales de línea tampoco son significativos (una expresión puede codificarse ocupando una o más líneas).

La sintaxis de las expresiones se especifica mediante la siguiente gramática:

<Expresion> ::= <Termino> { + <Termino> }

<Termino> ::= <Factor> { * <Factor> }

<Factor> ::= variable

|  constante

|  ( <Expresion> )

• Especificación léxico-sintáctica codificada con la notación JavaCC

Una manera de escribir la especificación (para la que se ha elegido el nombre  ExprMin)  de forma que sea aceptada por el generador es:

options {   Ignore_Case = true;   }

PARSER_BEGIN (ExprMin)

public class ExprMin {

public static void main (String[] argum) throws ParseException {

ExprMin anLexSint = new ExprMin (System.in);

anLexSint.unaExpresion();

System.out.println(“Análisis terminado:”);

System.out.println

(“no se han hallado errores léxico-sintácticos”);

}

}

PARSER_END (ExprMin)

void unaExpresion() :

{ }

{

expresion() <EOF>

}

void expresion() :

{ }

{

termino() ( “+”  termino() )*

}

void termino() :

{ }

{

factor() ( “*”  factor() )*

}

void factor() :

{ }

{

<constante>

| <variable>

| “(” expresion() “)”

}

TOKEN:

{

<  variable : [“a”-“z”]  >

}

TOKEN:

{

<  constante :  ( [“0”-“9”] ) +  >

}

SKIP:

{ ” ” | “\t” | “\n” | “\r” }

• Obtención del analizador

Si la especificación precedente se tiene grabada en un fichero de nombre  Ejemplo.jj, para obtener el analizador:

–  se ejecuta el generador:   javacc Ejemplo.jj

–  se compila el analizador generado:    javac ExprMin.java

• Ejecución del analizador

Si se quiere analizar una expresión grabada en un fichero de nombre  PruebaExp.txt:

–  se ejecuta el analizador obtenido:    java ExprMin < PruebaExp.txt

VIDEO

Fuente: Sitio Oficial , Plugin , Ocio


Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: