Catégories : Tous - dimensiones - variables - memoria - identificadores

par Dennisse Enriquez Il y a 4 années

358

RESUMEN UNIDAD 3

En el desarrollo de traductores, una pieza crucial es la gestión de identificadores de usuario. La información almacenada en esta tabla depende del traductor específico, pero generalmente incluye el tipo de elemento, lo cual es vital para asegurar que el uso de las variables sea coherente con su declaración.

RESUMEN UNIDAD 3

RESUMEN UNIDAD 3

4.3 TABLA DE SIMBOLOS EJEMPLOS

- crear : Crea una tabla vacía. - insertar: Parte de una tabla de símbolo y de un nodo, lo que hace es añadir ese nodo a la cabeza de la tabla. - buscar: Busca el nodo que contiene el nombre que le paso por parámetro. - imprimir: Devuelve una lista con los valores que tiene los identificadores de usuario, es decir recorre la tabla de símbolos. Este procedimiento no es necesario pero se añade por claridad, y a efectos de resumen y depuración
El programa lex : Si se encuentra un número lo convierte a int y devuelve el token NUMERO. Si se encuentra un identificador de usuario: Primero lo busca en la tabla de símbolos, Si lo encuentra, entonces devuelve su valor Si no lo encuentra, lo inserta

El programa Yacc: %union { int numero; simbolo * ptr_simbolo; } Esto es un registro con parte variante, en el que todo es parte variante. Si ponemos %union ya no hay que poner YYSTYPE. Cosas interesantes de la gramática: prog : prog asig ... | (J forma parte de un prog). ; asig : ID ASIG expr | ID ASIG asig Como podemos observar esta regla es recursiva a la derecha. Se permiten cosas como a := b := c := 3 * 4 En cuanto a la regla expr produce ambigüedad, ésta se soluciona introduciendo las instrucciones % left ‘+’ % left ‘*’ El atributo del identificador de usuario ‘ID’, es un puntero a un símbolo.

4.2.- TABLA DE SÍMBOLOS

Una tabla de símbolos es una estructura de datos usada en el proceso de traducción de un lenguaje de programación (por un compilador o un intérprete), dónde cada símbolo en el código fuente de un programa está asociado con información tal como la ubicación, el tipo de datos y el ámbito de cada variable, constante o procedimiento.
La estructura inicial de la tabla de símbolos suele constar de dos partes:

PARTE VARIABLE

definida por el programador: con el significado de los identificadores utilizados en cada frase (programa).

PARTE FIJA

formada por las palabras clave del lenguaje (suelen ser de uso reservado y del orden de unas decenas de palabras en un lenguaje programación típico)

Operaciones con la Tabla de símbolos.

En general en la Tabla de símbolos (TS a partir de ahora) se realizan dos operaciones: la inserción y la búsqueda. En C la operación de inserción se realiza cuando se procesa una declaración. Hay dos posibilidades: que la TS esté ordenada (o sea, nombres de variables por orden alfabético) o que no esté ordenada.

Interfaz de la tabla de símbolos

Como ya se ha comentado, la interfaz de la tabla de símbolos debe quedar clara desde el principio de manera que cualquier modificación en la implementación de la tabla de símbolos no tenga repercusión en las fases del compilador ya desarrolladas. Las operaciones básicas que debe poseer son:

crear(): crea una tabla vacía. insertar(símbolo): añade a la tabla el símbolo dado. buscar(nombre): devuelve el símbolo cuyo nombre coincide con el parámetro. Si el símbolo no existe devuelve null. imprimir(): a efectos informativos, visualiza por la salida estándar la lista de variables almacenadas en la tabla de símbolos junto con sus valores asociados.

Estructura

Cada entrada de la tabla de símbolos corresponde a al declaración de un nombre. El formato de las entradas no tiene que ser uniforme porque la información de un nombre depende del uso de dicho nombre. Cada entrada en principio puede considerarse: ( Nombre, descriptor ) LEXEMA ATRIBUTOS

4.1.- IDENTIFICADORES DE USUARIO

La información que el desarrollador decida almacenar en esta tabla dependerá de las características concretas del traductor que esté desarrollando. Entre esta información puede incluirse:
• Valor del elemento

Cuando se trabaja con intérpretes sencillos, y dado que en un intérprete se solapan los tiempos de compilación y ejecución, puede resultar más fácil gestionar las variables si almacenamos sus valores en la tabla de símbolos.

• Dirección de memoria en que se almacenará su valor en tiempo de ejecución

Esta dirección es necesaria, porque las instrucciones que referencian a una variable deben saber donde encontrar el valor de esa variable en tiempo de ejecución con objeto de poder generar código máquina, tanto si se trata de variables globales como de locales.

Tipos de los parámetros formales

Si el identificador a almacenar pertenece a una función o procedimiento, es necesario almacenar los tipos de los parámetros formales para controlar que toda invocación a esta función sea hecha con parámetros reales coherentes.

• Tipo del elemento

Cuando se almacenan variables, resulta fundamental conocer el tipo de datos a que pertenece cada una de ellas, tanto si es primitivo como si no, con objeto de poder controlar que el uso que se hace de tales variables es coherente con el tipo con que fueron declaradas.

• Número de dimensiones.

Si la variable a almacenar es un array, también pueden almacenarse sus dimensiones.

• Nombre del elemento.

El nombre o identificador puede almacenarse limitando o no la longitud del mismo.

4.5.- Implementación de analizador léxico sintáctico

Haciendo usos de la estructura de análisis de un diagrama de Conway verificamos que todos los caminos desde el inicio de nuestro código, hasta el final; representan formas senténciales válidas. main ( ) {  get_token ( );  do {   expresión ( );   while (token != PUNTOYCOMA) {!Error en expresión¡  get_token ( );   };   get_token( );   }while (token != EOF);  };
En este caso se considera al ‘;’ como un token de seguridad, lo que permite hacer una recuperación de errores mediante el método panic mode.   El programa flex por medio de su proceso de compilación reconoce los errores sintácticos dentro de la estructura de análisis. Estos errores corresponden a que el analizador sintáctico pide al lexicográfico tokens a través de get_token ( );, y que el lexicográfico deja el token actual en la variable global token.  Es decir que antes de entrar a una función, en token debemos tener el token de lookahead, que esa función necesita consultar.
Analizador Sintáctico(Parser) Sintaxis: El orden correcto de las palabras Ej. Programa Fuente: 34:= *x - 640; Analex: NUM ASIGN POR ID MENOS NUM PTOCOMA Parser: "Error Sintáctico"

4.4.- Integración de JFlex (analizadores léxico y sintáctico)

OPCIONES Y DECLARACIONES
Codificación de caracteres

%7bit Permite usar entradas de 7 bits, es decir entre 0-127. Si una entrada es mayor que 127 se generará un error en tiempo de ejecución y se lanzará una excepción de tipo:

ArrayIndexOutofBoundsException.

Reglas lexicográficas

El siguiente fragmento formará parte esencial dentro del funcionamiento del analizador, en este se definirán el conjunto de expresiones regulares que se utilizarán durante el proceso de análisis, a continuación se presentan unos ejemplos de este tipo de declaraciones:

FinDeLinea = \r | \n | \r\n Variable = [:jletter:][:jletterdigit:]* Si = “Si” Entero = 0 | [1-9][0-9]*

Código de usuario

En el siguiente fragmento de código podremos incluir código Java el cual podemos utilizar en el analizador, cabe notar que el código que aquí se escriba será incluido sin ninguna alteración al resultado final del analizador, dicho fragmento ira enmarcado entre las etiquetas %{ al inicio del código y %} al final del mismo.

%{ public static void escribir(String cadena) { System.out.println(cadena); } % }

El bloque de configuración se define por el conjunto de parámetros que Unicode, es una gran tabla, que en la actualidad asigna un código a cada uno de los más de cincuenta mil símbolos, los cuales abarcan todos los alfabetos europeos, ideogramas chinos, japoneses, coreanos, muchas otras formas de escritura, y más de un millar de símbolos especiales.
Luego sigue un par de signos de porcentaje ( %) para indicar que empezará la definición del bloque de configuración del analizador.
La primera parte del archivo es el bloque donde se importaran los paquete que se van a utilizar para nuestro analizador, es decir, si en nuestro programa utilizaremos componentes del paquete útil debemos importar aquí dicho paquete: import java.util.*;
ESTRUCTURA UN ARCHIVO DE JFLEX
Un archivo JFex esta dividido en 3 secciones: Opciones y declaraciones Código de usuario Reglas lexicográfica
CARACTERÍSTICAS DE JFLEX
Las características sobre salientes de JFlex son las siguientes: Soporte completo con caracteres Unicode Permite generar analizadores léxicos rápidamente. Tiene una sintaxis cómo da de manipular y fácil de interpretar. Es independiente de la plataforma debido a que esta diseñado para ser integrado con Java. Permite la integración con CUP (Analizador sintáctico