Antlr

ANTLR (ANother Tool for Language Recognitionotra herramienta para reconocimiento de lenguajes) 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 cae 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.

Además, ANTLR proporciona facilidades para la creación de estructuras intermedias de análisis (como ser ASTs – Abstract Sintax Tree), para recorrer dichas estructuras, y provee mecanismos para recuperarse automáticamente de errores y realizar reportes de los mismos.

ANTLR es un proyecto bajo licencia BSD, viniendo con todo el código fuente disponible, y preparado para su instalación bajo plataformas Linux, Windows y Mac OS X.

ANTLRWorks es un entorno de desarrollo con interfaz gráfica que permite el desarrollo de gramáticas para la versión 3.0 o superior de ANTLR. Consiste en una aplicación independiente Java, que se puede ejecutar directamente desde un jar. De quererse incorporar las funcionalidade de ANTLR en ambientes de desarrollo ya existentes, existen plug-ins que se pueden bajar directamente de la web del autor, habilitando el poder trabajar en IntelliJ, gUnit, Eclipse, NetBeans, etc.

Actualmente ANTLR genera código Java, C, C++, C#, Python, Perl, Delphi, Ada95, JavaScript y Objective-C. Otros lenguajes como Ruby, php, etc. son generados por medio de extensiones planteadas por la comunidad.

Ejemplo

grammar SimpleCalc;



tokens {

 PLUS     = '+' ;

 MINUS = '-' ;

}



@members {

 public static void main(String[] args) throws Exception {

 SimpleCalcLexer lex = new SimpleCalcLexer(new ANTLRFileStream(args[0]));

 CommonTokenStream tokens = new CommonTokenStream(lex);

 SimpleCalcParser parser = new SimpleCalcParser(tokens);

 try {

 parser.expr();

 } catch (RecognitionException e)  {

 e.printStackTrace();

 }

 }

}



/*------------------------------------------------------------------

 * PARSER RULES

 *------------------------------------------------------------------*/

expr      : ID '=' op {System.out.println($ID.text +"="+ $op.value);};

op          returns [int value]

 :   e=factor {$value = $e.value;}

 (   PLUS e=factor {$value += $e.value;}

 |   MINUS e=factor {$value -= $e.value;}

 )*

 ;

factor    returns [int value]

: NUMBER {$value = Integer.parseInt($NUMBER.text);};



/*------------------------------------------------------------------

 * LEXER RULES

 *------------------------------------------------------------------*/



ID  :   ('a'..'z'|'A'..'Z')+ ;

NUMBER             : (DIGIT)+ ;

WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+   { $channel = HIDDEN; } ;

fragment DIGIT                : '0'..'9' ;

 

La primera parte es la cabecera del fichero. Aquí hemos de prestar atención de darle el mismo nombre que tiene el fichero. ¿Os recuerda a java esto, no? Pues básicamente la idea es la misma. La clase debe llamarse igual que el nombre del fichero, sino, no compilará.

El segundo bloque es la declaración de tokens. Aquí debemos añadir todos los elementos que queremos que reconozca nuestra gramática. En nuestro caso el signo + y el signo –

El tercer bloque @ members contiene el código java de nuestra aplicación. En nuestro caso hemos colocado un main. De hecho el programa funcionará igual sin este código el problema es que no podremos llegar a ver nada si el texto de entrada es aceptado. Lo que hace este código es leer un fichero de texto especificado en la línea de comandos cuando arrancamos nuestro compilador, eso es args[0]. Dentro del bloque try, llamamos a la primera regla del programa (parser.expr()), esto desencadenará el inicio del programa.

El cuarto bloque es las reglas del parser, es decir puramente la gramática. Aquí podemos ver como una expresión es un ID (identificador, o nombre de variable) el token igual ´=´ (si, ya sé que lo podríamos haber definido en el apartado de tokens, pero para que vierais que también podemos ponerlo directamente aquí) y una operación (la definimos más abajo). Lo que vemos entre { } es el código java que he escrito yo. Basicamente nos imprimirá por pantalla las expresiones que vaya reconociendo.
La siguiente regla es la operación. Tenemos un factor OPERANDO factor. El factor en nuestro caso será un entero, lo podemos ver en la tercera regla. Lo que hace es almacenar en una variable valor temporal, el resultado de sumar o restar los dos factores.
La tercera regla, almacena en una variable llamada value el resultado de parsear la lectura del fichero a un Entero.

El cuarto bloque es la declaración de los tipos en nuestro caso un ID (identificador de variable) es cualquier nombre de la a-Z que contenga al menos una letra. Esto es debido a la cláusula positiva de Klenee (+).
El mismo razonamiento para los números, para los espacios en blanco y los dígitos.

Me he dejando por comentar un par de cosas adrede, porque quería que quedaran claras. Los campos disponen de varios valores (como si fueran una struct) estos son .value y .text.

Se entiende que value es un entero y text un campo para almacenar strings, como los ID.

5 comentarios sobre “Antlr

  1. que mas bro… me alegro q te sirva… verás netbeans tiene un plugin que te va a permitir trabajar con antlr, es decir, te reconoce la sintaxis de antlr (es la misma del ejemplo de arriba) y te ayuda a la ejecución… creo que tengo ese plugin x ahí o busca uno de acuerdo a la versión de tu netbeans…

  2. Mis saludos para usted, soy un estudiante universitario de La Universidad de las Tunas, Cuba. Estoy a punto de discutir mi tema de tesis por lo que le pediria de favor si me podria aclarar algunas dudas de concepto referente a los interpretes.
    Mi tesis trata de un editor de formulas para elaborar aceros inoxidables, lo realice utilizando el plugin Antlr+Eclipse para implementar el analizador lexico-sintactico-semantico y exporte las clases a ficheros *.js, luego utilice Visual Studio y ExtJS para la implementacion de la interfaz visual del mismo, integrandolo luego a las clases generadas por Antlr lexer-parcer.
    Luego de hacerle un preambulo mi duda surge porque la definicion de interpretes en algunas bibliografias definen que el interprete ademas de ejecutar estos analisis al final debe realizar una accion determinada. Mi programa ha sido cuestionado por estas definiciones, pero observando la definicion de usted del Antlr, mi software cumple. Tambien se me olvidaba que ademas implemente a mano el analisis semantico, comparando Token a token de la formula con elementos de la base de dato para comprobar su validez y al final en vez de una ejecucion solo le muestro al usuario si está correctamente definida la formula.

    1. Que tal amigo… la información que está en esta entrada es recopilación de algunas fuentes bibliográficas… así que supongo que su software se encuentra bien desarrollado de acuerdo a lo que me dice… además cumple cada analizador con su parte… presentalo y suerte…

  3. Muchas Gracias Amigo……..Entonces usted cree que el termino que utilizo que mi software pertenece a los interpretes pero en el caso particular a los iterpretes de formula para la elaboracion de acero este correcta por bibliografias consultadas……entonces hago referencia a su sitio claro si usted me lo permite…

Replica a fabricioflores Cancelar la respuesta