RSS

03 Feb

ANTLR

ANTLR (ANother Tool for Language Recognition) es una herramienta creada principalmente por Terence Parr, que opera sobre lenguajes, proporcionando un marco para construir reconocedores (parsers), intérpretes, compiladores y traductores de lenguajes a partir de las descripciones gramaticales de los mismos (conteniendo acciones semánticas a realizarse en varios lenguajes de programación).

ANTLR genera analizadores pred-LL(k), y él mismo utiliza un analizador pred-LL(k) para leer los ficheros en los que están escritas las reglas EBNF. ANTLR admite acciones en sus reglas, además de otras prestaciones como paso de parámetros, devolución de valores o herencia de gramáticas.
Los analizadores en ANTLR
Ya mencionamos que ANTLR genera sus analizadores a partir de unos ficheros de entrada en los que se especifica el funcionamiento de dichos analizadores mediante el uso de reglas EBNF.
Para poder comprender los analizadores necesitaremos conocer la sintaxis de dichos ficheros de entrada.
Especificación de gramáticas con ANTLR
Los ficheros con los que trabaja ANTLR tienen la terminación *.g, y en adelante los llamaremos ficheros de especificación de gramáticas o, directamente, ficheros de gramáticas.
Un fichero de gramática contiene la definición de uno o varios analizadores. Cada uno de estos analizadores se traducirá a código nativo (java, C++ o C#, dependiendo de ciertas opciones) en forma de clases. Es decir, por cada analizador descrito en el fichero de gramáticas se generará una clase.

ANTLR esta dentro de la categoría de meta-programas, por ser un programa que escribe otros programas. Partiendo de la descripción formal de la gramática de un lenguaje, ANTLR genera un programa que determina si una sentencia o palabra pertenece a dicho lenguaje (reconocedor), utilizando algoritmos LL(*) de parsing. Si a dicha gramática, se le añaden acciones escritas en un lenguaje de programación, el reconocedor se transforma en un traductor o intérprete.

ANTLR es un programa está escrito en java, por lo que se necesita alguna máquina virtual de java para poder ejecutarlo. Es software libre, lo que quiere decir que al descargarlo de la página oficial (http://www.antlr.org) btendremos tanto los ficheros compilados *.class como el código fuente en forma de ficheros *.java.

ANTLR es un generador de analizadores. Mucha gente llama a estas herramientas compiladores de compiladores, dado que ayudar a implementar compiladores es su uso más popular. Sin embargo tienen otros usos. ANTLR, por ejemplo, podría servir para implementar el intérprete de un fichero de configuración.

ANTLR es capaz de generar un analizador léxico, sintáctico o semántico en varios lenguajes (java, C++ y C# en su versión 2.7.2) a partir de unos ficheros escritos en un lenguaje propio.

Dicho lenguaje es básicamente una serie de reglas EBNF y un conjunto de construcciones auxiliares.

 

JAVA CC

JavaCC (Java Compiler Compiler) es una herramienta de generación automática de  analizadores gramaticales basada en Java. La herramienta es propiedad de Sun  Microsystems, la compañía propietaria del lenguaje Java, por lo que se ha convertido en el metacompilador más usado por los programadores en Java.

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.

Indicaciones iniciales para  JavaCC

  • Disponibilidad del sistema Java

Es necesario disponer de una versión del sistema Java (compilador de Java e intérprete de la Máquina Virtual Java). Son programas de libre distribución; entre otros sitios se pueden conseguir en:

▫  la página oficial de Java

▫  la página de la asignatura Compiladores e Intérpretes

Herramientas → Desarrollos con Java → Máquina Virtual Java (se tiene la versión: Java 2 Runtime Environment. Standard Edition)

  • Disponibilidad del generador JavaCC

Es necesario disponer de una versión del generador JavaCC. Es un programa de libre distribución; entre otros sitios se pueden conseguir en:

▫  la página oficial de JavaCC:   https://javacc.dev.java.net

▫  la página de la asignatura Compiladores e Intérpretes

Herramientas → Desarrollos con Java → JavaCC  (se tiene la versión: Java Compiler Compiler, version 4.0)

Ejemplo:

options {
  IGNORE_CASE = true;
}
PARSER_BEGIN(ExampleParser)
 
  public class ExampleParser {
    //Ejecución del analizador
    public static void main ( String args [ ] ) {

      //Inicialización del analizador
      ExampleParser parser;
     
      if(args.length == 0){
        System.out.println (“ExampleParser: Leyendo de la entrada estandar …”);
        parser = new ExampleParser(System.in);
      }
      else if(args.length == 1){
        System.out.println (“ExampleParser: Leyendo de fichero ” + args[0] + ” …” );
        try {
          parser = new ExampleParser(new java.io.FileInputStream(args[0]));
        }
        catch(java.io.FileNotFoundException e) {
          System.out.println (“ExampleParser: El fichero ” + args[0] + ” no ha sido encontrado.”);
          return;
        }
      }
      else {
        System.out.println (“ExampleParser:  Debes utilizarlo de una de las siguientes formas:”);
        System.out.println (”         java ExampleParser < fichero”);
        System.out.println (“Or”);
        System.out.println (”         java ExampleParser fichero”);
        return ;
      }
      try {
        compilador.Start();
        System.out.println (“ExampleParser: La entrada ha sido leida con éxito.”);
      }
      catch(ParseException e){
        System.out.println (“ExampleParser: Ha ocurrido un error durante el análisis.”);
        System.out.println (e.getMessage());
      }
      catch(TokenMgrError e){
        System.out.println (“ExampleParser: Ha ocurrido un error.”);
        System.out.println (e.getMessage());
      }
    }
  }
PARSER_END(ExampleParser)

//ESTRUCTURAS Y CARACTERES DE ESCAPE
SKIP : {
 ” ”
|  “\t”
|  “\n”
|  “\r”
|  <“rem” (~[“\n”,”\r”])* (“\n” | “\r” | “\r\n”)>
}
//TOKENS ESTÁTICOS
TOKEN : {
 <INTEGER_CONSTANT: (<DIGIT>)+>
|  <LOGIC_CONSTANT: “true” | “false” | “-1”>
|  <STRING_CONSTANT: “\”” ( ~[“\””,”\\”,”\n”,”\r”] | “\\” ( [“n”,”t”,”b”,”r”,”f”,”\\”,”\'”,”\””] | ( [“\n”,”\r”] | “\r\n”)))* “\””>
|  <#DIGIT: [“0”-“9”]>
}
//PALABRAS RESERVADAS
TOKEN : {
 <NOT: “not”>
|  <IF: “if”>
|  <END: “end”>
|  <SUB: “sub”>
|  <LET: “let”>
|  <CALL: “call”>
|  <THEN: “then”>
|  <CASE: “case”>
|  <ELSE: “else”>
|  <INPUT: “input”>
|  <PRINT: “print”>
|  <SELECT: “select”>
|  <STATIC: “static”>
}
//TOKEN IDENTIFICADOR
TOKEN : {
 <IDENTIFIER: <LETTER>(<LETTER>|<DIGIT>)*([“$”])?>
|  <#LETTER: ([“a”-“z”,”A”-“Z”])>
}

//UNIDAD PRINCIPAL
void Start () : {}
{
  (
    INTEGER_CONSTANT | STRING_CONSTANT | LOGIC_CONSTANT |
    NOT | IF | END | SUB | LET | CALL | THEN | CASE | ELSE | INPUT | PRINT | SELECT | STATIC |
    IDENTIFIER
  )*
  <EOF>
}

Fuentes:Javacc

Anuncios
 
Deja un comentario

Publicado por en 3 febrero, 2011 en Uncategorized

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: