Subido por Luis Guillermo córdoba

herramienta-lex-y-yacc

Anuncio
Herramienta lex y yacc
Compiladores
Instituto Politécnico Nacional (IPN)
16 pag.
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
INSTITUTO POLITÉCNICO NACIONAL
ESCUELA SUPERIOR DE INGENIERIA
MECÁNICA Y
ELECTRICA
UNIDAD CULHUACÁN
LA HERRAMIENTA LEX
ASIGNATURA: COMPILADORES
PROFESORA: RESENDIZ COLÍN PILAR.
GRUPO: 5CV24
EQUIPO: 5
INTEGRANTES: NºLISTA – NOMBRE
1
ALVAREZ RODEA CARLOS GERARDO.
3
CARRASCO VAZQUEZ LEONARDO.
11
IRIARTE HERNANDEZ JESUS EMMANUEL
16
MERINO MARTINEZ ROBERTO EDUARDO
26
VERA OROZCO MARÍA DE LOS ÁNGELES
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Índice
• Introducción
• La herramienta Lex
• Esquema de una fuente en Lex
• Zona de definiciones
• Zona de reglas
• Zona de rutinas del usuario
• Archivo de salida (lex.yy.c)
• Copilar una fuente de Lex
• Opciones estándar
• Depuración de una fuente de Lex
• Prueba rápida de una fuente
• Expresiones regulares en Lex
• Caracteres
• Clases de caracteres
• Reconocer cualquier caracter
• Unión
• Clausuras
• Repetición acotada
• Opción
• Paréntesis
1
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Introducción
La herramienta Lex es un generador de analizadores léxicos utilizado en el campo
de la informática. También se conoce como un "analizador de escáner" o "analizador
léxico". Lex se utiliza comúnmente para procesar y analizar texto estructurado en
lenguajes de programación, sistemas de compilación y otros entornos relacionados.
El propósito principal de Lex es reconocer y dividir el texto de entrada en unidades
léxicas más pequeñas llamadas "tokens". Estos tokens pueden representar
palabras clave, identificadores, números, símbolos y otros elementos del lenguaje
de programación o del sistema que se está analizando. Lex utiliza un enfoque
basado en reglas para generar analizadores léxicos. El usuario define un conjunto
de reglas en un archivo de especificación de Lex que describe cómo se deben
reconocer los tokens en el texto de entrada.
Cada regla consta de un patrón de búsqueda y una acción asociada. Cuando Lex
encuentra una coincidencia entre un patrón y una parte del texto de entrada, ejecuta
la acción correspondiente, que puede ser una función o un fragmento de código.
Una vez que se ha generado el analizador léxico con Lex, se puede utilizar en
conjunción con otros componentes del sistema para realizar tareas más complejas,
como el análisis sintáctico o la generación de código. Lex se ha utilizado
ampliamente en la implementación de compiladores, intérpretes y otras
herramientas de procesamiento de lenguajes de programación.
En resumen, Lex es una herramienta eficiente y flexible que simplifica el proceso de
análisis léxico en informática. Proporciona una forma estructurada de definir y
reconocer tokens en el texto de entrada, lo que facilita el desarrollo de sistemas de
procesamiento de lenguajes de programación y otros entornos relacionados.
Herramienta Lex
Lex es una herramienta que traduce la especificación de un analizador léxico a un
programa escrito en C que lo implementa.
Para especificarlo usaremos en esencia, expresiones regulares a las que se puede
asociar acciones escritas en C. Cada vez que el analizador encuentra en la cadena
2
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
de entrada un prefijo que encaja con una de las expresiones regulares
especificadas, ejecutará la acción que le hallamos asociado.
El principal problema que se le suele achacar a Lex es el hecho de que genera
programas poco eficientes, por lo que su aplicación en entornos de producción
industrial se ve claramente menguada.
En la actualidad, se ha desarrollado una versión que genera un código final más
eficiente, pero mantiene una completa compatibilidad con la herramienta original.
Se trata de Flex, un producto GNU de dominio público del que existen versiones
para UNIX y MS-DOS.
Esquema de una fuente en Lex
%{
// Declaraciones del encabezado, incluyendo bibliotecas y definiciones
#include <stdio.h>
%}
// Reglas
%%
patrón1 acción1
patrón2 acción2
// ...
// Código C adicional
%%
// Función principal
int main() {
// Inicialización y llamada al analizador léxico generado por Lex
yylex();
// Código adicional, si es necesario
return 0;
}
Declaraciones del encabezado (%{ y %}): Esta sección contiene las declaraciones
del encabezado, que incluyen bibliotecas y definiciones que se utilizarán en el
código C generado por Lex.
3
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Reglas (%%): Esta sección contiene las reglas del analizador léxico. Cada regla
tiene un patrón y una acción asociada. Cuando el analizador léxico encuentra un
patrón que coincide con la entrada, ejecuta la acción correspondiente.
Código C adicional: Esta sección contiene cualquier código C adicional que
desees incluir en el programa. Puede contener funciones o variables que se
utilizarán en las acciones de las reglas.
Función principal: La función main() inicializa el analizador léxico y llama a la
función yylex(), que es generada automáticamente por Lex. Puedes incluir código
adicional después de la llamada a yylex() si es necesario.
Reglas:
Reconocer números enteros:
%%
[0-9]+
{ printf("Entero: %s\n", yytext); }
Reconocer identificadores (variables):
%%
[a-zA-Z_][a-zA-Z0-9_]* { printf("Identificador: %s\n", yytext); }
Reconocer palabras clave:
%%
if
else
{ printf("Palabra clave IF\n"); }
{ printf("Palabra clave ELSE\n"); }
Ignorar espacios en blanco y saltos de línea:
%%
[ \t\n]
; // Ignorar espacios en blanco y saltos de línea
4
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Manejar errores:
%%
.
{ printf("Carácter no reconocido: %s\n", yytext); }
Estos son ejemplos muy simples y puedes expandirlos según las necesidades de
tu lenguaje o aplicación específica. Cada regla consta de un patrón y una acción.
Cuando la entrada coincide con el patrón, se ejecuta la acción asociada. Puedes
tener tantas reglas como sea necesario para manejar diferentes partes de tu
lenguaje fuente.
Archivo de salida (lex.yy.c)
Generalmente está asociado con el uso de herramientas como Flex (Fast Lexical
Analyzer Generator). lex.yy.c es el nombre predeterminado del archivo de salida
generado por Flex cuando se crea un analizador léxico.
Cuando utilizas Flex para generar un analizador léxico, creas un archivo de
entrada con extensión .l que contiene reglas de análisis léxico. Luego, ejecutas
Flex en este archivo de entrada para generar el código fuente del analizador léxico
en C, y el resultado se guarda en un archivo llamado lex.yy.c por defecto. Este
archivo contiene el código C para el analizador léxico.
Aquí hay un ejemplo básico del proceso:
Crear un archivo de entrada Flex (por ejemplo, mi_analizador_lexico.l):
%{
#include <stdio.h>
%}
%%
5
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
palabra_clave
printf|scanf
identificador
[a-zA-Z][a-zA-Z0-9]*
numero
[0-9]+
%%
int main() {
yylex();
return 0;
}
Ejecutar Flex:
flex mi_analizador_lexico.l
Esto generará el archivo lex.yy.c.
Compilar el código C generado:
gcc lex.yy.c -o mi_analizador_lexico
Esto compilará el código generado por Flex y creará un ejecutable llamado
mi_analizador_lexico.
Ejecutar el analizador léxico:
./mi_analizador_lexico
Estos pasos son un ejemplo básico, y el contenido real del archivo .l y cómo se
utiliza el analizador léxico dependerá de tus necesidades específicas. Ten en
cuenta que el nombre del archivo de salida (lex.yy.c) y del ejecutable (a.out por
defecto) pueden variar según la configuración o opciones utilizadas.
6
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Copilar una fuente de Lex
Escribe el Código en Lex:
Utiliza un editor de texto para escribir tu código en Lex. Los archivos suelen tener
la extensión .l o .lex. Por ejemplo, si estás trabajando en un archivo llamado
mi_analizador.lex, puedes usar un editor de texto para escribir el código fuente.
Ejecuta el Compilador Lex:
Utiliza el compilador de Lex para generar el código en C correspondiente. El
comando puede variar según tu sistema operativo. En muchos sistemas basados
en Unix/Linux, puedes usar el comando lex. Por ejemplo:
lex mi_analizador.lex
Compila el Código Generado:
El paso anterior generará un archivo en C, generalmente con el nombre lex.yy.c.
Ahora necesitas compilar ese código C. Puedes usar un compilador como gcc.
Por ejemplo:
gcc lex.yy.c -o mi_analizador -ll
En algunos sistemas, el flag -ll es necesario para vincular la biblioteca de Lex.
Ejecuta el Programa Compilado:
Una vez que hayas compilado tu programa, puedes ejecutarlo:
./mi_analizador
Estos son pasos generales y pueden variar según el sistema operativo y las
herramientas específicas que estés utilizando. Asegúrate de consultar la
7
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
documentación de Lex y las herramientas asociadas en tu entorno de desarrollo
específico para obtener detalles precisos.
Opciones estándar
Generar un Archivo de Salida Específico:
Puedes utilizar la opción -o para especificar el nombre del archivo de salida
generado por Lex.
Por ejemplo:
lex -o mi_analizador.c mi_analizador.lex
Mostrar Información Detallada:
La opción -t o --t suele utilizarse para que Lex muestre información detallada sobre
el análisis léxico durante el proceso de generación. Esto puede ser útil para
depurar tu código en Lex.
lex -t mi_analizador.lex
No Generar Funciones de Entrada/Salida por Defecto:
A veces, puede que no desees que Lex genere sus funciones de entrada/salida
estándar (yyin, yyout). Puedes usar la opción -p para especificar un prefijo
personalizado para estas funciones. Si no quieres que se generen, puedes usar P seguido de un nombre no existente para deshabilitarlas.
lex -Pnoyyin mi_analizador.lex
8
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Generar un Analizador Silencioso:
Puedes usar la opción -q para hacer que Lex genere un analizador sin imprimir
mensajes sobre el análisis léxico.
lex -q mi_analizador.lex
Depuración de una fuente de Lex
Mensajes de Depuración:
Agrega mensajes de depuración en tu código para imprimir información relevante
durante la ejecución. Puedes usar la función printf en C para imprimir mensajes
en la salida estándar. Esto puede ayudarte a entender en qué parte del código se
produce un problema.
Habilita la Impresión de Información Detallada:
Usa la opción -t al ejecutar Lex para que genere información detallada sobre el
análisis léxico. Esto puede ayudarte a identificar problemas relacionados con el
reconocimiento de tokens.
lex -t mi_analizador.lex
Visualización de Automatas:
Algunas implementaciones de Lex te permiten generar diagramas de estados
finitos para visualizar el autómata finito que representa tu analizador léxico. Esto
9
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
puede ser útil para comprender el flujo del programa y detectar posibles
problemas.
Revisa las Expresiones Regulares:
Asegúrate de que las expresiones regulares utilizadas para definir patrones de
tokens sean correctas. Verifica si alguna expresión regular está generando
conflictos o no está coincidiendo correctamente con la entrada.
Revisa las Acciones asociadas a los Patrones:
Verifica las acciones asociadas a tus reglas. Asegúrate de que estén
correctamente escritas y que estén manejando adecuadamente los datos. Errores
en las acciones pueden causar comportamientos inesperados.
Manejo de Errores:
Implementa un manejo adecuado de errores en tu código. Asegúrate de que tu
programa pueda manejar entradas inesperadas o incorrectas y proporcionar
mensajes de error claros.
Divide y Conquista:
Si tu programa es grande, trata de dividirlo en partes más pequeñas y verifica cada
parte por separado. Esto puede ayudarte a identificar rápidamente la sección del
código que está causando el problema.
10
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Utiliza Herramientas de Depuración:
Si estás trabajando en un entorno de desarrollo que admite la depuración de
programas en C, aprovecha las herramientas de depuración disponibles, como
gdb. Esto te permitirá realizar un seguimiento paso a paso del programa y
examinar variables en tiempo de ejecución.
Al seguir estos consejos y realizar un enfoque sistemático para la depuración,
deberías poder identificar y corregir los problemas en tu programa Lex de manera
efectiva.
Prueba rápida de una fuente Lex
Lexicografía: Es la disciplina que se ocupa de la elaboración de diccionarios, la
descripción de las palabras y su clasificación de acuerdo con criterios como el
significado, la etimología, la pronunciación, etc.
Léxico: Es el conjunto de palabras que pertenecen a una lengua o que se utilizan
en un área específica. En términos más simples, el léxico se refiere al vocabulario
de una lengua.
Ejemplo:
Supongamos que tenemos el siguiente código fuente en un lenguaje de
programación imaginario:
# Código fuente de ejemplo
suma = 10 + 20 * 5
resultado = suma / 2
11
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
La prueba léxica para este código podría generar una secuencia de tokens, donde
cada token representa una unidad léxica reconocida por el analizador léxico. Aquí
hay una posible salida:
<Token: IDENTIFICADOR, Lexema: 'suma'>
<Token: OPERADOR_ASIGNACION, Lexema: '='>
<Token: ENTERO, Lexema: '10'>
<Token: OPERADOR_SUMA, Lexema: '+'>
<Token: ENTERO, Lexema: '20'>
<Token: OPERADOR_MULTIPLICACION, Lexema: '*'>
<Token: ENTERO, Lexema: '5'>
<Token: FIN_DE_LINEA, Lexema: '\n'>
<Token: IDENTIFICADOR, Lexema: 'resultado'>
<Token: OPERADOR_ASIGNACION, Lexema: '='>
<Token: IDENTIFICADOR, Lexema: 'suma'>
<Token: OPERADOR_DIVISION, Lexema: '/'>
<Token: ENTERO, Lexema: '2'>
<Token: FIN_DE_LINEA, Lexema: '\n'>
En este ejemplo:
IDENTIFICADOR: Representa nombres de variables como "suma" y "resultado".
OPERADOR_ASIGNACION: Indica la asignación de un valor a una variable.
ENTERO: Representa números enteros como '10', '20', y '5'.
12
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
OPERADOR_SUMA, OPERADOR_MULTIPLICACION, OPERADOR_DIVISION:
Representan operadores aritméticos.
FIN_DE_LINEA: Indica el final de una línea en el código fuente.
Esta sería una salida simplificada; en un compilador real, también podrían
aparecer otros tokens, como tokens de palabras clave, operadores lógicos,
delimitadores, etc. La idea es que el analizador léxico descomponga el código
fuente en unidades léxicas significativas para que el compilador pueda procesarlo
de manera más estructurada.
Expresiones regulares en Lex
Supongamos que estamos escribiendo un analizador léxico para un lenguaje
simple que incluye números enteros, identificadores y operadores aritméticos.
Aquí estaría un fragmento de código Lex con expresiones regulares:
%{
// Encabezado: Código en C que se copiará directamente al analizador léxico
generado
#include <stdio.h>
%}
// Definición de tokens y expresiones regulares
%%
[0-9]+
{ printf("TOKEN_ENTERO: %s\n", yytext); }
[a-zA-Z][a-zA-Z0-9]* { printf("TOKEN_IDENTIFICADOR: %s\n", yytext); }
"+"
{ printf("TOKEN_SUMA\n"); }
"-"
{ printf("TOKEN_RESTA\n"); }
"*"
{ printf("TOKEN_MULTIPLICACION\n"); }
13
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
"/"
{ printf("TOKEN_DIVISION\n"); }
"="
{ printf("TOKEN_ASIGNACION\n"); }
\n
{ /* Ignorar caracteres de nueva línea */ }
[ \t]
{ /* Ignorar espacios y tabulaciones */ }
.
{ printf("ERROR: Caracter no reconocido\n"); }
%%
// Código adicional después de la sección de reglas
int main() {
yylex(); // Llamada al analizador léxico generado
return 0;
}
En este ejemplo:
[0-9]+: Coincide con uno o más dígitos, representando un número entero.
[a-zA-Z][a-zA-Z0-9]*: Coincide con un identificador, que comienza con una letra y
puede estar seguido por letras o dígitos.
+, -, *, /, =: Coinciden con los operadores aritméticos y de asignación
respectivamente.
\n: Coincide con un salto de línea.
[ \t]: Coincide con espacios y tabulaciones, que se ignorarán.
.: Coincide con cualquier otro carácter, y en este caso, se utiliza para manejar
errores cuando se encuentra un carácter no reconocido.
14
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Estas expresiones regulares son utilizadas por Lex para generar un analizador
léxico que identificará y clasificará los tokens en el código fuente según los
patrones definidos.
Referencias
•
Componentes léxicos, patrones y lexemas
http://cidecame.uaeh.edu.mx/lcc/mapa/PROYECTO/libro32/22_compon
entes_lxicos_patrones_y_lexemas.html
•
•
•
•
Análisis léxico, Universidad Europea de Madrid
https://www.cartagena99.com/recursos/alumnos/apuntes/ININF2_M4_U2_T
1.pdf
Análisis léxico, Procesamiento de lenguajes, Isis
https://lc.fie.umich.mx/~rochoa/MATERIAL_MATERIAS/ANA_LEXICO.pdf
Token. Wikipedia, The Free Encyclopedia.
https://es.wikipedia.org/w/index.php?title=Token_(inform%C3%A1tica)&oldi
d=153790078
Tokens. (s/f). Zator.com.
https://www.zator.com/Cpp/E3_2.htm
15
Document shared on https://www.docsity.com/es/herramienta-lex-y-yacc/10546596/
Downloaded by: luis-guillermo-cordoba ([email protected])
Descargar