Anlisis Lxico M C Juan Carlos Olivares Rojas

  • Slides: 63
Download presentation
Análisis Léxico M. C. Juan Carlos Olivares Rojas

Análisis Léxico M. C. Juan Carlos Olivares Rojas

Agenda • Introducción a los Autómatas expresiones regulares. finitos y • Analizador de léxico.

Agenda • Introducción a los Autómatas expresiones regulares. finitos y • Analizador de léxico. • Manejo de localidades temporales de memoria (buffers). • Creación de tablas de símbolos. • Manejo de errores léxicos. • Generadores de código léxico: Lexy Flex.

Ensamblado en Java • ¿Qué es un autómata? Es un modelo matemático que sirve

Ensamblado en Java • ¿Qué es un autómata? Es un modelo matemático que sirve para determinar si una cadena pertenece a un lenguaje no. • A = (Q, Σ, &, F) donde • • Q = conjunto de estados Σ= alfabeto de entrada & = funciones de transición F = conjunto de estados de aceptación

AFD • La característica que tienen los Autómatas Finitos Deterministas (AFD) es que solo

AFD • La característica que tienen los Autómatas Finitos Deterministas (AFD) es que solo existe una función de transición definida para un símbolo de entrada. Esto elimina ambigüedades • Una expresión regular es una forma abreviada de representar lenguajes: • a Representa el lenguaje de las letras a • a* Representa el lenguaje que tiene 0 hasta n a’s

AFD • El principio de diseño de un Lenguaje de Programación radica en la

AFD • El principio de diseño de un Lenguaje de Programación radica en la utilización de un autómata genérico y de ese autómata partir de varios subautómatas. • Los autómatas suelen representarse con expresiones regulares. Ejemplo: • Identificador: letra (letra | digito | gb)*

AFD • Generar la expresión regular para identificar URL válidas. • Ejemplo: • http:

AFD • Generar la expresión regular para identificar URL válidas. • Ejemplo: • http: //www. patito. com/recurso. php? id=0 • ftp: //ftp. sindominio. com/pub/archivo • file: //casa. decera. com/recurso+20+dos • ¿Cómo queda la expresión regular?

AFD • Dada la siguiente expresión regular como queda el autómata que lo representa:

AFD • Dada la siguiente expresión regular como queda el autómata que lo representa: • Alpha (alpha | num | sim)* • Donde alpha es un carácter de a. . Z • Num es un dígito de 0 a 9 • Sim es uno de los siguientes símbolos

AFD • ¿Cómo se programa un autómata? • Los autómatas tienen su representación en

AFD • ¿Cómo se programa un autómata? • Los autómatas tienen su representación en forma de grafos que a su vez se representan en forma de tablas de transiciones, se cuenta con un estado inicial y una función de siguiente estado. Al terminar de leer la cadena se verifica si el estado es algún estado de aceptación.

Práctica 5 • Programar un autómata para reconocer la URLs que son válidas. •

Práctica 5 • Programar un autómata para reconocer la URLs que son válidas. • Se deberá tener una matriz de transiciones y una función de estado siguiente. No se permitirán validaciones por otros medios. • Se deberán leer cadenas contenidas en un archivo de texto plano y deberá devolver que cadenas si son URLs

Expresiones Regulares y Gramáticas • ¿Qué similitudes existen entre las expresiones regulares y gramáticas?

Expresiones Regulares y Gramáticas • ¿Qué similitudes existen entre las expresiones regulares y gramáticas? • Una gramática sirve para generar cadenas de un determinado lenguaje pero también sirve para generarla. • Existente una relación uno a uno entre Lenguajes, Autómatas, Expresiones regulares y gramáticas.

Analizador Léxico • El análisis léxico es la primera fase de la compilación. •

Analizador Léxico • El análisis léxico es la primera fase de la compilación. • Un analizador léxico: • Lee caracteres de entrada y generar como salida una secuencia de componentes léxicos (generalmente representados por números).

Analizador Léxico • Un analizador léxico: • Elimina espacios en blanco (considerados por el

Analizador Léxico • Un analizador léxico: • Elimina espacios en blanco (considerados por el lenguaje como tabuladores, etc. ) • Eliminar comentarios • Proporcionar información acerca de errores léxicos (caracteres inexistentes o tokens inexistentes)

Tabla de Símbolos • La tabla de símbolos se compone de un lexema y

Tabla de Símbolos • La tabla de símbolos se compone de un lexema y un identificador del componente léxico. • Los componentes léxicos se conforman de un patrón (expresión regular que lo valida). • El patrón se codifica como un autómata.

Tokens, Lexemas y Patrones

Tokens, Lexemas y Patrones

Análisis Léxico • También recibe el análisis lineal, se llama léxico o exploración. •

Análisis Léxico • También recibe el análisis lineal, se llama léxico o exploración. • Ejemplo: • Posicion: = inicial + velocidad * 60 • Posicion: identificador • : = símbolo de asignación • Inicial: identificador

Análisis Léxico • • +: signo de suma Velocidad: identificador *: signo de multiplicación

Análisis Léxico • • +: signo de suma Velocidad: identificador *: signo de multiplicación 60: numero • Las palabras clave de muchos lenguajes son lexemas tal cual. Por ejemplo para reconocer un token if, se necesita de un patrón “if”.

Analizador Léxico • La tabla de símbolo debe insertar y buscar componentes léxicos (aunque

Analizador Léxico • La tabla de símbolo debe insertar y buscar componentes léxicos (aunque en el análisis léxico sólo se inserten, se debe recordar que la tabla de símbolos es utilizada por el analizador sintáctico y por otras fases del proceso de traducción. • Los componentes léxicos se tratan como terminales de la gramática del lenguaje fuente. Existen muchas herramientas para utilizar expresiones regulares.

Definiciones Regulares • Dan nombres a las expresiones regulares. Permiten referenciar las expresiones regulares

Definiciones Regulares • Dan nombres a las expresiones regulares. Permiten referenciar las expresiones regulares recursivamente • • • Ejemplo: Digito 1|2|3|4|5|6|7|8|9|0 Entero dígito+ Decimal dígito+ |. dígito+ E (+ |- | ε) dígito+ Real entero (decimal | ε)

Abreviaturas • * cero o más casos • + uno o más casos •

Abreviaturas • * cero o más casos • + uno o más casos • ? 0 ó 1 vez (opcional) • [a-z. A-Z] mayúsculas y minúsculas • [0 -9] dígitos

Definiciones Regulares • Digito [0 -9] • Entero digito+ • Decimal . digito+exponente? •

Definiciones Regulares • Digito [0 -9] • Entero digito+ • Decimal . digito+exponente? • Exponente (E | e) (+|-)? digito+ • Real entero decimal?

Analizador Léxico

Analizador Léxico

Examen 2 • Entrega: viernes 9 • Análisis de Requerimientos dado un archivo *.

Examen 2 • Entrega: viernes 9 • Análisis de Requerimientos dado un archivo *. class correcto, encontrar los mnemónicos que tiene disponible el ensamblador (alias javap –c Archivo) • Complejidad al detectar el encabezado (formato *. class) y después la complejidad del código

Examen 2

Examen 2

Examen • Se puede observar que de este pequeño hola mundo se tienen dos

Examen • Se puede observar que de este pequeño hola mundo se tienen dos métodos. • El primero de ellos de 5 bytes, revisando sus mnemónicos se puede observar que su códigos de operación en byte es: • 0 x 2 a • 0 xb 7 0 x 00 0 x 01 • b 1

 • • • BB FE AF EA 77 03 05 2 a b

• • • BB FE AF EA 77 03 05 2 a b 7 00 01 b 1 12 Formato valido aload_o Invokespecial 0 1 Return

Examen 2

Examen 2

Examen 2 • Esto se puede buscar en el archivo *. class. • El

Examen 2 • Esto se puede buscar en el archivo *. class. • El detalle radica en que el código no viene sólo sino en una estructura Attribute denominada code_attribute (ver unidad pasada). Nótese por ejemplo que un byte antes del código marcado nos indica el tamaño del código de ese método.

Examen 2 • Reformulación del proyecto. Dado nuestro propio formato comenzará de la siguiente

Examen 2 • Reformulación del proyecto. Dado nuestro propio formato comenzará de la siguiente forma: 4 bytes de número mágico: BB FE AF EA, 2 bytes para indicar la versión y subversión del compilado, 2 bytes para indicar el tamaño del código, instrucciones del ensamblador de java y un byte al final como código de comprobación (tamaño total del archivo % 255).

Examen 2 • Se deberá validar que sus archivos *. obj tengan este formato.

Examen 2 • Se deberá validar que sus archivos *. obj tengan este formato. Se hará la impresión de los mnemónicos contenidos (puede ser modo texto o visual). • Se ocupa conocer mnemónicos el tamaño de los • ¿Para el viernes autómata o examen 2? Por lo tanto queda para el lunes.

Mnemónicos en Java • astore <varnum>: saca de la pila una referencia. • baload:

Mnemónicos en Java • astore <varnum>: saca de la pila una referencia. • baload: recupera un byte de un arreglo de bytes y lo convierte a un entero que se coloca en la pila de operandos. • bipush <n>: coloca un entero de 8 bits en la pila (lo convierte a un entero de 32 bits)

Mnemónicos en Java • d 2 f: saca de la pila un flotante de

Mnemónicos en Java • d 2 f: saca de la pila un flotante de doble presición para convertile a un flotante sencillo y volverlo a colocar en la pila (esta operación puede causar pérdida de precisión). • dadd: toma dos dobles de la pila, los suma y coloca el resultado en la pila. • dup_x 1: duplica el valor de la cima de la pila y la coloca una posición debajo.

Mnemónicos en Java • fneg: niega un flotante. • goto <label>: brinca a la

Mnemónicos en Java • fneg: niega un flotante. • goto <label>: brinca a la dirección especificada por la etiqueta (cadena de texto), label ocupa dos bytes por lo que esta instrucción es de 3 bytes. • iand: realiza una operación lógica “Y” entre dos enteros en la cima de la pila, el resultado lo deja en la pila.

Mnemónicos en Java • ifeq <label>: realiza un pop en la pila para comparar

Mnemónicos en Java • ifeq <label>: realiza un pop en la pila para comparar si el valor apuntado por etiqueta es igual al de la pila. Esta es una instrucción de 3 bytes • istore <varnum>: saca un valor de la pila y lo almacena en una variable local. • jsr_w <label>: salta a una subrutina, label hace referencia a un valor doble, por lo que esta instrucción es de 5 bytes.

Manejo de localidades temporales de memoria (buffers) • La forma más fácil de realizar

Manejo de localidades temporales de memoria (buffers) • La forma más fácil de realizar el escanner de un código es a través de carácter por carácter pero esto es sumamente ineficiente. • La forma más eficiente es realizar una copia a la memoria de todo el código fuente.

Manejo de Buffers • La desventaja de este último enfoque es que la gran

Manejo de Buffers • La desventaja de este último enfoque es que la gran mayoría de las ocasiones es impráctico por las dimensiones de los programas. Para solucionar este problema se sugiere utilizar buffers. • Existen muchas formas de dividir el trabajo, pero siempre se deberá llevar dos punteros, uno al carácter actual y otro al inicial del lexema.

Creación de Tabla de Símbolos • En general el proceso de análisis léxico puede

Creación de Tabla de Símbolos • En general el proceso de análisis léxico puede describirse simplemente como el reconocimiento de caracteres de un lenguaje para generar una tabla de símbolos. • El primer paso consiste en crear un escáner, el cual se encarga de verificar que no existan caracteres no presentes en el lenguaje.

Tabla de Símbolos • La tabla de símbolos va a guardar cada palabra analizada,

Tabla de Símbolos • La tabla de símbolos va a guardar cada palabra analizada, la va identificar como un lexema y le va asociar un identificador numérico para posteriormente utilizarlo. • La tabla de símbolos debe estar en memoria para realizar un análisis rápido.

Errores Léxicos • Son pocos los errores que se pueden detectar al hacer análisis

Errores Léxicos • Son pocos los errores que se pueden detectar al hacer análisis léxico • Por ejemplo: – fi (a == f(x)) • ¿Es error léxico? No, es error sintáctico • Puede existir algún error si ninguno de los patrones no concuerda con el prefijo de entrada.

Técnicas de Recuperación de Errores • Borrar un carácter extraño • Insertar un carácter

Técnicas de Recuperación de Errores • Borrar un carácter extraño • Insertar un carácter que falta • Reemplazar un carácter incorrecto por otro correcto • Intercambiar dos caracteres adyacentes

Técnicas para realizar analizadores léxicos • Utilizar un analizador léxico como LEX. El generador

Técnicas para realizar analizadores léxicos • Utilizar un analizador léxico como LEX. El generador se encarga de manejar buffers • Escribir el analizador en un lenguaje de alto nivel haciendo uso de la E/S del lenguaje • Escribir el lenguaje ensamblador y manejar explícitamente la E/S

Patrones en Java • El lenguaje Java es un lenguaje de alto nivel de

Patrones en Java • El lenguaje Java es un lenguaje de alto nivel de propósito general que cuenta entre sus cosas con un motor para reconocimento de patrones de texto. • El paquete javax. util. regex. *; el cual dispone de dos clases: Pattern y Matcher.

Patrones en Java • La clase Pattern se utiliza para especificar los patrones y

Patrones en Java • La clase Pattern se utiliza para especificar los patrones y la clase Matcher se utiliza para procesar las cadenas y ver si coinciden con el patrón. • El método compile de la clase Pattern permite especificar la expresión regular utilizando prácticamente la misma simbología de comodines de expresiones regulares.

Patrones en Java • Un objeto de la clase Matcher se crea a través

Patrones en Java • Un objeto de la clase Matcher se crea a través del método matcher() del objeto instanciado de la clase Pattern. • La clase matcher tiene los siguientes métodos: matches para una coincidencia exacta, looking. At cuando se encuentra el patrón en parte de la cadena, find permite buscar subcadenas que coincidan con el patrón.

Patrones en Java • El método find permite utilizar los métodos start y end

Patrones en Java • El método find permite utilizar los métodos start y end para encontrar la primera y última coincidencia. • El método replace. All(), permite cambiar una subcadena por otra.

Patrones en Java import java. util. regex. *; public class Validar. Email { public

Patrones en Java import java. util. regex. *; public class Validar. Email { public static void main(String[] args) throws Exception { String cadena = “jcolivar@hotmail. com"; Pattern p = Pattern. compile("\w\+@\w\. \w"); Matcher m = p. matcher(input); if (m. find()) System. err. println("Las direcciones email no empiezan por punto o @"); } }

Generadores de Código Léxico • FLEX es la versión de software libre del popular

Generadores de Código Léxico • FLEX es la versión de software libre del popular generador de analizadores léxicos LEX para sistemas *NIX, genera código C aunque existen otras herramientas que generan código en otros lenguajes (Jflex para Java) • Analizador. lex flex lex. yy. c Programa ejecutable analizador • $gcc lex. yy. c –o analizador –l fl gcc

Estructura Lex %{ Definiciones globales ‘C’ }% Definiciones flex %% Acciones %% Código ‘C’

Estructura Lex %{ Definiciones globales ‘C’ }% Definiciones flex %% Acciones %% Código ‘C’ auxiliar

Definiciones de Expresiones Regulares • %% Separadores de secciones • Def expresión • Acciones

Definiciones de Expresiones Regulares • %% Separadores de secciones • Def expresión • Acciones • {def} {código ‘C’ asociado} • “@”{código ‘C’ asociado}

Ejemplo Scanner Flotante %{ #include <stdio. h> int ocurrencias; %}� digito [0 -9] punto

Ejemplo Scanner Flotante %{ #include <stdio. h> int ocurrencias; %}� digito [0 -9] punto [. ] exp [e. E] signo[+-] digitos {digito}+

Ejemplo de Scanner Flotante decimal {punto} {digitos}({exp}{signo}{digitos})? flotante {digitos}{decimal}? %% {flotante} { printf(“flotante encontradon”);

Ejemplo de Scanner Flotante decimal {punto} {digitos}({exp}{signo}{digitos})? flotante {digitos}{decimal}? %% {flotante} { printf(“flotante encontradon”); ocurrenicas++; } “@” { printf(“Arroban”); }. { printf(“Inválido: %sn”, yytext); } %%

Ejemplo de Scanner Flotante int main(int argc, char* argv[]) { FILE *f; F =

Ejemplo de Scanner Flotante int main(int argc, char* argv[]) { FILE *f; F = fopen(argv[1], “r”); yyin= f; while(yylex()); printf(“%dflotantes encontradosn”, ocurrencias); fclose(f); return 0; � }

JFlex • Es otra forma de incluir expresiones regulares para crear scanners pero ahora

JFlex • Es otra forma de incluir expresiones regulares para crear scanners pero ahora con lenguaje java. • Se tiene que manejar una sintaxis muy similar a lex con sus respectivas variantes. • Las expresiones regulares se definen dentro de un archivo con extension. lex o jflex (realmente la extensión no importa). A continuación se muestra un ejemplo.

JFlex /*Aqui van todas las bibliotecas*/ import javax. swing. JOption. Pane; %% /*Definiciones regulares

JFlex /*Aqui van todas las bibliotecas*/ import javax. swing. JOption. Pane; %% /*Definiciones regulares configuracion*/ %class Flotante %unicode %full %int y parametros de

JFlex %line %column %{ /*Codigo Java genérico*/ int ocurrencias; public int get. Ocurrencias(){ return

JFlex %line %column %{ /*Codigo Java genérico*/ int ocurrencias; public int get. Ocurrencias(){ return ocurrencias; }

%} JFlex /*Definiciones regulares*/ digito=[: digit: ] blancos=[nrtfb] punto =[. ] exp=[e. E] signo=[+-]

%} JFlex /*Definiciones regulares*/ digito=[: digit: ] blancos=[nrtfb] punto =[. ] exp=[e. E] signo=[+-] digitos={digito}+ decimal={punto}{digitos}(("e"|"E"){signo}{digitos}) ?

JFlex flotante={signo}? {digitos}{decimal}? /*Sección de acciones*/ %% /*Palabras reservadas */ <YYINITIAL> "break" JOption. Pane.

JFlex flotante={signo}? {digitos}{decimal}? /*Sección de acciones*/ %% /*Palabras reservadas */ <YYINITIAL> "break" JOption. Pane. show. Message. Dialog(null, encontro un break"); } <YYINITIAL> { {flotante} { "Se

JFlex { JOption. Pane. show. Message. Dialog(null, encontro un flotante: "+ yytext()); ocurrencias++; }

JFlex { JOption. Pane. show. Message. Dialog(null, encontro un flotante: "+ yytext()); ocurrencias++; } "Se {blancos} {/*se ignora*/}. { /*ignoramos el token*/ } } • //Falta construir la clase principal o bien incrustarla dentro del código main

JFlex import java. io. *; public class Scanner. Flotante { public static void main(String[]

JFlex import java. io. *; public class Scanner. Flotante { public static void main(String[] args) { try { File. Reader arch = new File. Reader(args[0]); Flotante f = new Flotante(arch); f. yylex(); System. out. print("Numero de flotantes encontrados: " + f. get. Ocurrencias()); } catch (Exception e) {

JFlex e. print. Stack. Trace(); } } } • La invocación de Jflex se

JFlex e. print. Stack. Trace(); } } } • La invocación de Jflex se realiza jflex archivo. lex, sino se pasan argumentos se abre una interface gráfica. • La clase generada se llama Flotante. java (si no se expecifica se crea una clase Yylex. java)

JFlex • Al igual que lex, se puede complementar el código con algún otro

JFlex • Al igual que lex, se puede complementar el código con algún otro código de Java, por ejemplo APIs para el manejo de gráficos. • Jflex genera autómatas finitos no determinista que luego convierte a autómatas finitos determinista para posteriormente minimizar su estado.

Referencias • Aho, Sethi, Ullman. Compiladores Principios, técnicas y herramientas Ed. Addison Wesley. •

Referencias • Aho, Sethi, Ullman. Compiladores Principios, técnicas y herramientas Ed. Addison Wesley. • Beck, . Software de Sistemas, Introducción a la programación de Sistemas Ed. Addison-Wesley Iberoamericana. • Kenneth C. Louden. Construcción de compiladores Principios y práctica. Ed. Thomson.

Referencias • Java Virtual Machine Specification

Referencias • Java Virtual Machine Specification

¿Preguntas?

¿Preguntas?