Procesadores del Lenguaje Práctica 1: Ejemplo sencillo

Documentos relacionados
PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 1

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 1

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 6

LABORATORIO 1: ENTORNO DE DESARROLLO

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 5

Árboles de Sintaxis Abstracta en ANTLR

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 3

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 2

TEMA 2: ANÁLISIS LÉXICO-SINTÁCTICO

PROCESADORES DEL LENGUAJES Enero 2015

PROCESADORES DE LENGUAJES I PRÁCTICA DE LABORATORIO 4

PROCESADORES DEL LENGUAJES Ev. Alternativa

Práctica #5: Uso de control de flujo, Excepciones y Lectura Estándar

Objetivos. El alumno empleará el concepto de excepción en la programación orientada a objetos para el manejo de errores de ejecución.

Por el contrario System.in es un byte Stream sin caracteristicas de character Stream.

Departamento de Lenguajes y Sistemas Informáticos Procesadores de Lenguajes

TEMA 3: ANÁLISIS SEMÁNTICO

Examen parcial Convocatoria de junio de 2005 FUNDAMENTOS DE LA PROGRAMACIÓN

TEMA 2: PARSERS Y CONSTRUCCIÓN DEL ÁRBOL DE SINTAXIS ABSTRACTA PARA L-0

El programa P1 tiene como objetivo imprimir cada uno de los caracteres de una cadena en una línea, como por ejemplo: h o l a

VARIABLES AUTOMÁTICAS

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

UNIVERSIDAD DE CÓRDOBA ESCUELA POLITÉCNICA SUPERIOR DEPARTAMENTO DE INFORMÁTICA Y ANÁLISIS NUMÉRICO

c) Explicar qué es un BreakPoint en Netbeans y para qué sirve. 0,5 punto

Unidad II. Fundamentos de programación en Java. Ing. José Luis Llamas Cárdenas

Tema 4. Excepciones en Java

7. Otras sentencias Sentencia break. 84 A. García-Beltrán y J.M. Arranz

Estructura de datos y Programación

PROCESADORES DEL LENGUAJES Enero 2018

Compiladores e Intérpretes

Elementos Básicos de Java. LUIS MENGUAL (c)

Fundamentos de Computadores y Lenguajes

PROGRAMACIÓN EN JAVA. { una línea para definir, crear o ejecutar ; }

PROCESADORES DEL LENGUAJES Septiembre 2017

Parte I: Programación en un lenguaje orientado a objetos

Tema 4. Control de flujo. Programación Programación - Tema 4: Control de Flujo

Maestro Coordinador de la Carrera Gestión de la Calidad Director de la Facultad

Programación Orientada a Objetos (Grado en Ingeniería Informática y Grado en Ingeniería en Tecnologías de la Información - UNED)

ANÁLISIS LÉXICO Ing. Ronald Rentería Ayquipa

PRACTICA Nº Realizar una aplicación que calcule el volumen de una esfera, que viene dado por la fórmula:

1. Cuántas sentencias hay en la secuencia principal del siguiente programa?

Conceptos básicos de Orientación a Objetos, manejo con Eclipse.

Entrada y Salida de datos

Estructura de un programa en Java. Tipos de datos básicos. class miprimerprograma{ // comentario, no es parte del programa

HERENCIA. Problema: Reparar el el coche. Jesús (Valencia) Luis, Mecánico (Valencia) Antonio, Servicio Técnico Ferrari (Madrid)

Arquitecturas cliente/servidor

Estructuras de control selectivas

a) Reescribir P1 introduciendo un error sintáctico (de compilación), otro de ejecución, y

Objetivos. Índice. 1. Paquetes

Introducción a Java 10/02/2011. Tokens. Juan Manuel Fernández Peña Curso Rev Tokens. Tokens

Introducción a Java. Introducción a Java. Programación I

3.9 Streams y Archivos Streams Básicos 18/04/2004. API de InputStream (1/2) Streams de Bytes y Caracteres. API de OutputStream

PROGRAMACIÓN ORIENTADA A OBJETOS 10/02/2009. Examen de Java. Nombre: DNI: Titulación:

Excepciones. Una excepción es una situación anómala a la que llega la ejecución de un programa

Fundamentos de Computadores y Lenguajes

Examen escrito de Programación I

PROGRAMACIÓN ORIENTADA A OBJETOS (L40629) Sabino Miranda-Jiménez

Construcciones del Lenguaje Java

Tema 2: EL TIPO DE DATOS ENTERO. INSTRUCCIÓN DE ASIGNACIÓN Y DE COMPOSICIÓN SECUENCIAL

Excepciones. Excepciones

Ficheros y streams. Desde el punto de vista de Java, cada fichero no es más que una secuencia o flujo de bytes [stream].

Java. Introducción a la Programación Orientada a Objetos

El programa P1 tiene como objetivo imprimir cada uno de los caracteres de una cadena en una línea, como por ejemplo: h o l a

VARIABLES, CONSTANTES Y EXPRESIONES ASIGNACIÓN. TIPOS ELEMENTALES. PRECEDENCIA DE LOS ESTRUCTURAS DE CONTROL. CONDICIONAL E

PROGRAMACIÓN ORIENTADA A OBJETOS 1/7/2009. Examen de Java. Nombre: DNI: Titulación:

Carlos Montenegro. Programación Orientada a Objetos Proyecto Curricular de Ingeniería de Sistemas

Flujos (streams) Programación. Licenciatura Lingüística y Nuevas Tecnologias Nadjet Bouayad-Agha

Esta aplicación se compone de 3 programas o clases, según el siguiente esquema: SueldoMedio.java. Sueldo.java

Examen de prácticas de Programación 1

Guía - Taller # 2 (JAVA)

a. Cuántas veces se ejecuta la instrucción System.out.println? b. Cuál es el diagrama de flujo correspondiente a este fragmento?

TEORÍA DE AUTÓMATAS Y LENGUAJES

Centro Asociado Palma de Mallorca. Antonio Rivero Cuesta

Examen Teórico. Convocatoria de Febrero de 2015

Manejo de Excepciones

Elementos léxicos del lenguaje de programación Java

Introducción a Java. Fernando Cerezal López. 24 Noviembre 2005

Procesamiento de Lenguajes (PL) Curso 2014/2015. Práctica 1: analizador descendente recursivo

HOJA DE EJERCICIOS 5 PROGRAMACIÓN CON EXCEPCIONES EN JAVA

TECNICAS DE PROGRAMACION Universidad Católica Los Angeles de Chimbote MODIFICADORES DE ACCESO A LOS MIEMBROS DE UNA CLASE

INGENIERÍA DE PROTOCOLOS DE COMUNICACIONES (MÓDULO 2)

M.C. Yolanda Moyao Martínez

PROGRAMACIÓN ORIENTADA A OBJETOS CON JAVA

String s = t.readline() 4. Si el valor leído desde teclado, se requiere almacenar en una variable de un tipo diferente a

Compiladores: Introducción

1. (1 punto) Dado el siguiente fragmento de programa:

PROGRAMACIÓN EN JAVA

Lenguajes de programación

Unidad Didáctica 3. Tipos genéricos. Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos

GENERACIÓN DE CÓDIGO INTERMEDIO EJEMPLOS PARA DISTINTAS ESTRUCTURAS DE DATOS

Tema 5. Análisis semántico

HERENCIA (2ª parte) En Java todas las clases derivan de otra, aunque no se diga explícitamente.

Unidad V. Ya veremos qué poner en "algunas_palabras" y "algo_más", por ahora sigamos un poco más.

Tema 2: Análisis léxico

Programación Orientada a Objetos

Transcripción:

Procesadores del Lenguaje Práctica 1: Ejemplo sencillo ANTLR es una herramienta que integra la generación de analizadores léxicos, sintácticos, á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 página oficial http://www.antlr.org/. En esta práctica trabajaremos con un lenguaje muy sencillo, que nos servirá para presentar la notación que usa ANTLR para la especificación de analizadores léxicos y sintácticos. Aunque haremos algunas modificaciones sobre la solución propuesta en el enunciado, no será hasta las prácticas 2 y 3 cuándo estudiemos en profundidad los problemas asociados a los analizadores léxicos y sintácticos. Todas las herramientas necesarias para realizar la práctica están instaladas en las aulas de laboratorio. Un lenguaje ejemplo El siguiente fragmento muestra el fichero de configuración de un determinado sistema. El lenguaje es extremadamente simple y sólo permite asociar valores numéricos a una serie de variables: max_robots = 50; tiempo_combate = 120; municion = 512; max_ataques = 200; Especificación del analizador ANTLR permite especificar cada analizador (léxico, sintáctico, semántico) 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 más complejos será recomendable especificar cada uno por separado. El analizador para nuestro lenguaje tendría un aspecto como este en ANTLR: /////////////////////////////// // Analizador léxico ///// ////////////////////////// class Analex extends Lexer; BLANCO: (' ' '\t' "\r\n") {$settype(token.skip);; protected LETRA : ('a'..'z') '_'; protected DIGITO : '0'..'9'; NUMERO : (DIGITO)+; IDENT : LETRA(LETRA DIGITO)*; SEPARADOR: ';'; OPERADOR: '=';

/////////////////////////////// // Analizador sintáctico /////////////////////////////// class Anasint extends Parser; entrada : (asignacion)* ; asignacion : IDENT "=" NUMERO ";" ; La estructura de un fichero fuente ANTLR Los ficheros de gramáticas tienen la siguiente estructura: header{ /* código de cabecera */ options{ /* opciones comunes a toda la especificación */ ////////////////////////////// // Definición de analizadores //////////////////////////////... Las dos primeras secciones son opcionales. La sección header sirve para incluir código de cabecera, fundamentalmente instrucciones import o definición del paquete al que pertenecerá la clase del analizador. La sección options permite configurar algunos aspectos de ANTLR a través de opciones, que se representan mediante asignaciones del tipo nombre_opcion = valor;. Tras estas secciones se incluye la definición de los analizadores, ANTLR permite especificar todos los analizadores en un único fuente o dedicar un fichero independiente para cada uno. La definición de un analizador sigue la siguiente estructura: class nombre_analizador extends tipo_analizador; options { /* opciones específicas del analizador */ tokens { /* definición de tokens */ { /* código propio del analizador */ //--------------------------- // Zona de reglas //---------------------------...

donde: La primera instrucción sirve para establecer cual será el nombre del analizador y de qué clase heredará (tipo_analizador). En el caso de analizadores léxicos se extenderá la clase Lexer, para los sintácticos se usará Parser y TreeParser para los recorridos de árboles de sintaxis abstracta. La sección options será opcional y servirá para especificar opciones propias del analizador. Se puede, por ejemplo, definir el número de símbolos de anticipación en el reconocimiento LL(k), importar tokens, etc. La sección tokens también es opcional, permite definir nuevos tokens que se añaden a los definidos en otros analizadores. La zona de código nativo sirve para incluir declaraciones de atributos y métodos que se añaden a las que de forma automática se generan para la clase que implementa el analizador. Por último la zona de reglas constituye el núcleo de la especificación. En los ejemplos previos ya hemos mostrado el aspecto que tienen estas reglas. Los comentarios se pueden incluir en cualquier parte del fuente, permitiéndose comentarios de una sola línea (con el símbolo //) y de varias líneas (con los símbolos /* y */ para marcar el comienzo y final respectivamente). Ejecutando el intérprete Hasta ahora hemos especificado los distintos analizadores, pero aún nos queda por escribir un último fuente para poder ejecutarlos, el que describe la clase que contiene el método main: // Procesador.java (clase principal) import java.io.*; import antlr.collections.ast; import antlr.antlrexception; public class Procesador { public static void main(string args[]) { try { FileInputStream fis = new FileInputStream("entrada.txt"); Analex analex = null; Anasint anasint = null; analex = new Analex(fis); anasint = new Anasint(analex); anasint.entrada(); catch(antlrexception ae) {

System.err.println(ae.getMessage()); catch(filenotfoundexception fnfe) { System.err.println("No se encontró el fichero"); El código es bastante claro y en general se limita a: Abrir el fichero "entrada.txt". Crear un objeto de cada analizador. Lanzar el método anasint.entrada()para realizar el análisis sintáctico. 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 análisis léxico (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 cómo StringReader (una subclase de Reader) nos permitirá aplicar el análisis léxico al contenido de una cadena de caracteres que a su vez ha sido leída desde el teclado: // Procesador.java (clase principal) import java.io.*; import antlr.collections.ast; import antlr.antlrexception; public class Procesador { public static void main(string args[]) { try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String linea = br.readline(); while (!linea.equals("$")) { Analex analex = null;

Anasint anasint = null; analex = new Analex(new StringReader(linea)); anasint = new Anasint(analex); anasint.asignacion(); linea = br.readline(); catch(antlrexception ae) { System.err.println(ae.getMessage()); catch(ioexception ioe) { System.err.println(ioe.getMessage()); Los aspectos más interesantes de este programa son: Se construye el flujo de caracteres isr aplicando InputStreamReader sobre el flujo de bytes System.in. A partir del flujo isr se obtiene br, un flujo de caracteres con buffer (BufferedReader) que puede leerse línea a línea. La entrada del teclado se lee línea a línea en la variable linea en un bucle que se repite hasta que se introduce $, el carácter elegido para indicar el fin del proceso. Para analizar el contenido de la variable línea basta con crear a partir de ella un flujo de entrada con el constructor StringReader. Dicho flujo se utilizará en la construcción del analizador léxico. 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 "entrada.txt" reciba el nombre del fichero a procesar a través del parámetro args[0] del método main. 3. Adaptar el reconocedor de manera que la entrada se lea del teclado y no de un fichero. La entrada se procesará línea a línea y por tanto no será necesario tener en cuenta el símbolo ";" como separador. El proceso terminará cuando se introduzca la entrada $. Ante entradas correctas el intérprete no emitirá ningún 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? Cómo 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 instrucción SET, los nombres empezarán con "$": SET $nombre_robot = Legolas ; 5. Amplía el lenguaje anterior de manera con una instrucción condicional if, que permita decidir si se ejecuta una parte del fichero en función del valor de una variable booleana (predefinida o de usuario): SET $multi_robot = TRUE; IF ($multi_robot) { max_robots = 10;