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.