You are on page 1of 24

TEMA 4 - ANÁLISIS LEXICOGRÁFICO

4.1 Concepto de analizador léxico El analizador léxico se encarga de obtener y analizar las palabras que componen un texto fuente, distinguiendo sí pertenecen o no a un determinado conjunto, dependiendo de su definición lógica (su descripción). La entrada del analizador léxico podemos definirla como una secuencia de caracteres definidos sobre un alfabeto: ASCII, Unicode, .. etc. La secuencia de caracteres consecutivos obtenidos de la entrada, que pertenecen al léxico del lenguaje se denomina lexema. El analizador léxico divide la secuencia de caracteres obtenidos (lexemas) desde la entrada en conjuntos de palabras con un significado propio (una descripción) Cada uno de los conjuntos de palabras con significado propio que pueden formar parte del lenguaje (conjunto de lexemas) se llama componente léxico, categoría léxica ( tokens en inglés) Texto fuente
Área_triangulo = (base*altura)/2 Ejemplo simple de analizador léxico Identificador (variable) símbolo asignación paréntesis Identificador (variable) operador Identificador (variable) paréntesis operador constante entera

Analizador Léxico

Cada categoría léxica se ajusta a un patrón que describe el conjunto de lexemas que componen dicha categoría. En la siguiente tabla se representan las descripciones de las categorías léxicas, para los lexemas de entrada en el ejemplo anterior. Lexema area := ( base * altura ) / 2 Categoría léxica identificador simb_asignación par_abrir Identificador operador_* identificador par_cerrar operador_/ constante entera Descripción letra seguida de letra o dígito := ( letra seguida de letra o dígito * letra seguida de letra o dígito ) / dígito seguido de dígitos

Tabla con la descripción de las categorías léxicas de un lenguaje de programación

El fin principal de un analizador léxico una vez que se ha reconocido el conjunto de caracteres (lexema) que forman el componente léxico (pieza sintáctica), por medio de un patrón descrito por un mecanismo regular, es entregado al analizador sintáctico. Comp. léxico Prog. fuente Analizador Léxico Obtener Comp. léxico Analizador Sintáctico

1

El analizador léxico que es la primera fase de un procesador de lenguajes, además de leer los caracteres de entrada y elaborar como salida una secuencia de componentes léxicos, que entrega al analizador sintáctico, tiene que asociar unos atributos a esos componentes léxicos. Prog. fuente Analizador Léxico atributos Tabla de símbolos Los atributos son propiedades adicionales que se precisan para la caracterización (documentación) de la pieza sintáctica, así los identificadores necesitan de los lexemas y los literales de valores. Los atributos se guardan en una memoria para su utilización en las siguientes fases del traductor. Existen piezas sintácticas que no necesita atributos así el símbolo de asignación, los paréntesis, los operadores,…etc, lo único que puede decirse de ellos es que se trata de piezas, pero que no llevan propiedades adicionales añadidas. Lexema categoría léxica Area identificador := simb_asigación ( par_abrir base identificador * operador_* altura identificador ) par_cerrar / operador_/ 2 const_entera atributos Nombre (area) --Nombre (base) -Nombre(altura) --Valor (2) descripción letra seguida de letra o dígito := ( letra seguida de letra o dígito * letra seguida de letra o dígito ) / Dígito seguido de dígitos Comp. léxico Obtener Comp. léxico Analizador Sintáctico

Tabla con la representación de atributos

El conjunto de lexemas que pueden formar parte de un componente léxico (token) constituyen un lenguaje, lenguaje que suele ser regular. Un lenguaje regular puede ser especificado por medio de un mecanismo regular: expresión regular, autómata finito (o regular) o por gramática de tipo 3 (o regular). Un patrón es una regla que describe el conjunto de lexemas de un componente léxico. Para describir los patrones se utilizan la notación de expresiones regulares, como descriptores de lenguajes regulares. Lexema categoría léxica atributos area identificador Nombre(area) := simb_asignación -( par_abrir -base identificador Nombre(base) * operador_* -altura identificador Nombre(altura) ) par_cerrar -/ operador_/ -2 const_entera Valor(2) descripción letra seguida de letra o dígito := ( letra seguida de letra o dígito * letra seguida de letra o dígito ) / Dígito seguido de dígito patrón (ER) Letra(letra|dígito)* := ( Letra(letra|dígito)* * Letra(letra|dígito)* ) / Digito+

Tabla con la representación de los patrones que describen las categorías léxicas

2

En el análisis de un programa fuente conviene diferenciar la forma de cada componente del analizador léxico y la estructura del analizador sintáctico Prog. Especificación sintáctica de la sentencia de asignación Sent_asig → identificador simb_asig Expresion Expression → Expresion Operador Operando |Operando Operando → ident ificador | cte_ent |…. el que se lo debe enviar.El alfabeto terminal de la gramática léxica coincide con el alfabeto del lenguaje fuente.….2 Iteración entre el AL y AS A la hora de la construcción de un analizador léxico depende principalmente del enlace e iteración entre AL y AS. es el tipo de iteración de nuestro estudio. fuente Comp.El alfabeto terminal de la gramática sintáctica coincide con el alfabeto no terminal de la gramática léxica { ident.Ambas actividades se realizan de forma independiente. no se sabrá si la secuenciación de los componentes léxicos es correcta hasta que se pase por el análisis sintáctico con la correspondiente perdida de tiempo y memoria . Está configuración permite la relación entre ambos analizadores. para el que se quiere construir el analizador léxico { a-z. .|z digito→ 0|…. que puede realizarse de diferentes formas: . tales como ignorar los comentarios.. 0-9.}.El analizador léxico es una subrutina o corrutina del analizador sintáctico.| par_abrir Expresión par_cerrar Operador → operador_+ | operador_* | operador_/ |…. cte_ent. es el léxico.. .}. dos algoritmo donde uno usa el otro (ambos análisis avanzan simultáneamente).|9 operador_+→ “+” simb_asig→ “:=” ………. Esta conexión se puede ver en la siguiente gramática en la cual los elementos de conexión son los elementos terminales (palabras en negrita). dos algoritmos totalmente independientes. Al realizar los análisis de forma independiente. saltos de líneas. simb_asig.4. un único algoritmo En este caso se está cargando el analizador sintáctico de acciones que no son propias de él. léxico Analizador Sintáctico atributos Relación entre analizador léxico y sintáctico Tabla de símbolos El analizador sintáctico debe configurar estructuralmente las piezas que recibe del analizador léxico para formar un programa.Ambas actividades se realizan de forma concurrente. . mientras que los no terminales marcan la estructura que debe cumplir la secuencia de componentes léxicos. pues mientras el analizador sintáctico pide el componente que tiene que recibir. 3 .…. …………………………………………… Especificación léxica de los componentes que pueden aparecer en una sentencia de asignación identificador → letra identificador | digito identificador | letra | digito cte_ent→ digito cte_ent | digito letra → a|…. léxico Analizador Léxico obtener Comp.

Normalmente un analizador léxico permite simplificar notablemente aspectos del analizador sintáctico: Permite si es necesario realizar modificaciones o extensiones al lenguaje inicialmente ideado. el analizador léxico se ocupa de la forma de cada una de las piezas A continuación se proponen algunas razones de esta separación: Simplificación del diseño Separar el análisis léxico del análisis sintáctico a menudo permite simplificar una.. La sintaxis del léxico es mas sencilla de implementar. en otras palabras. P_cerrar Oper_/ Cte_ent A. Elimina tratamientos innecesarios en el analizador sintáctico.. 4 . para el que se quiere construir el analizador sintáctico. se facilita el mantenimiento del compilador a medida que el lenguaje evoluciona. componentes léxicos especiales. que mientras el analizador sintáctico se encarga de la estructura (la colocación) de las piezas.El alfabeto no terminal de la gramática sintáctica representan la estructura de las palabras del lenguaje. para ver la separación y comunicación entre el léxico y el sintáctico Área := ( base * altura ) / 2 ⇒ identificador simb_asig p_abrir ident operador_* identificador p_cerrar operador_ / cte_ent Sent_asig ident Sim_asig Expresión Expresión Operando P_abrir Operador Oper_/ Expresión P_cerrar Operando Cte_ent A sintáctico ident Sim_asig P_abrir …. corresponde a gramáticas más simples (tipo 3). léxico area := ( base * altura ) / 2 Entrada Comunicación entre el léxico y sintáctico En definitiva. otra o ambas fases. Un analizador léxico independiente permite construir un procesador especializado y potencialmente más eficiente. Eficiencia La división entre análisis léxico y sintáctico también mejora la eficiencia del compilador. Ejemplo de palabra correcta. Gramáticas que tratan lenguajes regulares.

´ . La complejidad de este procesamiento hace recomendable aislarlo en una fase independiente del análisis sintáctico. clases. excepto el de carácter. que llamamos token (TK_identificador).. TK_cte_real. TK_cadena..5 a la variable DO5I) DO 5 I = 2. *. métodos. ya que las peculiaridades del alfabeto de entrada (códigos: ASCII. Operadores Al igual que en matemática. Todos ellos deben ajustarse a una misma descripción. >… Los lexemas representativos de los operadores. ]. pero de significado bien distinto: DO5I = 2. que definen el conjunto de lexemas que se pueden utilizar. existe el siguiente par de proposiciones muy similares sintácticamente. Separadores de construcciones Símbolos utilizados como separadores de las diferentes construcciones de un lenguaje de programación. tipos definidos por el usuario. 5 (Bucle que se repite para I = 2.´ . en lenguajes como Fortran primero se diseñó el lenguaje y luego el compilador. Literales Cualquier lenguaje de programación necesita de la especificación del valor concreto de un tipo de dato. [ . con un nombre representativo del token (TK_cte_entera. Por ejemplo en Fortran( no es de formato libre). lo que conllevó problemas como el que se acaba de plantear. cadenas y caracteres. reales.… } 5 .Se puede aumentar su eficacia con técnicas especiales de manejo de buffers de entrada. El conjunto de lexemas es infinito para todos ellos. relacionales: <. 4. >= (TK_may_igu). los lenguajes de programación necesitan de los operadores para realizar las tareas propias de cálculo: Operadores aritméticos: +. … lógicos: or. Ha sido necesario examinar la cadena de entrada mucho más allá de la propia palabra a reconocer haciendo lo que se denomina lookahead (o prebúsqueda).…. ) . and. Portabilidad Se mejora la portabilidad del compilador. 4 y 5) El analizador léxico no sabe si DO es una palabra reservada o es el prefijo del nombre de una variable hasta que se lee la coma.…) mayúsculas. -. forman un conjunto finito y cada una de ellos se corresponde a un componente léxico: + (TK_suma). ´. descripción que tiene un nombre representativo. ´{´ . Así el (TK_identificador) que define el conjunto de lexemas que se pueden utilizar para denominar los identificadores (variables. que se pueden emplear en el lenguaje: constantes enteras.3 Categorías léxicas más usuales en los lenguajes de programación Entre las categorías léxicas habituales a usar en los lenguajes de programación están las siguientes: Identificadores Cualquier lenguaje de programación necesita de una identificación de los objetos en él utilizados: nombres de variables. TK_carácter) respectivamente.. 3. Patrones complejos Otra razón por la que se separan los dos análisis es para que el analizador léxico se centre en el reconocimiento de componentes y pueda resolver ciertas ambiguedades. EBCDIC. funciones. Cada uno ellos se ajusta a una descripción. Dado que la gran parte del tiempo utilizado en la traducción de un lenguajes se invierte en leer y analizar el texto del programa fuente. Por lo general el conjunto de lexemas que define el TK_identificador es infinito. En cualquier caso.…… .5 (Asignación del valor 2. not y. símbolos especiales y otras anomalías propias de los dispositivos de entrada pueden quedar limitados al ámbito del AL. {´.´ . ´.). ( .. ´}´ . son tipos de literales que se pueden utilizar en la mayoría de los lenguajes .

Prog. Fin de entrada Trata de una categoría léxica ficticia emitida por el analizador léxico para indicarle al analizador sintáctico que es último componente de la entrada 4. Case (TK_pal_res_case). 6 . ( (par_abr).caracter A. todo aquello que carezca de significado según la sintaxis del lenguaje. leer . Al no pasarse al analizador sintáctico. void. Todos los lenguajes disponen de una descripción para los comentarios. for. if. etc. begin. La reinserción de los caracteres suele hacerse en el buffer de la entrada donde están almacenados los lexemas correspondientes a una línea de la entrada. bajo petición del token del analizador sintáctico (según iteración AL y AS).Manejar el fichero fuente ( abrir. indicándolo mediante mensaje de error al usuario (mensaje_error()).Sintáctico . lex A. El analizador léxico no los tiene en cuenta. los espacios en blanco y los tabuladores. cerrar). retorno de carro.. fuente carácter sig. no los manda al analizador sintáctico. léxico Sig comp. class . los espacios en blanco. Cada una de ellas se corresponde a un componente léxico.Rechazar aquellos caracteres o conjunto de éstos que no pertenezcan al lenguaje.…. no necesita de una representación sintáctica (token). Separadores de piezas léxicas En los lenguajes con formato libre (java. y en general.Analizarlo y acumular el carácter (guardar_caracter()) si no se ha determinado aún un token (una categoría léxica) . . for (TK_pal_res_for). Acciones secundarias: .Los lexemas representativos de los separadores forman un conjunto finito. {case. . pascal). léxico Comp. los salta y. En este caso se debe reinsertar dicho carácter a la entrada para realizar el análisis léxico de la siguiente petición del analizador léxico (reinsertar()). Palabras reservadas Palabras con un significado concreto dentro del lenguaje. end. . .4 Funcionalidad del AL Acciones principales : . tabuladores y saltos de línea sólo sirven para separar componentes léxicos. En la mayoría de los lenguajes el analizador léxicos los suprime.Ignorar del programa fuente los comentarios. Categoría léxicas especiales Comentarios Información que se incluye en el texto del programa fuente para mejorar su legibilidad. …} Los lexemas representativos de las palabras reservadas forman un conjunto finito.En ocasiones sólo se puede determinar un token cuando se ha recibido un carácter que pertenece al siguiente token. llamada componente léxico (token) junto con información adicional relevante para las siguientes fases del traductor (atributo). Cada uno de ellos corresponde a un componente léxico. (TK_pun_com ).….Entregar al analizador sintáctico (según iteración entre el AL y AS) la unidad sintáctica (anal_lex (token)).Leer carácter a carácter (siguiente_carácter ()) de la entrada.

informar del fin de línea. Mensaje Error Interfaz T.Si el formato de línea no es libre. Interfaz con el fichero que contiene el programa fuente. . recibe la orden “dame el siguiente componente léxico” del analizador sintáctico Como se ha visto anteriormente la función más importante del analizador léxico es la entrega de los componentes léxicos y sus atributos al analizador sintáctico bajo petición de éste.E. El (anal_lex (token)) devuelve una estructura que contenga token y atributo. solicitado por el analizador sintáctico. y se pueden clasificar según el interfaz con el que entra en contacto el analizador léxico: Interfaz entrada Interfaz AL_AS siguiente Fichero Comp. de errores El analizador léxico es una función llamada por el analizador sintáctico.Tratamiento de espacios en blanco. para la siguiente comunicación En caso de no detectar el componente léxico. ………………………………… Estructura funcional de un analizador léxico Esta interacción suele aplicarse convirtiendo al analizador léxico en una subrutina o corrutina del analizador sintáctico. El (anal_lex (token)) realiza las siguientes tareas con el programa fuente: Detecta el siguiente componente léxico. la representación del lexema así como la longitud del mismo.Controlar la marca de fin de fichero del programa fuente. para mejorar su 7 . tabuladores y caracteres de fin de línea. . . por medio de un buffer (u otra forma) de la lectura de entrada después de : .Guardar información relacionada con los componentes léxicos: identificadores y constantes en la tabla de símbolos.Comunica el componente (la pieza sintáctica) al analizador sintáctico por medio de variables globales: variable para almacenar el lexema. Los token son definidos mediante constantes enteras o representación y operatividad interna. fuente léxico Siguiente carácter Analizador Léxico Siguiente token Analizador Sintáctico Guardar lexema Interfaz T. Trat.Contar los saltos de línea y asociar los mensajes de error con el número de la línea del programa fuente donde se producen. almacenando previamente el atributo en una variable global. . Tabla de símbolos Interfaz con el analizador sintáctico. Estos delimitadores son ignorados excepto el de salto de línea que se incrementa un contador para poder usarlo en el mensaje de error. o sólo el token.Avanza el texto fuente. . llamar al gestor de errores. El resto de las funciones dependen del traductor y del propio lenguaje a procesar.Eliminación de comentarios . tipo enumerado.. S.

Tratamiento de los errores. función.presencia de un carácter que no pertenece al vocabulario terminal.. indicando al menos una línea de la fuente . sin aplicar reglas para su definición. 8 . El (anal_lex (token.. Cuando el (anal_lex (token.. variable) y su posición en memoria. Errores más frecuentes: . su uso (etiqueta.)) sobre la TS son: Inserción de identificadores o constantes Búsqueda de identificadores o constantes Estas operaciones deben realizarse muy rápidamente y su velocidad debe ser independiente del tamaño de la tabla.Sin recuperación: se detecta el error y se cancela el análisis del programa fuente. Las fases posteriores del compilador pueden añadir más información a la tabla.. debe emitir un mensaje de error indicando en la línea del programa fuente donde se produce. En otras ocasiones se utiliza un recuperador de errores. comillas. constante. Gestión de errores Detección: imposibilidad de concordar un prefijo de la entrada con ningún patrón. La tabla de símbolos es una estructura de datos utilizada por el compilador para almacenar toda la información ligada a los identificadores y constantes utilizadas en el programa fuente. su tipo.Con recuperación: se detecta un error. A veces se eliminan los caracteres de la entrada restante hasta que el (anal_lex(token. que no es más que una “reparación” para continuar con el análisis. además del lexema.5 Especificación léxica de un lenguaje de programación Podemos destacar tres modalidades a la hora de la especificación del léxico de un lenguaje: No formalizada – describiendo los componentes léxicos por medio de un lenguaje ordinario.)) guarda los lexemas de los identificadores y el valor de las constantes en la TS.. se toma alguna acción que permita seguir con el análisis.. fin de sentencia..escritura incorrecta de un nombre de usuario: identificador.  se ha incluido un carácter extraño. tras haber advertido del error. Interfaz con el tratamiento de errores. Por esta razón habitualmente se utilizan métodos “hash”. etiqueta.Interfaz con la tabla de símbolos ( TS ) . También es frecuente pasar el mismo carácter o un token especial al Anal_sint() y dejar que éste sea el encargado de realizar 4. .  Se ha omitido un carácter  Se ha añadido un carácter  Han sido permutados dos caracteres adyacentes -comentarios.. Las operaciones que realiza el (anal_lex (token.)) pueda reconocer un patrón ( por ejemplo un delimitador ). etc sin cerrar. La información más común que suele almacenarse en la TS son.)) lee un carácter que no es del lenguaje o no encuentra ningún lexema que concuerde con uno de los patrones especificados. escribiendo el mensaje de dicho error . (dos modalidades) con la necesidad de un buen diagnóstico. etc.

Relacionales: ==. “. [ . +=… .uno o más dígitos. $dolar. $ o ´_´. . ( . interface. uno1. class . Reales 123.Lógicos: &. float) . que pueden estar precedidos por los símbolos 0. cadena vacía “” . ´. *.enteros ( int.Constante entera Descripción . cadena y carácter . 100l long. ´. ) } Cada uno de ellos corresponde a un componente léxico Palabras reservadas {case. & o ´_´.45 double 12. |. seguido de una secuencia de símbolos numéricos alfabéticos .Constante reales Descripción – dos partes separadas por el símbolo ´. ++. el conjunto de lexemas asociados a dicho patrón. una_variable. 0X dependiendo si se trata de una constante octal o hexadecimal respectivamente. ´}´ . 1111. Especificar un token de una manera formalizada. Uno_1 Literales .Constante carácter Descripción – un símbolo delimitado por los símbolos ´ . consiste en dar una expresión regular (o patrón) que describe. Identificadores : Cuenta. Descripción .34f float.34d double . 12. …… .Aritméticos: +. métodos. reales( double.Descripción de las categorías léxicas de un lenguaje de programación como java: Identificadores – clases.{´. if. float) . 9 . ^.Formalizada – describiendo los componentes léxicos por medio de mecanismos regulares A la hora de la especificación lexicográfica de un lenguaje habrá que crear la relación de todas las piezas sintácticas (categorías léxicas).} Cada una de ellas se corresponde a un componente léxico.´ . void. a la vez que permite simplificar. Cadena: “ es una cadena” . /.´ ambas partes están formadas por uno o más digitos. ´. ]. -. simular y aplicar los algoritmos necesarios para calcularlos e implementarlos A partir de las expresiones regulares podemos transformarlas en otros mecanismos regulares que facilitan la especificación de algoritmos para su reconocimiento.<=… . con sus definiciones léxicas. <. Carácter ´c´ Operadores . nombres de atributos. !=. 011 octal 0x111 hexadecimal . Diagramas que también se utilizan para especificar las características sintácticas.Cada una de ellos se corresponde a un componente léxico Delimitadores . Gráfica – mediante la utilización de algún método gráfico.´ . %.Constante cadena Descripción – cero o más símbolos delimitados por los símbolos “. ´{´ .´ . for. ….símbolo alfabético.… . Enteras: 100 int. como los diagramas sintácticos. La segunda parte puede finalizar por el símbolo ´f´ o ´d´ según se tratae de una contante real flota o double respectivamente.

Simulación de la implementación de las categorías léxicas A continuación se representan diferentes seudocódigos reconocedores de lenguajes (* Seudocódigo que simula el anterior diagrama de transiciones por medio de un case. .Categoría léxicas especiales Comentarios. “ “} En los lenguajes con formato libre (java. (* estado inicial *) REPETIR obtener símbolo CASE estado OF 0 : CASE símbolo OF Letra. *) Estado:=0./* comentario de múltiples líneas */ Descripción . dispone de tres tipos de comentarios: . otro: llama_error END.$. pascal). 1: CASE símbolo OF Letra. &: estado:=2.los símbolos “//” seguidos de una secuencia de símbolos hasta final de linea .cualquier secuencia de símbolos delimitados por los símbolos ´/*´ y pueden abarcar más de una línea ´*/´ ._: estado:=1. los espacios en blanco. _ : estado:=1. descrito por una expresión regular a través de la cual se obtiene un AFD equivalente.java. Letra. $. otro: llama_error END. pueden abarcar más de una línea Java dispone de una herramienta javadoc que permite analizar los comentarios de documentación Separadores. tabuladores y saltos de línea sólo sirven para separar componentes léxicos. \ n.//comentario de una línea Descripción . que puede ser definido por medio de un mecanismo regular.Mecanismos regulares que definen las categorías léxicas A continuación se pone un ejemplo de componente léxico. $. dígito._ ……………………………… . UNTIL estado =2 or llama_error Si estado no es de aceptación llama_error 10 . ELSE llama_error END._ digito q0 q1 q2 & AFD identificador Letra. En la mayoría de los lenguajes el analizador léxicos los suprime. El conjunto de lexemas que define una estructura correspondiente a un componente léxico es un lenguaje regular./** comentario de documentación */ Descripción -cualquier secuencia de símbolos delimitados por los símbolos ´/**´ y ´*/´ . Categoría léxica Identificador de java: Descripción por medio de una expresión regular Identificador →( letra | $ | ´_´) ( letra | digito | $ | ´_´)* letra → [a-z] dígito → [0-9] Autómata finito determinista representado por un diagrama de transición que reconoce el lenguaje denotado por la expresión regular anterior.{ \t. . $.

estado:=0. otro: llama error. (*implementación del AFD anterior que reconoce el componente léxico identificador*) BEGIN longitud:=length(palabra). $. (* estado inicial *) REPETIR obtener símbolo.es una representación tabular convencional de la función de transición δ. '0'. REPEAT CASE palabra[posicion] OF 'a'. UNTIL error OR (posicion)>longitud). 1:estado:=1 END. entrada) y devuelve un valor ( un estado ) o error (*Pseudocódigo que simula la anterior tabla de transiciones. & : entrada:= &. posición:=1. IF error THEN AFD_id:=false ELSE AFD_id:=(estado=2) END. La unión de dos o más lenguajes regulares es otro lenguaje regular. '$'. CASE símbolo OF letra : entrada:= letra.*) Estado:=0.1: estado:=1 END. Por lo que podemos ligar todos los autómatas que especifican los componentes léxicos en una estructura común e implementarla 11 .'9': CASE estado OF 0:error:=true. digíto. error:=false. ‘_’. ‘$’] entonces componenter:=”” REPETIR componente=componente + c c:= obtenersímbolo UNTIL no [letra.'z'. El conjunto de palabras reservadas se ajustan a la misma definición que los identificadores pero es un conjunto finito que queda definido por su enumeración.*) c:= obtener símbolo Si c es [letra. entrada ]. If estado=”error” llama_error. ELSE error:=true. Para su reconocimiento bastará con almacenarlas en una tabla y analizarlas antes de comprobar si es un identificador.Tabla de transición. posicion:=posicion+1. '&': CASE estado OF 0:error:=true. ‘_’.. END. dígito: entrada:=dígito. que toma dos argumentos (estado. END . ‘$’] Retroceder un símbolo a la izquierda Aceptar (componente) Return (token) Otro error_léxico (*Implementación en lenguaje Pascal del anterior diagrama de transiciones*) FUNCTION AFD_id (palabra:string): boolean.´_´ estado q0 q1 q2 q1 q1 Error digito error q1 error & error aceptar error (*Pseudocódigo de simulación de una función de transición con retroceso. estado:= tabla [estado. UNTIL estado=”aceptar” entrada letra. 1:estado:=2 END..'_'’`´: CASE estado OF 0.

pero también el código generado es más difícil de mantener. implementar los autómatas resultantes.6. construir sus autómatas finitos individuales. fusionarlos y estructurarlos por medio de un mecanismo selector (también llamado máquina discriminadora determinista). Este tipo de construcciones es muy propensa a errores y difícil de mantener. Sin embargo. TK_punto. cualquier actualización de los patrones reconocedores implica la modificación del código que los implementa costoso..De forma automática mediante un metacompilador. al lenguaje. Se basa en el uso de sentencias if y case para simular las posibilidades que se pueden dar en la lecturas de los caracteres de entrada para formar los componentes léxicos.4.Lex) Esquema estructural de un analizador léxico 12 . Valor:String [] end TokenTipo= ( TK_identificador.Entrada Delimitador Modulo selector Mensaje de error tokens otros literal identificador return (Tok) return (Tok. Este mecanismo consiste en identificar la colección de categorías léxicas (tokens) en construir los patrones necesarios para cada categoría léxica. Lo que hace es dividir la entrada en una serie de componentes léxicos realizando para cada uno de ellos unas acciones determinadas. Token= record Tipo: tokenTipo.1 Construcción de un analizador léxico de forma manual Hasta ahora hemos visto como se implementan los lenguajes asociados a las diferentes categorías léxicas.Mediante la implementación manual de los autómatas finitos. ….6 Construcción de un analizador léxico Podemos destacar tres formas básicas para construir un analizador lexicográfico: -Ad hoc. TK_mas.val) return (Tok. finalmente. Consiste en la codificación de un programa reconocedor que no sigue los formalismos propios de la teoría de autómatas. . Para representar las piezas sintácticas en la implementación del analizador léxico se emplea un tipo enumerado formado por nombres significativos. 4. Con el tipo enumerado se van a tener todas las piezas que se pueden reconocer por el léxico. el analizador léxico no se utiliza para comprobar si una cadena pertenece o no. Aunque la construcción de analizadores mediante este método es sistemática y no propensa a errores. sino el conjunto de cadenas que lo componen. un generador automático de analizadores léxicos( en la práctica se utilizará javacc) son los más sencillos de construir. . ) AS Lexema a analizar Siguiente lexema Lect.

El puntero posición va avanzando hasta encontrar un componente léxico .Una vez encontrado el lexema.contiene las diferentes piezas que el analizador léxico va reconociendo del texto de entrada y va a pasar al analizador sintáctico bajo su petición V_atributo – contiene la longitud del lexema para un identificador y el valor para literales Condiciones iniciales Antes de llamar por primera vez a (anal_lex (token. saltar blancos (caracteres no significativos) Posicionarse al principio del lexema a analizar Lectura de entrada La lectura de entrada se realiza por líneas que se lleva a una estructura estática. línea apuntadores inicio posición límite Línea – vector de caracteres para contener la última línea leída del fichero fuente .longitud del lexema que forma la palabra reservada . El número de caracteres por adelantado necesarios para analizar un lexema determinan la complejidad del analizador léxico. inicio toma el valor de la posición (el primer carácter del siguiente lexema) lexAtributo Variables globales Long atributo pieza LexAtributo – contiene el lexema del componente pieza..)) para obtener una pieza habrá que realizar: Inicializar el contenido de la tabla de palabras reservadas: . que se le pasa desde línea Pieza – comunica al analizador sintáctico la pieza encontrada Long_atributo – longitud del lexema almacenado en lexAtributo Caracteres por adelantado Caracteres por adelantado son los caracteres que han de examinarse más allá de la terminación de un lexema para decidir la pieza que corresponde a ese lexema. así se facilita el examen de los símbolos por adelantado.nombres de las palabras reservadas .. posición se coloca en el siguiente carácter del siguiente lexema . ejemplo ‘++’. Estas variables y su cometido puede ser el siguiente: Token . Pudiendo retroceder sin mayor complejidad. se hace por medio de unas variables globales donde se devuelve el valor de la pieza y el tipo enumerado de la pieza.Representación interna de la palabra reservada Leer la primera línea y ponerla en el buffer de entrada (lectura de entrada).Entre inicio y posición delimitan el lexema .Después de devolver el componente léxico.La comunicación entre el analizador léxico y sintáctico. 13 . llevando la contabilidad de los caracteres leídos.En un principio inicio y posición señalan el primer carácter del lexema que hay que analizar .

su fin se encontrará cuando se llega a un carácter que no forma parte de su definición. ‘. Prioridad de tokens . por lo que el analizador léxico debe ser capaz de tratar recursivamente varios comentarios..La longitud del lexema es desconocida.….} formadas por una secuencia de símbolos alfabéticos identificadores – letra (letra|dígito)* símbolos alfabéticos seguidos de símbolos alfanuméricos Forma de tratar las palabras reservadas Resolución implícita Reconociendo todas como identificadores.Cuando se está analizando un lexema se da prioridad al token con el lexema más largo que se reconoce primero: ejemplo ´+´ y ´+=´ este último es el primero. empezando siempre en cada caso en punto distinto pero siempre en estado inicial de un AFD 14 .’.. Mayúsculas y minúsculas El tratamiento de mayúsculas y minúsculas también es una tarea lexicográfica. palabras reservadas { case .La longitud del lexema es conocida su fin se encontrará cuando se llega al final de la cuenta de los caracteres considerados en dicho lexema.45 se trata de un componente léxico constante real Si el mismo lexema se puede asociar a dos tokens. . while. analiza y los salta. con la particularidad que el analizador léxico no lo pasa al analizador sintáctico puesto que no lo pide. Si es_palabra_reservada ( lexema.[e|E] return (Token_while) ………. mientras que unos lenguajes no la distinguen como Pascal otros sí como: java y C Módulo selector Para reconocer las distintas categorías léxica utilizamos una especie de autómata que llamamos módulo selector que mediante el primer carácter del lexema permite determinar por medio de un CASE que AFD puede simular el reconocimiento del lexema de la entrada y devolver la pieza sintáctica correspondiente. ejemplo area:= . Situaciones posibles que podemos encontrar a la hora de la delimitación de los lexemas: . areabbb:= . El módulo selector no intenta reconocer la entrada sino segmentarla conociendo el primer carácter del lexema. ejemplo ‘. tabla_palabras_reservadas) Entonces TK_palabra_rservada Resolución explícita Se indican todas las expresiones regulares de todas las palabras reservadas y se integran los diagramas de transiciones resultantes de su especificaciones en una sola If [f|F] [o|O] [r|R] return (Token_for) If [w|W]…. [a-zA-Z]( [a-zA-Z]|[0-9])* return (Token_identificador) Los comentarios Los comentarios también forman parte de las características lexicográficas. se detectan por la presencia del delimitador final ejemplo (*…. estos patrones estarán definidos en el orden de aparición.los lexemas que conforman el texto fuente no tienen restricción alguna Restringido . el analizador léxico los detecta.los lexemas que conforman el texto fuente están sujetos a unas reglas (condiciones). Puede darse una serie de comentarios sucesivos..’ . utilizando una tabla adicional con las palabras reservadas.Formato de la codificación Libre. El módulo selector actúa repetidamente sobre la entrada.*).Los lexemas están marcados por delimitadores. 23. que se consulta para ver el lexema reconocido es un identificador o palabra reservada. En el caso de no reconocerlo se creará un mensaje de error.

'”' IF AFD_cadena THEN componente := 'Cadena' ELSE error_lexico(3).'z': IF AFD_id THEN componente :='Identificador' ELSE error_lexico (1).. él cual va a servir al modulo selector de dicho analizador para que devuelva al sintáctico una pieza ficticia (p_ultima).devolver el token y sus atributos en las variables globales correspondientes Codificación del módulo selector FUNCTION Reconocer_palabra (palabra:string):string.. { : begin AFD_saltarComentarios. Rec_literales En cada una de las alternativas hemos de realizar las siguientes operaciones: . va a poner en la variable token un símbolo especial.'9': IF AFD_cte_real THEN componente :='Cte_real' ELSE IF AFD_cte_ent THEN componente pieza:='Cte_ent' ELSE error_lexico(2).Seleccionar reconocedor según el primer símbolo del lexema Modulo selector letra Pal_reservadas Rec_ identificadores dígito Rec_constantes ´´ ……………. (*módulo selector*) FUNCTION Es_trivial:boolean. Pieza que el analizador sintáctico espera para finalizar.terminar de leer el lexema .determinar el token de que se trata y cuáles son sus atributos .') OR (palabra='=') OR (palabra='<') OR (palabra='>=') OR (palabra='+') OR (palabra=':') OR (palabra='-') OR palabra='*') OR (palabra='integer') OR …) END. '0'. (*components que no necesitan un AFD para su reconocimiento*) BEGIN Es_trivial=((palabra='main') OR (palabra='is') OR (palabra='function') OR (palabra='mod') OR (palabra='(') OR (palabra='. Condiciones finales La tarea de reconcimiento de los tokens del texto fuente concluye cuando en dicho texto se encuentra la marca de fin de fichero (EOF). en otro caso se producirá una situación de error. ha de indicar analizador sintáctico de alguna forma que ha concluido el reconocimiento de tokens en el texto fuente. Cuando el analizador léxico encuentra esa marca. ELSE error_lexico(4). END END.. BEGIN IF Es_trivial THEN componente:=palabra ELSE CASE palabra[1] OF 'a'. cuando el analizador lexicográfico detecta el final de fichero. Para ello. 15 .

… . * operaciones: op.) .… .boolean o string type tipo_registro is record <componentes> end record .. En este caso por tratarse de la construcción de un reconocedor lo más fiable y simple será por medio de AFD.. op..’.constantes reales: { lenguaje regular } – componente léxico cte_real .*.’. Llama_proc ( par_act1 . lógicas y operadores +.nom_camp2.integer.!=.… Componentes léxicos infinitos: . .<=. nom_var1 . vector..in out Function nomb_func <argumentos> return <tipo> is <objetos> begin <operaciones> end .!=. pasando por una manera formalizada. operandos . := expresión .cadena: { lenguaje regular } – componente léxico cadena 16 . var_1 .end. par_act2 .’.....identificadores: { lenguaje regular } – componente léxico ident .real.[. -.2 Implementación de un AL formalizado como subrutina del AS La lógica de diseño de un analizador léxico puede ser muy diversa (vista en apartados anteriores) desde lo que es Ad hoc. Análisis léxico dependiente del sintáctico Ejemplo de la estructura de un lenguaje: main nombre_fuente is <objetos> begin <operaciones> end * objetos: Tipos type tipo_vector is array [ cte_ent .. registro subprogramas procedure nomb_proc<argumentos>is<objetos>begin<operaciones> end. tipo – tipo_basico.constantes enteras : { lenguaje regular } – componente léxico cte_ent . expr1. ) .begin. <=. e/s asignación llamada expresión put ( expr0. *.separadores: (.div.) . : <tipo> .6.. cte_ent ]of <tipo_basico> . Selección if<expression>then<operaciones>else<operaciones> end if . aumentando la eficiencia en implementación y tiempo de reconocimiento. var_0 . reales. case expresión is <alternativas> end case . pudiendo ser dependiente o independiente del analizador sintáctico En la asignatura de Procesadores lo diseñaremos de una manera mecánica sistemática.… Componentes léxicos del lenguaje Componentes léxicos finitos: . var1 .out.variables.4.: <tipo_basico> .. loop <operaciones> end loop . get ( var0 . hasta la construcción automática por medio de un metacompilador como pueden ser LEX. control while <expression> loop <operaciones> end loop .: op. determine a que autómata mandarle a reconocer. constantes enteras.operadores: =. variables nom_var0 . JavaCC…...nom_camp1. modelizando los diferentes componentes léxicos en mecanismos regulares.. …… . tipo_basico . <alternatives> when cte_ent | cte_ent |…. Creando un módulo selector que conociendo el primer símbolo.’.palabras reservadas: main. argumentos : iden_arg : form_paso tipo forma_paso : in. componente ....

’.' '. con la excepción de que no puede empezar por un 0.Sin embargo. ni terminar en el carácter subrayado.'9' .. La parte entera está formada por cualquier combinación dígitos (1 ó más). Definición regular que denota los identificadores . ””..'9' Autómata finito determinista AFD que reconoce las constantes enteras .' digito09 digito09 digito09)* digito19 : '1'. salvo en el caso de existir solamente un dígito. digito : '0'.' q7 0-9 q8 Definición regular que denota las constantes reales.cte_ent cte_ent: 0| digito19 (digito09|ε) (digito09|ε) ('. En el interior podrá haber un número indefinido de caracteres. excepto el número 0.'9' Autómata finito determinista AFD que reconoce los identificadores .. aquellas cuyo primer dígito sea un cero.. Además. incluso ninguno. es decir. es decir.' 0-9 0-9 q4 '. Definición formal de los componentes léxicos. excepto el blanco. Para representar en el interior de la cadena el carácter ” se le antepondrá otro carácter ”.' q5 q6 '. Las cadenas comienzan y finalizan con el carácter (”).Definición en lenguaje natural de los componentes léxicos: identificador. no se consideran constantes enteras válidas aquellas que tengan algún cero no significativo.cte_ent 0 q1 q0 1-9 q2 0-9 q3 0-9 '. deben cumplirse las condiciones de que el identificador no puede tener tres o más caracteres de subrayados consecutivos. Los identificadores en este lenguaje deben comenzar obligatoriamente por una letra minúscula y a continuación de cero a infinito símbolos.. salvo en el caso de existir solamente un dígito.'9' 17 .0-9 Definición regular que denota las constantes enteras. de los cuales cada tres deben estar separados por un punto (.'z' . La parte decimal está formada por cualquier combinación dígitos (1 ó más). un dígito o un carácter de subrayado. Digito09 : '0'. que se representa por 0.cte_real cte real: ( 0| digito19digito09 *) '.0-9 q2 q2 a-z. cada uno de los cuales puede ser una letra minúscula.ident a-z.'9' .' ( digito09 * digito19 | 0) digito19 : '1'. digito09 : '0'. cadena. Es válido cualquier carácter. constante entera y constante real.ident : Ident: letra_min (letra_min| digito |_letra_min| _digito|_ _ letra_min| _ _digito)* letra_min: 'a'. Las constantes enteras se forman con uno o más dígitos. Las constantes reales están compuestos de una parte entera y una parte decimal separadas por el carácter ‘.0-9 '_' '_' q0 a-z q1 a-z..) empezando por la derecha. con la excepción de que no puede finalizar por un 0.

Pieza que el analizador sintáctico espera para finalizar.Autómata finito determinista AFD que reconoce las constantes reales – cte_real: 0 q1 q4 '..Representación interna de la palabra reservada Leer la primera línea y ponerla en el buffer de entrada. ha de indicar analizador sintáctico de alguna forma que ha concluido el reconocimiento de tokens en el texto fuente. en otro caso se producirá una situación de error. Para ello. él cual va a servir al modulo selector de dicho analizador para que devuelva al sintáctico una pieza ficticia (p_ultima).cadena car-” ” ” " q0 Implementación q1 q2 Antes de llamar por primera vez al analizador léxico anal_lex (token. 18 . Posicionarse al principio del lexema a analizar Obtener primer componente léxico del texto fuente An Programa..longitud del lexema que forma la palabra reservada . ComprobarFinalAnálisis. La tarea de reconcimiento de los tokens del texto fuente concluye cuando en dicho texto se encuentra la marca de fin de fichero (EOF). (* subprograma asociado al símbolo inicial *) Una vez sentadas las condicionales iniciales en el proceso de análisis el analizador sintáctico comenzará con la llamada al subprograma asociado al símbolo inicial de la gramática a partir del cual se construirá el proceso del análisis sintáctico que llamará al analizador léxico para comprobar los componentes léxicos que va obteniendo.)) el analizador sintáctico para obtener una pieza habrá que realizar: InicializarAnalizadorLexico Inicializar el contenido de la tabla de palabras reservadas: .' 0 0 q0 1-9 q3 q2 0-9 '. cuando el analizador lexicográfico detecta el final de fichero. saltar blancos (caracteres no significativos) OntenerPieza.' 1-9 1-9 q5 0 1-9 q6 Definición regular que denota las cadenas – cadena: cadena: “ (car-“ | ”” )* ” car-“ : cualquier carácter excepto la “ Autómata finito determinista AFD que reconoce las cadenas . Cuando el analizador léxico encuentra esa marca. va a poner en la variable token un símbolo especial.nombres de las palabras reservadas .

Para obtener una pieza a petición del AS.El proceso del análisis lo lleva el analizador sintáctico Procedure Analisis_Sintáctico. Digito: tratar_cte . ‘=’ : p_igual. Begin InicializarAnalizadorLexico. el analizador léxico determinará de que token se trata para comparar con el pedido del AS Diagrama de bloques de un analizador léxico Leer entrada siguiente componente Inicializar tabla Analizador Sintáctico Componente Comp_lex_fin 'a'. (* comprobar si pieza es pultima *) End.. ObtenerPieza.'9 '''' AFD cte_real o AFD cte entera AFD cadena Módulo central o selector Procedure ObtenerPieza. end end end 19 . Begin BuscarInicio Inicio := posición. ‘<’: Ver_si_menor. ‘{‘ : begin saltarComentario. (*inicializar palabras reservadas.'z' AFD identificador Selector autómatas '0'. (* símbolo inicial de la gramática*) ComprobarFinalAnálisis. ………………. (* primera pieza*) AnPrograma.. Case linea [inicio] of Letra: tratar_id .. ‘+’ : pieza:=p_suma. Obtener Pieza end Else begin errorlexicográfico() . saltar blancos *) OntenerPieza.

// subprograma asociado al símbolo no terminal objetos Aceptar(prbegin) AnOperaciones. escribiendo a su salida el token al que pertenecen. while not final do begin posición=posición +1 . Aceptar (pId).’9’] then final:= posición = limite. begin final:= posición = limite. Procedure AnObjetos. IF pieza= prPrcedure THEN AnDefProcedure.’z’. Begin Aceptar (prmain)..Comprueba el analizador léxico si se trata de un identificador Procedimiento Tratar_id .. Comprueba si la pieza pedida por el analizador sintáctico es la obtenida por el analizador léxico Procedure Aceptar (p: piezaSint).6.. else begin final:= true . AnObjetos. 4. uno por línea. 20 . . End. longAtributo:= posición – inicio +1 pieza:=TipoDePalabra().pasar de línea a lex_atributo El procedimiento asociado al símbolo inicial trata de construir de una forma ficticia el árbol sintáctico Procedure AnPrograma. Begin IF pieza= prType THEN AnDefTipo. IF pieza= p_id THEN AnDefVar. Begin If pieza= p then ObtenerPieza Else ErrorSintactico End. if pieza= p_id then anotarAtributo. TipoDePalabra(). finalizando por el token ‘ fin de fichero’. // subprograma asociado al símbolo no terminal Operaciones Aceptar (prend). posisción:=posición-1 end end. End. IF pieza= prFunction THEN AnDefFunction. ‘0’. var final: bolean. …………………………………. if linea [posición] in [ ‘a’. end.3 Implementación de un AL formalizado independiente del AS El analizador léxico realiza la tarea de reconocer todas las palabras del programa fuente a las cuales va reconocer carácter a carácter.Comprueba si es palabra reservada anotarAtributo. Aceptar (prIs).

'9 '''' AFD cte_real o AFD cte entera AFD cadena PROGRAM Analizador_lexico (f_entrada.. palabra.. ……. BEGIN palabra:=''. seguido de la palabra que no coincide con ningún componente léxico* ) BEGIN …….Programa fuente main ejemplo is objetos begin operaciones end Componentes léxicos main identificador is ….. ………………… Leer_palabra:=palabra. END. palabra:string. VAR F_entrada. (*escribe en el fichero de salida F_salida el componente léxico que recibe en la variable componente en el caso de tratarse de un error se escribe 'ERROR LEXICO EN LA PALABRA:' . (*lee caracteres del fichero de entrada F_entrada y los va almacenando en la variable palabra hasta encontrar un carácter separador. es decir un blanco o un fin de línea.. READ(f_entrada.car).. begin …… end Analizador Léxico Diagrama de bloques de un analizador léxico Leer entrada Reconocer palabra Comp_lex_fin 'a'.f_salida). END. PROCEDURE Escribir_componente (componente:string).) 21 . IF componente='ERROR LEXICO EN PALABRA :' THEN writeln(f_salida.…….'z' AFD identificador Escribir salida Selector autómatas '0'.) ELSE writeln(f_salida. (*en palabra se almacena la palabra leída en el fuente*) (*en componente se almacena el componente léxico reconocido*) ……… FUNCTION Leer_palabra:string.…….componente : string. La variable palabra se manda al módulo selector*) VAR car:char.f_salida:TEXT.

'z': IF AFD_ident THEN Reconoce_palabra :='Ident' ELSE Reconoce_palabra :='ERROR LEXICO EN PALABRA:'. BEGIN Comp_lex_finito =((palabra='main') OR (palabra='is') OR (palabra='function') OR (palabra='mod') OR (palabra='(') OR (palabra='. ELSE error:=true END. '0'.'9': CASE estado OF '0':error:=true.'9': IF AFD_cte_real THEN Reconoce_palabra :='Cte_real' ELSE IF AFD_cte_ent THEN Reconoce_palabra :='Cte_ent' ELSE Reconoce_palabra :='ERROR LEXICO EN PALABRA:'. posicion:=posicion+1. '''' IF AFD_cadena THEN Reconoce_palabra := 'Cadena' ELSE Reconoce_palabra :='ERROR LEXICO EN PALABRA:'.. REPEAT CASE palabra[posicion] OF 'a'.. (*implementación del AFD que reconoce el componente léxico cte_ent y cte real*) …… FUNCTION AFD_cadena (palabra:string): boolean.'3':error:=true. '0'.) END. '2'. '1':estado:=2. error:=false. '_': CASE estado OF '0'. '1'. ……………………………………… ELSE Reconoce_palabra :='ERROR LEXICO EN PALABRA:'. FUNCTION AFD_cte (palabra:string): boolean. (*implementación del AFD que reconoce el componente léxico cadena*) …… (*****componentes que no necesitan un AFD para su reconocimiento)************) FUNCTION Comp_lex_finito (palabra:string):boolean. BEGIN estado:=0.'1'.'3':estado:=1 END. posición:=1.posición:INTEGER. IF error THEN AFD_ident:=false ELSE AFD_ident:=(estado=1) END. (*implementación del AFD que reconoce el componente léxico ident*) VAR estado.(*****componentes que necesitan de un AFD para su reconocimiento)************) FUNCTION AFD_ident (palabra:string): boolean. '3': estado:=1 END. error:BOOLEAN. BEGIN IF Com_lex_fin (palabra) THEN Reconoce_palabra:=palabra ELSE CASE pal [1] OF 'a'.. 22 .'z': CASE estado OF '0'. UNTIL error OR(Length(palabra)<posicion). END END. '2':estado:=3 END.'2'.') OR (palabra='=') OR (palabra='<') OR (palabra='>=') OR (palabra='+') OR (palabra=':') OR (palabra='-') OR palabra='*') OR (palabra='integer') OR ……. (************************(*módulo selector*)*******************************) FUNCTION Reconoce_palabra (palabra:string):string..

.. . se utiliza un programa especial que tiene como entrada pares de elementos de la forma: patrones que especificación una categoría léxica por medio de una expresión regular seguido de la acción que se quiere realizar cuando en la entrada aparezca una palab ra que se ajuste a dicho patrón. Por ejemplo. retornan objetos con una estructura más compleja. write(f_salida. los analizadores resultantes suelen ser bastante eficientes tanto en tiempo como en memoria. 9)+ {return NUM_REAL. C. por medio del método de los subconjuntos. etc Los metacompiladores más modernos basados en programación orientada a objetos también asocian un código a cada categoría gramatical. Mediante un metacompilador ( generador de analizadores léxicos) en este caso. Así los patrones más frecuentes deben ir en los primeros lugares (espacios en blanco. generan los autómatas finitos no deterministas con transiciones vacías por medio del método de Thompson.'Fin_fichero'). 9)+ {return NUM_ENT.. Dado que hoy día existen numerosas herramientas para construir analizadores léxicos a partir de notaciones de propósito especial basadas en expresiones regulares. 23 . Escribir_componente (componente)... Normalmente esta acción suele finalizar con la devolución de una categoría léxica. se puede proponer una estructura como: (“ ”\t \n) (0 .7 Codificación de un analizador léxico de forma automática. Cuando existan patrones que coincidan en una subcadena se pondrá primero el reconocimiento del lexema más largo. nos basaremos en ellas para proseguir nuestro estudio dado que.. si se necesita construir un analizador léxico que reconozca los números enteros.. los cuales se simulan e implementa en un lenguaje de programación. tabuladores. Existen metacompiladores que generan código en la mayoría de los lenguajes de programación: java.. El metacompilador al encontrar los patrones descritos por medio de expresiones regulares. que generan código en java. etc.. (Expresión regular n) {acción a ejecutar n} Cada acción a ejecutar es un fragmento de programa que describe cuál ha de ser la acción del analizador léxico cuando la secuencia de entrada coincida con la expresión regular.. (Expresión regular 1) {acción a ejecutar 1} (Expresión regular 2) {acción a ejecutar 2} (Expresión regular 3) {acción a ejecutar 3} ..} El programa así generado se compila y se genera un ejecutable que es el analizador léxico de nuestro lenguaje. z) (a . 4. END.. los números reales y los identificadores en minúsculas...(*****************programa principal****************************************) BEGIN(*Programa Principal*) Abrir ficheros WHILE NOT EOF(f_entrada) DO BEGIN palabra:=Leer_palabra. pascal. saltos de línea.. Comenzaremos con un generador de analizadores léxicos escritos en java .} (0 .} (a . pero en lugar de retornar dicho código. además. se convierte a autómata finito determinista. 9)* {return ID. z 0 . (0 . cerrar ficheros END. 9)*. componente:=Reconoce_palalabra(palabra). Colocando la secuencia de patrones en el orden que queremos el análisis..

"-"])? (["0"-"9"])+ > } Programa entrada Programa fuente en L Comp."F"])? | ". pero el código generado por el AL es más difícil de mantener y puede resultar menos eficiente. } El siguiente ejemplo muestra la definición de una constante de tipo real: TOKEN : { < FLOAT_LITERAL : (["0"-"9"])+ ".println (“ es un literal en coma flotante”). . Léxica Meta Comp.} | < #EXPONENT: ["e"." (["0"-"9"])+ (<EXPONENT>)? (["f". de L Programa salida Esp. Esp en L en Prog."E"] (["+".out.. Obj en Esquema general de un generador automático de analizadores léxicos 24 ."F"])? > { system."F"])? | (["0"-"9"])+ (<EXPONENT>)? (["f". requieren más esfuerzo pero más eficiente y sencillez de mantenimiento Ejemplo de especificación léxica en JavaCC La sintaxis básica de una declaración léxica es la siguiente TIPO_DECLARACION : { <Token1_id:Expresión_regular_1>{código} |<Token2_id:Expresión_regular_2>{código} |<Token3_id:Expresión_regular_3>….." (["0"-"9"])* (<EXPONENT>)? (["f". Mientras que los escritos a mano en un lenguaje de alto nivel.Es la forma más sencilla de construcción de analizadores léxicos.