Está en la página 1de 10

Función del analizador léxico (1)

• Componente léxicos (token): unidad mínima de información que significa


algo a la hora de compilar; concepto de palabra; las frase de un lenguaje
constan de cadenas de componentes léxicos.
• Lexemas: Una secuencia de caracteres de entrada que comprenda un solo
componente léxico se llama lexema; cadenas de caracteres de las que extraigo
el concepto abstracto de componente léxico.
• Patrón: Descripción de la forma que han de tomar los lexemas para ajustarse
a un componente léxico.
Ejemplo:
COMP. LÉXICO LÉXEMA PATRÓN
const const const
if if if
oprel <, <=, =, >, >= <|<=|=|>|>=
id pi, D2, velocidad [a-zA-Z][a-zA-Z0-9]*
núm 3.141, 6.2E23, 120 -?([0-9]+|[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?
literal "hola mundo" "[^"]*"

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 2

Función del analizador léxico (2) Función del analizador léxico (3)
• Un analizador léxico aísla al analizador sintáctico de • Interfaz con el analizador sintáctico
la representación en lexemas de los componentes • Es habitual que el analizador léxico y el sintáctico formen un par
léxicos. Tiene como funciones: productor-consumidor. El analizador léxico produce componentes léxicos
y el analizador sintáctico los consume.
– Eliminación de espacios en blanco y comentarios. Si el componente
analizador léxico elimina los espacios en blanco, el léxico
analizador sintáctico nunca tendrá que considerarlos. La programa Analizador Analizador
alternativa de modificar la gramática para incorporar los fuente léxico sintáctico
obtén sig.
espacios en blanco dentro de la situación no es tan fácil de comp. lex.
implantar.
Tabla de
– Reconocimiento de identificadores y palabras clave. Es símbolos
el encargado de construir los lexemas que constituyen los
identificadores de los lenguajes de programación. • Hay varias razones para dividir la fase de análisis de la compilación en
– Reconocimiento de constantes. La tarea de agrupar dígitos análisis léxico y análisis sintáctico.
para formar enteros se le asigna, por lo general, a un 1.Separar el análisis léxico del análisis sintáctico a menudo permite simplificar
analizador léxico, porque los números se pueden tratar una u otra de dichas fases.
como unidades simples durante la traducción. 2.Se mejora la eficiencia del compilador.
3.Se mejora la transportabilidad del compilador.
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 3 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 4
Función del analizador léxico (4) Función del analizador léxico (5)
• Atributos de los componentes léxicos Ejemplo.
• Cuando concuerda con un patrón más de un lexema, el
analizador léxico debe proporcionar información adicional printf("Resultado: %d\n", 25);
sobre el lexema concreto que concordó a las siguientes fases <id, apuntador a la entrada de la tabla de símbolos para printf >
del compilador. <(, >
• El analizador léxico recoge información sobre los <str, apuntador a la cadena "Resultado: %d\n">
componentes léxicos en sus atributos asociados. <,,>
• Los componentes léxicos influyen en las decisiones del <núm, valor entero 25 >
análisis sintáctico, y los atributos, en la traducción de los
< ),>
componentes léxicos. En la práctica, los componentes.
<;,>
• En la práctica, los componentes léxicos suelen tener un solo
atributo –un apuntador a la entrada de la tabla de símbolos
donde se guarda la información sobre el componente léxico.
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 5 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 6

Función del analizador léxico (6) Función del analizador léxico (7)
function analex: integer;
var buflex: array [0..100] of char; c: char;
• Errores léxicos begin
loop begin
• Son pocos los errores léxicos que se pueden detectar lee un carácter en c;
if c es un espacio o un tabulador then no hacer nada;
simplemente a nivel léxico porque un analizador else if c es un carácter de línea nueva then numlínea:=numlínea+1;
léxico tiene una visión muy restringida del programa else if c es un dígito then begin
asignar a valcomplex el valor de éste y los dígitos siguientes;
fuente. return NUM
• La estrategia de recuperación más sencilla es el end
else if c es una letra then begin
“modo pánico”. Se borran caracteres sucesivos de la poner c y las letras y dígitos sucesivos en buflex;
entrada hasta que el analizador léxico pueda encontrar p:=busca(buflex);
if p=0 then p:=inserta(buflex, ID);
un componente léxico bien formado. valcomplex:=p;
return el campo complex de la entrada p de la tabla
• Otras posibles acciones de recuperación son: end
1. Borrar un carácter extraño else begin
valcomplex:= NINGUNO;
2. Insertar un carácter que falta return el número entero del código del carácter c
3. Reemplazar un carácter incorrecto por otro correcto end
end
4. Intercambiar dos caracteres adyacentes. end
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 7 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 8
Manejo de buffers de entrada (1) Manejo de buffers de entrada (2)
• Se utiliza un buffer dividido en dos mitades de N caracteres cada una.
• Existen tres métodos generales de implantación de un analizador E = M * C * * 2 eof
léxico:
–Utilizar un generador de analizadores léxicos delantero
–Escribir el analizador léxico en un lenguaje convencional de comienzo_lexema
programación de sistemas
• Se leen N caracteres en cada mitad del buffer con una orden de lectura de
–Escribir el analizador léxico en lenguaje ensamblador
sistema, en vez de invocar una instrucción de lectura para cada carácter.
• Estos enfoques tienen un orden de dificultad creciente,
lamentablemente los enfoques más difíciles consiguen analizadores Si quedan menos de N caracteres en la entrada, entonces se lee un
léxicos más rápidos. carácter especial eof en el buffer después de los caracteres de entrada.
• Como el analizador léxico es la única fase que lee el programa carácter • Se mantienen dos apuntadores al buffer de entrada. La cadena de
a carácter su velocidad es un problema en el diseño de compiladores. caracteres entre los dos apuntadores es el lexema en curso. Al principio,
• Además en muchos lenguajes el analizador léxico necesita preanalizar los dos apuntadores apuntan al primer carácter del próximo lexema que
varios caracteres, antes de poder anunciar una concordancia. Los
caracteres preanalizados se tienen que devolver después a la entrada. hay que encontrar.
Como se puede consumir mucho tiempo moviendo caracteres, se han • El apuntador delantero, examina hacia delante hasta encontrar una
desarrollado técnicas especializadas en el manejo de buffers para concordancia con un patrón. Una vez determinado el siguiente lexema, el
reducir el número de operaciones necesarias para procesar un carácter
de entrada. apuntador delantero se coloca en el carácter de su extremo derecho.
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 9 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 10

Manejo de buffers de entrada (3) Manejo de buffers de entrada (4)


• Después de haber procesado el lexema, ambos apuntadores se • El algoritmo tal como se ha expuesto necesita dos comparaciones para
colocan en el carácter situado inmediatamente después del lexema. cada avance del apuntador delantero. Se pueden reducir a una las
• Cuando el apuntador delantero esta apunto de sobrepasar la marca comparaciones si se amplía cada mitad del buffer para admitir un
intermedia del buffer, se llena la mitad derecha.
carácter centinela al final.
• Cuando el apuntador delantero está a punto de sobrepasar el extremo
derecho del buffer, se llena la mitad izquierda y el apuntador E = M * eof C * * 2 eof eof
delantero se regresa al principio del buffer delantero
if delantero está al final de la primera mitad then begin comienzo_lexema
recargar la segunda mitad; • Este código realiza sólo una comparación en la mayoría de las ocasiones
delantero := delantero + 1; delantero := delantero + 1;
end if delantero = eof then begin
else if delantero está al final de la segunda mitad then begin if delantero esta al final de la primera mitad then begin
recargar la primera mitad; recargar la segunda mitad;
pasar delantero al principio de la primera mitad delantero := delantero + 1;
end end
else delantero := delantero + 1; else if delantero al final de la segunda mitad then begin
recargar la primera mitad;
• Este esquema funciona muy bien, pero limita la cantidad de pasar delantero al principio de la primera mitad
caracteres de preanálisis, esto puede imposibilitar el reconocimiento end
de los componentes léxicos cuando la distancia recorrida por el else /* eof dentro de bufer*/ terminar la entrada
apuntador delantero sea mayor que la longitud del buffer. end
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 11 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 12
Especificación de componentes Especificación de componentes
léxicos (1) léxicos (2)
• Las expresiones regulares son la notación mas • Las expresiones regulares se utilizan para denotar lenguajes
regulares y se definen del siguiente modo recursivo (dado un
generalizada para especificar los patrones de alfabeto Σ):
los lexemas de los componentes léxicos. –ε la expresión regular que denota el conjunto {ε}
–∀a ∈ Σ, a es una expresión regular que designa al conjunto regular {a}
• Conviene tener claros los siguientes conceptos: –Si α y β son expresiones regulares que designan los conjunto regulares
Cα y Cβ respectivamente, entonces:
–alfabeto; cadena sobre un alfabeto; cadena vacía; • (α)|(β) es la expresión regular que designa al conjunto regular Cα ∪ Cβ
longitud de una cadena; concatenación y • (α)(β) es la expresión regular que designa al conjunto regular Cα·Cβ
• (α)* es la expresión regular que designa al conjunto regular Cα*
exponenciación de cadenas; lenguaje; lenguaje • (α) es la expresión regular que designa al conjunto regular Cα
vacío; unión, concatenación y cerraduras de Kleene –Φ es la expresión regular que representa la conjunto vacío (que es
regular)
y positiva de un lenguaje; expresión y definición
–Ninguna otra cosa es un expresión regular.
regular • Además se utilizan las abreviaturas: +, ? , [c1c2 ... cn], [ci-cf]

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 13 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 14

Especificación de componentes Reconocimiento de componentes


léxicos (3) léxicos (1)
• Definición regular: Conjunto de definiciones de la forma:
d1→ r1 donde r1 es una expresión regular sobre Σ
Ejemplo
d2→ r2 donde r2 es una expresión regular sobre Σ∪d1 prop → if expr then prop
d3→ r3 donde r3 es una expresión regular sobre Σ∪d1∪d2 | if expr then prop else prop
..... . . ... |ε
di→ ri donde ri es una expresión regular sobre Σ ∪ ∪ij=1dj expr → término oprel término
..... . . ... | término
dn→ rn donde rn es una expresión regular sobre Σ ∪ ∪nj=1dj término → id | núm
Ejemplo
dígito → [0-9] if → if
delim → [ \t\n]
letra → [a-zA-Z] then → then
eb → delim +
else → else
dígitos → dígito + oprel → < | <= | = | <> | > | >=
fracción_opt → ( . dígitos ) ? id → letra ( letra | dígito ) *
exponente_opt → ( E ( + | - ) ? dígitos ) ? núm → dígito ( . dígito + ) ? ( E ( + | - ) ? dígito + ) ?
núm → dígitos fracción_opt exponente_opt
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 15 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 16
Reconocimiento de componentes Reconocimiento de componentes
léxicos (2) léxicos inicio
(3)
0 < 1 = 2 devuelve(oprel, MEI)
EXPR. REG. COMP. LÉX. VALOR DEL ATRIBUTO > 3 devuelve(oprel, DIF)
eb - - otro *
4 devuelve(oprel, MEN)
if if - =
5 devuelve(oprel, IGU)
then then -
> =
else else - 6 7 devuelve(oprel, MAI)
otro *
id id apuntador a la entrada en la tabla 8 devuelve(oprel, MAY)
letra o dígito
núm núm apuntador a la entrada en la tabla *
inicio letra otro devuelve(obten_complex(), instala_id())
< oprel MEN 9 10 11
<= oprel MEI dígito dígito dígito
*
= oprel IGU inicio dígito . dígito E +o- dígito otro
12 13 14 15 16 17 18 19
<> oprel DIF E dígito
dígito delim
> oprel MAY * *
inicio dígito inicio delim
otro otro
>= oprel MAI 25 26 27 28 29 30
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 17 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 18

Reconocimiento de componentes Reconocimiento de componentes


léxicos (4) léxicos (5)
• A partir del diagrama de transiciones se puede • Una secuencia de diagramas de transiciones se puede convertir en
construir “a mano” un programa analizador léxico de un programa que busque los componentes léxicos especificados
un modo sistemático. por los diagramas.
• En general puede haber varios diagramas de • A cada estado del diagrama le corresponde un segmento de código.
– Si hay aristas que salen de un estado, entonces su código lee un carácter y
transiciones, cada uno de los cuales especifique un selecciona una arista para seguir, si es posible. Si hay una arista etiquetada
grupo de componentes léxicos. con el carácter leído, o etiquetada con una clase de caracteres que contenga
el carácter leído, entonces el control se transfiere al código del estado
–Si surge un fallo mientras se esta siguiendo un diagrama de apuntado por esa arista.
transiciones, se debe retroceder el apuntador delantero hasta – Si no hay tal arista y el estado en curso de ejecución no es el que indica que
donde estaba en el estado inicial de dicho diagrama, y se ha encontrado un componente léxico, entonces se llama a la rutina
activar el siguiente diagrama de transiciones (igualar el fallo() para hacer retroceder el apuntador delantero a la posición del
apuntador delantero al valor del apuntador de inicio de apuntador al comienzo e iniciar la búsqueda del componente léxico
lexema). especificado por el siguiente diagrama de transiciones.
– Si no hay que probar más diagramas de transiciones, fallo() llama a una
–Si el fallo surge en todos los diagramas de transiciones, es rutina de recuperación de errores.
que se ha detectado un error léxico y se invoca una rutina de
recuperación de errores. • Para devolver los componentes léxicos se usa una variable global
valor_lexico.
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 19 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 20
Reconocimiento de componentes léxicos (listado)
int estado = 0, inicio = 0; case 9:
int valor_lexico;
int fallo(){
c=sigtecar();
if (isletter(c)) estado=10;
else estado=fallo(); break;
Autómatas finitos (1)
delantero=inicio_lexema;
case 10:
switch(inicio){
case 0: inicio=9; break;
c=sigtecar();
if (isletter(c)) estado=10; • Autómata finito determinista: es una
case 9: inicio=12; break;
case 12: inicio=20; break;
else if (isdigit(c)) estado=10;
else estado=11; break; quintupla (Σ,Q, f, q0, F ), donde:
case 20: inicio=25; break; case 11:
case 25: recupera(); break; regresa(1); Σ es un alfabeto de entrada.
–Σ
valor_lexico=instala_id();
–Q
Q es un alfabeto de estados.
default: /* error */
} } return ( obten_complex() );
. . /* aquí los casos 12 al 24 */
complex sigte_complex(){
while(1){
case 25:
c=sigtecar();
–f es la función de transición:
switch(estado){
case 0:
if (isdigit(c)) estado=26; f : Q ✕Σ → Q
else estado=fallo(); break;
c = sigtecar();
if(c==blanco||c==tab||
case 26:
c=sigtecar();
–q0 es el estado inicial.
c==newline){ if (isdigit(c)) estado=26;
else estado=27; break;
–F
F ⊂ Q es el conjunto de estados finales o estados
estado=0; inicio_lexema++;}
else if (c=='<') estado=1; case 27: de aceptación
regresa(1);
else if (c=='=') estado=5;
valor_lexico=instala_num();
else if (c=='>') estado=6; return( NUM );
else estado=fallo(); }}}
break;
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 21 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 22

Autómatas finitos (2) Autómatas finitos (3)


• Autómata finito no determinista: es una • La parte fundamental de un autómata finito es su
quintupla (Σ,Q, f, q0, F ), donde: función de transición por eso es habitual representarlo
mediante una tabla que da dicha función o mediante
Σ es un alfabeto de entrada.
–Σ
un grafo.
–Q
Q es un alfabeto de estados. a
a b c b
–f es la función de transición:
f : Q ✕ ( Σ∪ε ) → P(Q) → q0 q0 q1 q2 q0
c q1
a
b a
–q0 es el estado inicial. q1 q3 q2 q2 c b, c

–F
F ⊂ Q es el conjunto de estados finales o estados (q2) q3 q3 q3 q2 q3
estados = nodos a, b, c
de aceptación (q3) q3 q2 q2
transiciones = arcos
estados finales = nodo con doble circulo
estado inicial = nodo con flecha de entrada
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 23 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 24
Autómatas finitos (4) Autómatas finitos ~
(5)
cerr-εε(q) = {f (q, εn)}∪{q}.
Es decir el conjunto de estados a los que puedo
• Simulación de un AFD llegar a partir del estado q mediante transiciones ε (sin consumir entrada)
cerr-εε(T)= ∪q∈T cerr-ε(q)
s := s0;
mueve (s,c) es una función que • Paso de un AFND a un AFD
c := sgtecar(); implementa la función de • Algoritmo: Construcción de subconjuntos
while c ≠ eof do
transición, dado un estado y un
carácter nos devuelve el estado estaD← cerr-ε(q0);
siguiente.
begin while haya un estado T sin marcar en estaD do
sgtecar ( ) es una función que marcar T;
s := mueve(s,c); accede al siguiente carácter de la
cadena de entrada. for cada símbolo de entrada a∈Σ do
c := sgtecar(); U := cerr-ε(mueve(T, a));
dnd; if U∉estaD then añadir U sin marcar a estaD
if s∈F then return “SI” else return “NO” tranD[T, a] := U
AFND( Σ,Q, f, q0, F ) →AFD( Σ,estaD, tranD, cerr-ε(q0), F ) F={U∈estaD: U∩F ≠ ∅}
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 25 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 26

Paso de una expresión regular a un Paso de una expresión regular a un


AFN (1) AFN (2)

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 27 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 28
Paso de una expresión regular a un Construcción de un AFD a partir
AFN (3) de una expresión regular (1)
• Simulación de un AFND • Construirla e.r. ampliada α$ $∉Σ
S :=cerr-ε({s0 }); • Obtener el árbol sintáctico de α$
mueve (S,c) función de transición,
dado un cjto de estados y un carácter • Responder a las preguntas:
c := sgtecar(); nos devuelve los estados siguientes. –¿Que letras pueden aparecer como primera letra de la e.r.
while c ≠ eof do sgtecar ( ) accede al siguiente representada por α cuáles como últimas?
carácter de la entrada. –¿Supuesto que yo se que letra acaba de aparecer, que letras
begin
cerr-εε (S) conjunto de estados a los pueden venir a continuación en las palabras representadas
S := cerr-ε(mueve(S,c)); que se puede llegar a partiendo de por α?
estados de S y siguiendo arcos
c := sgtecar(); etiquetados con ε.
–La idea es tratar de numerar la posición de las letras que
aparecen en la e.r. Una vez que tengo el árbol puedo hacer
end una numeración, lo cual me da una ordenación parcial. Se
establece una equivalencia entre los estados significativos
if S∩F≠∅ then return “SI” else return “NO” del autómata y las posiciones del árbol (nodos hoja).

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 29 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 30

Construcción de un AFD a partir Construcción de un AFD a partir


de una expresión regular (2) de una expresión regular (3)
• Permite construir directamente un AFD a partir de una • La noción de una posición concordando con un símbolo de
expresión regular aumentada (α$ $∉Σ). entrada será definida en cuanto a la función siguiente-pos en
• Primero se construye un árbol sintáctico T para α$ con posiciones del árbol sintáctico. Si i es una posición,
siguiente-pos(i) es el conjunto de posiciones j tales que hay
las posiciones de las hojas numeradas y después se
alguna cadena de entrada ...cd... Tal que i corresponde a esta
calculan cuatro funciones: anulable, primera-pos,
aparición de c y j a esta aparición de d.
última-pos y siguiente-pos haciendo recorridos sobre T.
• Para calcular la función siguiente-pos, es necesario conocer
• Por último se construye el AFD a partir de la función qué posiciones pueden concordar con el primer o último
siguiente-pos. Las funciones anulable, primera-pos y símbolo de una cadena generada por una determinada
última-pos se definen sobre los nodos del árbol subexpresión de una expresión regular. Para esto es también
sintáctico y se usan para calcular siguiente-pos, que necesario conocer qué nodos son las raíces de las
está definida en el conjunto de posiciones de las hojas subexpresiones que generan lenguajes que incluyen la cadena
en el árbol. vacía (nodos anulables)

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 31 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 32
Construcción de un AFD a partir Construcción de un AFD a partir
de una expresión regular (4) de una expresión regular (5)
• Cálculo de las funciones: anulable, primera-pos y última-pos • La función siguiente-pos(i) indica qué posiciones
Nodo anulable(n) primera-pos(n) última-pos(n) pueden seguir a la posición i en el árbol sintáctico. Dos
n es una hoja
true ∅ ∅ reglas definen todas las formas en que una posición
con símbolo ε
n es una hoja
puede seguir a otra:
con la posición i false {i} {i} –Si n es un nodo-cat con hijo izquierdo c1 e hijo derecho c2, e i
n |
es una posición dentro de última-pos(c1), entonces todas las
∨anul(c2) pripos(c1)∪pripos(c2) últpos(c1)∪últpos(c2)
anul(c1)∨ posiciones de primera-pos(c2) están en siguiente-pos(i).
c1 c2
∀i∈última-pos(c1) siguiente-pos(i) ⊃ primera-pos(c2)
if anul(c1) then if anul(c2) then
n · ∧anul(c2) pripos(c1)∪pripos(c2) últpos(c1)∪últpos(c2)
anul(c1)∧ –Si n es un nodo-ast, e i es una posición dentro de última-
c1 c2 else pripos(c1) else últpos(c2) pos(n), entonces todas las posiciones de primera-pos(n) están
en siguiente-pos(i)
n *
true pripos(c1) últpos(c1) ∀i∈última-pos(c1) siguiente-pos(i) ⊃ primera-pos(c1)
c1
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 33 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 34

Construcción de un AFD a partir Minimización del número de


de una expresión regular (6) estados de un AFD
•Algoritmo para obtener el AFD a partir de siguiente-pos • Dado un AFD (Σ,Q, q0, f, F ), el AFD mínimo
estaD:= primera-pos (raíz); asociado (Σ, Q/≡, [q0], [ f ], F/≡) se puede construir
while haya un estado T sin marcar en estaD do mediante el siguiente algoritmo:
marcar T; 1. k = 0. Construir la partición Π0 de Q constituida por las
for cada símbolo de entrada a∈Σ do clases F y Q-F
U := siguiente-pos(p); 2. repetir
p∈T:p etiqueta una hoja con símbolo a a. incrementar k
if (U∉estaD) ∧ (U≠∅) then añadir U sin marcar a estaD b. construir Πk, partiendo de Πk-1 y manteniendo en la misma clase
dos estados q y q´ si y solamente si ∀a∈Σ los estados f(q,a) y
tranD[T, a] := U f(q´,a) están en la misma clase de Πk-1
end
end hasta que Πk-1=Πk (lo cual ocurrirá antes de que k=n-1)
3. Πk-1 es Q/≡
AFD( Σ,D,tranD,primera-pos(raíz),F ) F={U∈estaD: p∈U y p la posición de $}

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 35 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 36
Diseño de un generador de Diseño de un generador de
analizadores léxicos (1) analizadores léxicos (2)
• Supóngase que se tiene una especificación de un • Un método es construir la tabla de transiciones de un
analizador léxico de la forma: autómata finito no determinista N para el patrón
p1 {acción1} pi es una expresión regular
compuesto p1|p2| ... | pn. Esto se puede hacer creando
p2 {acción2} accióni es un fragmento de programa que debe ejecutarse
primero un AFND N(pi) para cada patrón pi
... siempre que se encuentre en la entrada un lexema que
concuerde con pi
utilizando el algoritmo de Thompson, añadiendo
pn {acciónn} después un nuevo estado de inicio s0, y por último
enlazando s0 al estado de inicio de cada N(pi) con una
• El problema es construir un reconocedor que busque transición ε.
lexemas en el buffer de la entrada. Si concuerda más ε N(p1)
de un patrón, el reconocedor elegirá el lexema más
largo que haya concordado. Si hay dos o más
patrones que concuerden con el lexema más largo, se s0
ε N(p2)
elige el primer patrón que haya concordado de la ...
lista. ε
N(pn)
César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 37 César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 38

Diseño de un generador de
analizadores léxicos (3)
• Cuando se simula el AFND, se construye la secuencia de conjuntos de estados
donde puede estar el AFND combinado después de leer cada carácter de
entrada.
• Siempre que se añada un estado de aceptación al conjunto de estados en curso,
se registran la posición del puntero delantero y el patrón pi correspondiente a
este estado de aceptación. Si el conjunto de estados en curso ya contiene un
estado de aceptación, entonces solo se registra el patrón que aparezca primero
en la especificación de LEX.
• Incluso si se encuentra un conjunto de estado que contenga un estado de
aceptación, para encontrar la concordancia más larga se debe seguir simulando
el AFND hasta alcanzar terminación, es decir, un conjunto de estados desde el
que no hay transiciones con el símbolo de entrada en curso.
• En la terminación se retrocede el apuntador delantero a la posición en que
ocurrió la última concordancia. El patrón que hizo dicha concordancia
identifica al componente léxico encontrado, y el lexema emparejado es la
cadena entre los apuntadores de inicio del lexema y delantero. (además existe
un patrón de error)

César Ignacio García Osorio. Universidad de Burgos. PL. Análisis léxico. 39

También podría gustarte