0% encontró este documento útil (0 votos)
482 vistas6 páginas

Ejemplo ANTLR

El documento describe un analizador simple creado con ANTLR para un lenguaje que permite asignar valores numéricos a variables. ANTLR genera analizadores léxicos, sintácticos y árboles de sintaxis abstracta. El ejemplo especifica analizadores léxico y sintáctico para un lenguaje que asigna valores numéricos a variables identificadas.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Temas abordados

  • entrada de teclado,
  • opciones de ANTLR,
  • métodos de análisis,
  • código de cabecera,
  • estructura de clases,
  • ejercicios,
  • gramáticas,
  • comentarios en código,
  • entrada de fichero,
  • tipos de datos
0% encontró este documento útil (0 votos)
482 vistas6 páginas

Ejemplo ANTLR

El documento describe un analizador simple creado con ANTLR para un lenguaje que permite asignar valores numéricos a variables. ANTLR genera analizadores léxicos, sintácticos y árboles de sintaxis abstracta. El ejemplo especifica analizadores léxico y sintáctico para un lenguaje que asigna valores numéricos a variables identificadas.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Temas abordados

  • entrada de teclado,
  • opciones de ANTLR,
  • métodos de análisis,
  • código de cabecera,
  • estructura de clases,
  • ejercicios,
  • gramáticas,
  • comentarios en código,
  • entrada de fichero,
  • tipos de datos

Procesadores del Lenguaje

Prctica 1: Ejemplo sencillo



ANTLR es una herramienta que integra la generacin de analizadores lxicos,
sintcticos, rboles de sintaxis abstracta y evaluadores de atributos. ANTLR est escrita en
Java y genera Java, C++ y C#. Todos los detalles de esta herramienta se encuentran en su
pgina oficial [Link]
En esta prctica trabajaremos con un lenguaje muy sencillo, que nos servir para
presentar la notacin que usa ANTLR para la especificacin de analizadores lxicos y
sintcticos. Aunque haremos algunas modificaciones sobre la solucin propuesta en el
enunciado, no ser hasta las prcticas 2 y 3 cundo estudiemos en profundidad los
problemas asociados a los analizadores lxicos y sintcticos. Todas las herramientas
necesarias para realizar la prctica estn instaladas en las aulas de laboratorio.

Un lenguaje ejemplo

El siguiente fragmento muestra el fichero de configuracin de un determinado
sistema. El lenguaje es extremadamente simple y slo permite asociar valores numricos a
una serie de variables:

max_robots = 50;
tiempo_combate = 120;
municion = 512;
max_ataques = 200;

Especificacin del analizador

ANTLR permite especificar cada analizador (lxico, sintctico, semntico) en un
fuente independiente o en un nico fuente. En este primer ejemplo optaremos por utilizar
un solo fuente. A medida que los analizadores sean ms complejos ser recomendable
especificar cada uno por separado. El analizador para nuestro lenguaje tendra un aspecto
como este en ANTLR:

///////////////////////////////
// Analizador lxico /////
//////////////////////////

class Analex extends Lexer;
BLANCO: (' '|'\t'|"\r\n") {$setType([Link]);};
protected LETRA : ('a'..'z')|'_';
protected DIGITO : '0'..'9';
NUMERO : (DIGITO)+;
IDENT : LETRA(LETRA|DIGITO)*;
SEPARADOR: ';';
OPERADOR: '=';




///////////////////////////////
// Analizador sintctico
///////////////////////////////

class Anasint extends Parser;
entrada : (asignacion)* ;
asignacion : IDENT "=" NUMERO ";" ;

La estructura de un fichero fuente ANTLR

Los ficheros de gramticas tienen la siguiente estructura:

header{
/* cdigo de cabecera */
}
options{
/* opciones comunes a toda la especificacin */
}
//////////////////////////////
// Definicin de analizadores
//////////////////////////////
...

Las dos primeras secciones son opcionales. La seccin header sirve para incluir
cdigo de cabecera, fundamentalmente instrucciones import o definicin del paquete al
que pertenecer la clase del analizador. La seccin options permite configurar algunos
aspectos de ANTLR a travs de opciones, que se representan mediante asignaciones del
tipo nombre_opcion = valor;. Tras estas secciones se incluye la definicin de los
analizadores, ANTLR permite especificar todos los analizadores en un nico fuente o
dedicar un fichero independiente para cada uno. La definicin de un analizador sigue la
siguiente estructura:

class nombre_analizador extends tipo_analizador;
options {
/* opciones especficas del analizador */
}
tokens {
/* definicin de tokens */
}
{
/* cdigo propio del analizador */
}

//---------------------------
// Zona de reglas
//---------------------------
...




donde:

La primera instruccin sirve para establecer cual ser el nombre del analizador y de qu
clase heredar (tipo_analizador). En el caso de analizadores lxicos se extender la
clase Lexer, para los sintcticos se usar Parser y TreeParser para los recorridos
de rboles de sintaxis abstracta.
La seccin options ser opcional y servir para especificar opciones propias del
analizador. Se puede, por ejemplo, definir el nmero de smbolos de anticipacin en el
reconocimiento LL(k), importar tokens, etc.
La seccin tokens tambin es opcional, permite definir nuevos tokens que se aaden a
los definidos en otros analizadores.
La zona de cdigo nativo sirve para incluir declaraciones de atributos y mtodos que se
aaden a las que de forma automtica se generan para la clase que implementa el
analizador.
Por ltimo la zona de reglas constituye el ncleo de la especificacin. En los ejemplos
previos ya hemos mostrado el aspecto que tienen estas reglas.
Los comentarios se pueden incluir en cualquier parte del fuente, permitindose
comentarios de una sola lnea (con el smbolo //) y de varias lneas (con los smbolos /*
y */ para marcar el comienzo y final respectivamente).

Ejecutando el intrprete

Hasta ahora hemos especificado los distintos analizadores, pero an nos queda por
escribir un ltimo fuente para poder ejecutarlos, el que describe la clase que contiene el
mtodo main:

/////////////////////////////////////
// [Link] (clase principal)
/////////////////////////////////////
import [Link].*;
import [Link];
import [Link];

public class Procesador {

public static void main(String args[]) {

try {

FileInputStream fis =
new FileInputStream("[Link]");
Analex analex = null;
Anasint anasint = null;
analex = new Analex(fis);
anasint = new Anasint(analex);
[Link]();

}catch(ANTLRException ae) {

[Link]([Link]());

}catch(FileNotFoundException fnfe) {

[Link]("No se encontr el fichero");

}
}
}

El cdigo es bastante claro y en general se limita a:
Abrir el fichero "[Link]".
Crear un objeto de cada analizador.
Lanzar el mtodo [Link]()para realizar el anlisis sintctico.
Capturar las distintas excepciones que se hayan podido lanzar durante el proceso.

Lectura de flujos de bytes y flujos de caracteres

Los reconocedores generados por ANTLR pueden adaptarse con facilidad para leer
desde distintos flujos de entrada. La clase que implementa el anlisis lxico (en nuestro
ejemplo Analex) es la encargada de recibir ese flujo de entrada y su constructor puede
recibir tanto objetos de la clase InputStream para recibir flujos de bytes, como de la
clase Reader para recibir flujos de caracteres.

Como ya hemos visto en el ejemplo anterior, FileInputStream (una subclase
de InputStream) nos sirve para procesar entradas almacenadas en un fichero. En el
siguiente ejemplo veremos cmo StringReader (una subclase de Reader) nos
permitir aplicar el anlisis lxico al contenido de una cadena de caracteres que a su vez ha
sido leda desde el teclado:

/////////////////////////////////////
// [Link] (clase principal)
/////////////////////////////////////

import [Link].*;
import [Link];
import [Link];

public class Procesador {

public static void main(String args[]) {

try {

InputStreamReader isr =
new InputStreamReader([Link]);
BufferedReader br = new BufferedReader(isr);
String linea = [Link]();
while (![Link]("$")) {
Analex analex = null;
Anasint anasint = null;
analex = new Analex(new StringReader(linea));
anasint = new Anasint(analex);
[Link]();
linea = [Link]();

}
}catch(ANTLRException ae) {

[Link]([Link]());

}catch(IOException ioe) {

[Link]([Link]());
}
}
}

Los aspectos ms interesantes de este programa son:

Se construye el flujo de caracteres isr aplicando InputStreamReader sobre el
flujo de bytes [Link].
A partir del flujo isr se obtiene br, un flujo de caracteres con buffer
(BufferedReader) que puede leerse lnea a lnea.
La entrada del teclado se lee lnea a lnea en la variable linea en un bucle que se repite
hasta que se introduce $, el carcter elegido para indicar el fin del proceso.
Para analizar el contenido de la variable lnea basta con crear a partir de ella un flujo de
entrada con el constructor StringReader. Dicho flujo se utilizar en la construccin del
analizador lxico.

EJERCICIOS

1. Compilar los fuentes presentados en el enunciado y comprobar el funcionamiento del
reconocedor de expresiones propuesto.

2. Modificar la clase principal de manera que en lugar de leer siempre del fichero
"[Link]" reciba el nombre del fichero a procesar a travs del parmetro
args[0] del mtodo main.

3. Adaptar el reconocedor de manera que la entrada se lea del teclado y no de un fichero. La
entrada se procesar lnea a lnea y por tanto no ser necesario tener en cuenta el smbolo
";" como separador. El proceso terminar cuando se introduzca la entrada $. Ante
entradas correctas el intrprete no emitir ningn mensaje mientras que para entradas
incorrectas se mostrar el mensaje de error generado por ANTLR.
Se detecta bien una entrada incorrecta de la forma max_robots = 12 12?
Cmo se puede solucionar este problema?


4. Ampliar el lenguaje del apartado 2 con los siguientes elementos:

Valores tipo booleano (true, false), cadenas y rutas de ficheros (siempre empiezan con
"/"):
disparo_efectuado = TRUE;
directorio_ficheros_cfg_robots = /home/robot/work;
mensaje = "el robot ha hecho blanco";

Variables de usuario definidas con la palabra instruccin SET, los nombres empezarn
con "$":

SET $nombre_robot = Legolas;

5. Ampla el lenguaje anterior de manera con una instruccin condicional if, que permita
decidir si se ejecuta una parte del fichero en funcin del valor de una variable booleana
(predefinida o de usuario):

SET $multi_robot = TRUE;
IF ($multi_robot) {
max_robots = 10;
}

Common questions

Con tecnología de IA

Dentro de un fichero de gramática ANTLR, las reglas constituyen el núcleo de la especificación del analizador, siguiendo la estructura de "class nombre_analizador extends tipo_analizador". Las reglas definen cómo deben reconocerse y manipularse los elementos del lenguaje, especificando relaciones y transiciones entre tokens. Por ejemplo, una regla de asignación en ANTLR podría definirse como "asignacion : IDENT '=' NUMERO ';'". Estas reglas son fundamentales para describir conductas, determinar secuencias aceptables y permitir la ejecución lógica de un lenguaje determinado .

El análisis léxico en ANTLR se adapta para leer distintos flujos de entrada. La clase de análisis léxico, por ejemplo Analex, puede recibir un InputStream para flujos de bytes o un Reader para flujos de caracteres. Para flujos de bytes, se utiliza FileInputStream para leer de ficheros, mientras que StringReader permite leer cadenas de caracteres del teclado, procesando línea a línea mediante un BufferedReader hasta que se introduce un carácter especial para terminar ($).

Especificar analizadores en un único archivo fuente simplifica la gestión y el mantenimiento cuando se trata de lenguajes sencillos, permitiendo una vista unificada del proceso de análisis. Sin embargo, a medida que los analizadores aumentan en complejidad, separar cada analizador en archivos independientes mejora la modularidad y facilita el trabajo colaborativo y la especialización de cada componente, ofreciendo más flexibilidad y claridad para sistemas amplios y complejos .

En un fichero fuente de ANTLR, las secciones header y options son opcionales. La sección header sirve para incluir código de cabecera, como instrucciones import o definición del paquete para la clase del analizador. La sección options permite configurar aspectos de ANTLR a través de opciones, como el número de símbolos de anticipación en el reconocimiento LL(k).

El uso de BufferedReader en ANTLR para gestionar flujos de entrada desde el teclado facilita la lectura línea a línea, almacenando datos en un buffer que mejora el rendimiento y reduce la cantidad de operaciones de lectura. BufferedReader proporciona un método readLine() eficiente, crucial para analizar interactivamente entrada continua y no previamente delimitada al ejecutar anasint.asignacion() en cada línea recibida .

La capacidad de ANTLR para generar código para diversos lenguajes, como Java, C++, y C#, facilita su integración en diferentes plataformas y contextos de programación, aumentando la flexibilidad y reutilización del código generado. Esto permite a los desarrolladores emplear ANTLR en un entorno familiar o en el que su aplicación ya está implementada, optimizando recursos y reduciendo barreras de lenguaje al momento de implementar analizadores personalizados .

Permitir entradas desde el teclado implica que el sistema debe gestionar entradas no predefinidas y dinámicas, requiriendo mecanismos para terminar la lectura como el uso de un carácter especial ($). Mientras un fichero permite una revisión integral y previa de errores, la entrada por teclado introduce la necesidad de una validación continua y manejo interactivo, lo que puede aumentar la complejidad del analizador léxico y comprometer la consistencia si no se gestionan bien los errores en tiempo real .

ANTLR es una herramienta que integra la generación de analizadores léxicos, sintácticos, árboles de sintaxis abstracta y evaluadores de atributos. Está escrita en Java y puede generar analizadores en los lenguajes Java, C++, y C# .

Para incluir variables booleanas y cadenas en un lenguaje sencillo en ANTLR, el lenguaje se puede extender para admitir boolenos literal, como 'TRUE' y 'FALSE', así como cadenas entre comillas dobles. Además, para incluir rutas de ficheros, se puede definir una regla donde la ruta siempre comience con '/'. Estas extensiones permiten trabajar con un mayor conjunto de datos y expresiones en el lenguaje .

El flujo de ejecución comienza con la apertura de un fichero de entrada utilizando FileInputStream. Se crean objetos para cada analizador, léxico y sintáctico, y se procede a realizar el análisis sintáctico con anasint.entrada(). Durante el proceso, se capturan excepciones ANTLRException y FileNotFoundException, manejando errores potenciales como la falta del fichero o errores internos del análisis .

También podría gustarte