Categorias: Todos - memoria - símbolos - identificadores - análisis

por Sergio Cunduri 4 anos atrás

371

UNIDAD 4: IMPLEMENTACIÓN DE ANALIZADORES LÉXICO / SINTACTICO

En el proceso de compilación de programas, se lleva a cabo un análisis léxico y sintáctico para asegurar que el código fuente es válido según las reglas del lenguaje de programación utilizado.

UNIDAD 4: IMPLEMENTACIÓN DE ANALIZADORES LÉXICO / SINTACTICO

UNIDAD 4: IMPLEMENTACIÓN DE ANALIZADORES LÉXICO / SINTACTICO

4.3. EJEMPLO DE LA TABLA DE SÍMBOLOS Bibliografía: http://www.lcc.uma.es/~galvez/ftp/tci/tictema5.pdf

FICHERO TablaSimbolo.yacc
%{ #include "tabsimb2.c" simbolo * t; %} %union { int numero; simbolo * ptr_simbolo; } %token NUMERO %token ID %token ASIG %type expr asig prog %start prog %left '+' %left '*' %% prog : prog asig '\n' { printf("Asignaciones efectuadas\n");} | prog expr '\n' { printf("%d\n",$2);} | prog error '\n' { yyerrok;} | ; asig : ID ASIG expr { $$ = $3; $1->valor = $3; } | ID ASIG asig { $$ = $3; $1->valor = $3; } ; expr : expr '+' expr {$$ = $1 + $3;} | expr '*' expr {$$ = $1 * $3;} | ID {$$ = $1->valor; } | NUMERO {$$ = $1;} ; %% #include "ejem2l.c" #include "errorlib.c" void main() { t = crear(); yyparse (); imprimir(t); }
FICHERO TablaSimbolo.lex
%% [0-9]+ { yylval.numero = atoi(yytext); return NUMERO; } ":=" { return ASIG; } [a-zA-Z][a-zA-Z0-9]*{ yylval.ptr_simbolo = buscar(t,yytext); if (yylval.ptr_simbolo == NULL) { yylval.ptr_simbolo=(simbolo *) malloc(sizeof(simbolo)); strcpy(yylval.ptr_simbolo->nombre, yytext); yylval.ptr_simbolo->valor=0; insertar(&t, yylval.ptr_simbolo); } return ID; } [ \t]+ {;} .|\n { return yytext[0]; } %%
FICHERO TablaSimbolo.c
#include #include typedef struct nulo { struct nulo * sig; char nombre [20]; int valor; } simbolo; simbolo * crear() { return NULL; }; void insertar(p_t,s) simbolo **p_t; simbolo * s; { s->sig = (*p_t); *p_t) = s; }; simbolo * buscar(t,nombre) simbolo * t; char nombre[20]; { while ( (t != NULL) && (strcmp(nombre, t->nombre)) ) t = t->sig; return (t); }; void imprimir(t) simbolo * t; { while (t != NULL) { printf("%s\n", t->nombre); t = t->sig; } };

4.4. INTEGRACIÓN DE UN ANALIZADOR LÉXICO / SINTÁCTICO Bibliografía: https://docplayer.es/25036146-Integracion-de-jflex-y-cup-analizadores-lexico-y-sintactico.html

Integración del generador de analizadores léxicos (JFLEX) y Generador de analizadores Sintácticos (CUP).
CUP

SINTAXIS

Definición de símbolo inicial de la gramática y reglas de producción

Declaración de procedencia

Declaración de símbolos terminales y no terminales

Sección de código de usuario

Definición de paquete y sentencias import

CUP es un homólogo para Java del programa YACC utilizado en C

Es un meta-compilador utilizado para generar analizadores sintácticos ascendentes con algoritmos LALR.

JFLEX

SECCIONES

Reglas lexicograficas

Código de usuario

Opciones y declaraciones

CARACTERÍSTICAS

Permite la integración con CUP.

Tiene una sintaxis cómoda de manipular y fácil de interpretar.

Permite generar analizadores léxicos rápidamente

Soporte completo con caracteres unicode

CONCEPTO

Es un meta-compilador que permite generar rápidamente analizadores léxicos que se integran con Java

Ahorra de manera abismal la generación de código al momento de desarrollar un compilador.
Se puede integrar cada uno de los procesos de los metacompiladores
La integración permite obtener un compilador mucha más complejo.

4.5. IMPLEMENTACIÓN DE ANALIZADOR LÉXICO SINTÁCTICO. Bibliografía: https://www.fdi.ucm.es/profesor/fpeinado/courses/compiling/Tema1.6-Implementacion.pdf

Primero se realiza el análisis léxico y luego el sintáctico, pero en la práctica ambos se van realizando en la misma pasada.
ANALIZADOR SINTÁCTICO

Se usa la definición sintáctica directamente para implementarlo (no hace falta llegar a diseñar el autómata a pila que reconoce el lenguaje)

La implementación es manual, usando la gramática incontextual y las restricciones contextuales sólo como “guías”

Dada la secuencia de componentes léxicos de entrada decide si el programa que representa es válido o no en el lenguaje propuesto.

ANALIZADOR LÉXICO

Solapar todos los AFNDs en un solo AFND.

Mínimo número de estados intermedios que se puedan.

Uno o varios estados finales por cada categoría léxica

Un único estado inicial para todo.

Añadir otra ER con lo necesario para tratar de separadores, comentarios, reconocer el final del fichero, etc.

Considerar las ER's de las definiciones regulares de cada categoría léxica.

Se usa la definición léxica (expresiones regulares) para diseñar un reconocedor del lenguaje (autómata finito determinista)

Convierte el programa de entrada en una secuencia de componentes léxicos (ocurrencias de categorías léxicas)

Cada componente léxico lleva el identificador de su categoría léxica y un conjunto de atributos léxicos

4.2. CONSIDERACIONES SOBRE LA TABLA DE SÍMBOLOS Bibliografía: http://www.lcc.uma.es/~galvez/ftp/tci/tictema5.pdf

La tabla de simbolos contiene unformacion util
Para compilar

No existe en tiempo de ejecución

Existe en tiempo de compilación

El optimizador de código no necesita hace uso de la dirección de memoria.
El generador de código intermedio usa las direcciones de memoria asociada a cada identificador.
El analizador semántico efectúa las comprobaciones sensibles al contexto.
Conforme aparecen nuevas declaraciones de identificadores
Insertará nuevas entradas en la tabla de símbolos

Evitará la existencia de entradas repetidas

Puede iniciar con cierta información útil
Palabras reservadas
Funciones de librerías

EXP, LOG, etc

Constantes

PI, E

4.1. INFORMACIÓN SOBRE LOS IDENTIFICADORES DE USUARIOS Bibliografía: https://sites.google.com/site/clsecompiladores/home/project-updates

En esta información puede incluir:
Tipos de parámetros formales

Almacena los tipos de los parámetros formales de una función o procedimiento

Número de dimensiones

Almacena las dimensiones de un array

Valor de elemento

Permite gestionar las variables fácilmente

Dirección de memoria

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

Tipo de elemento

Tipo de dato al que pertenece cierto elemento

Nombre del elemento

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

La información dependerá del traductor desarrollado
Información que el desarrollador decida almacenar en las tablas.