You are on page 1of 39

Universidad Autnoma del Estado de Mxico

Facultad deIngeniera

PROGRAMACION DE SISTEMAS II
Un compilador es un programa traductor que lee un programa escrito en un lenguaje (programa
fuente) y lo traduce a un programa equivalente en otro lenguaje (programa objeto). Una parte importante
durante el proceso de traduccin, es que el compilador indique los errores ocurridos.
PROGRAMA
FUENTE

PROGRAMA
OBJETO

COMPILADOR

MENSAJES DE
ERROR

El programa fuente puede estar escrito en varios lenguajes, as mismo, el programa objeto puede
ser diferente, quizs otro lenguaje, cdigo intermedio, o cdigo de mquina, el cual puede ser
ejecutado "directamente" por un microprocesador.
Existen compiladores de un paso, o de varios pasos, dependiendo de las lecturas que hagan del
archivo fuente o archivos con representaciones intermedias. Tambin existen de optimizacin de
cdigo, etc.
FASES DE UNA COMPILACION
Anlisis.- Descompone el programa fuente en piezas para obtener una representacin intermedia
del mismo.
Sntesis.- Toma la representacin intermedia para generar el cdigo mquina, o cuando menos, el
cdigo intermedio.
Durante la fase de anlisis se crean estructuras jerrquicas como los rboles de sintaxis.
X=2*Y+C
=
X

Existen impresoras que permiten la impresin con diferentes tipos de FONTS y los programas con
sangras. Estos pueden considerarse como parte de un compilador.
PREPROCESADORES
Existen algunos editores que van realizando algunas tareas adicionales, por ejemplo: Si se coloca
un "if automticamente se agrega un "then", o bien cuando se trabaja con parntesis se verifica el
balanceo de expresiones.
Los "Static Chequers" son otro tipo de preprocesadores que descubren posibles ciclos sin criterio
de paro, detectar las partes de cdigo que nunca sern ejecutadas; es similar a un proceso de
optimizacin de cdigo. Es decir, se enfoca ms hacia errores lgicos o semnticos.
-1-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

En el libro se considera a un intrprete como un preprocesador, un intrprete tiene que "realizar


toda" la tarea del compilador para una lnea de cdigo, es decir, revisar lxico, sintaxis, semntica,
crear una representacin de una expresin (quizs un rbol en el caso de una asignacin) y evaluarla.
Algunas ventajas son que en algunos casos no es posible conocer cuanta memoria se utilizar para
datos, y con un compilador, habr que reservarla.
Se puede pensar tambin que durante la fase de anlisis se habla de intrpretes de QUERYS, o
procesadores de palabras, etc.
El contexto en el que se desarrolla un compilador puede variar, ya que pueden existir
preprocesadores que realicen operaciones sobre el programa fuente, tal como expansiones de macros.
Por ejemplo quiz el lenguaje original de alto nivel no tenga un WHILE, pero si estructuras IF,
entonces el preprocesador modifica el cdigo WHILE simulndolo con IF'S.
Regularmente se piensa que el compilador genera
necesariamente es cierto, pero es factible en algunos casos.

cdigo en ensamblador, esto no

CONTEXTO GENERAL DE UN COMPILADOR


ESQUELETO DE PROGRAMA FUENTE
PREPROCESADOR
PROGRAMA FUENTE
COMPILADOR
PROGRAMA OBJETO EN ENSAMBLADOR
ENSAMBLADOR
CODIGO MAQUINA RELOCALIZABLE
LIGADOR
CODIGO MAQUINA (EJECUTABLE)

Libreras para
los archivos
objeto
relocalizables.

En la parte de anlisis se tienen estas partes para un compilador:

1. Anlisis Lineal, o lexicogrfico: Separar un archivo en cadenas de caracteres (unidades


lxicas o tokens) con algn formato particular.
2. Anlisis Jerrquico o Sintctico: Se agrupan los tokens obtenidos del anlisis lexicogrfico
con alguna jerarqua (arboles).
3. Anlisis Semntico: Verifica que las estructuras tengan congruencia (verificacin de tipos
principalmente).

-2-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

ANALISIS LEXICOGRAFICO: Separacin en tokens:


a:=b+4*a*c.
LEXEMAS = { :=, b, +, 4, *, a, *, c }
TOKENS = { asig, id, op_ar, num, op_ar, id, op_ar, id }
No se consideran los espacios.
ANALISIS SINTACTICO: Es un anlisis jerrquico (parsing) que agrupa los tokens en frases
gramaticales. Es frecuente representar frases gramaticales con arboles:

ASIGNACION
IDENTIFICADOR

:=

EXPRESION

EXPRESION

IDENTIFICADOR
b

EXPRESION

EXPRESION

IDENTIFICADOR

EXPRESION

EXPRESION

IDENTIFICADOR

EXPRESION
IDENTIFICADOR

Si identificador es una expresin y


Si nmero es una expresin
Si EXP1 y EXP2 son expresiones EXP1*EXP2 y EXP1+EXP2 y (EXP1) tambin son
expresiones

As en programacin:

Si IDENTIFICADOR1 es un identificador y EXPRESION2 es una expresin entonces


IDENTIFICADOR1:=EXPRESION2 es una afirmacin.
Si EXPRESION1 es una expresin y AFIRMACION2 es una afirmacin entonces
WHILE (EXPRESION1) DO AFIRMACION2 IF(EXPRESION1) THEN AFIRMACION2 son
afirmaciones.

El rbol jerrquico se simplifica como:

:=
a

Semantico

:=
+

a
*

+
b

*
a

*
real

-3-

*
a

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

ANALISIS SEMANTICO: En programacin prcticamente son las verificaciones de tipos en


expresiones; validez de ndices en arreglos, etc.
Conceptualmente un compilador trabaja en fases, y en cada fase el programa fuente se
transforma de una representacin a otra.

PROG. FUENTE
A. LEXICO
F. ANALISIS
TABLAS DE
SIMBOLOS
F. SINTESIS

A. SINTACTICO
A. SEMANTICO
GEN. COD. INT.

MANEJADOR
DE ERRORES

OPT. CODIGO
GEN. COD. OBJ.
PROG. OBJETO

Los manejadores de tablas de smbolos y errores, no son arbitrariamente fases; interactan


implcitamente "todo el tiempo" con las otras fases.
La funcin esencial de una tabla de smbolos es almacenar los tokens ledos de un programa
fuente junto con la serie de atributos que lo definen, tales como la lnea y columna donde se encuentra
en el programa fuente, direccin de almacenamiento, tipo, tamao (en caso de strings), alcance de
variables en procedimientos, nmero de argumentos de entrada y salida, etc.
Se selecciona normalmente un registro por cada identificador, con un nmero x de campos para
almacenar los atributos del token. La informacin de esta tabla debe recuperarse rpidamente. Con
frecuencia los atributos no pueden ser detectados en la fase lexicogrfica, entonces hay que esperar el
anlisis sintctico y semntico. Se puede hablar de compiladores que se frenan cuando e xiste un error,
no obstante, algunas fases (sintctica) permiten los mecanismos necesarios para indicar el error y
continuar la revisin y atrapar as ms errores.
Para mostrar cmo funciona un compilador completo. Supongamos que se tiene el un programa
fuente con la siguiente expresin:
PRECIO := CANTIDAD + DESC * 60

-4-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

PRECIO := CANTIDAD + DESC * 60


A. LEXICO
id1 asig id2 + id3 * num
A. SINTACTICO
asig
id1

+
id2

*
id3

num

A. SEMANTICO
asig
id1

+
id2

*
id3

real(num)

GEN. COD. INT.


var1 := real(60)
var2 := id3 * var1
var3 := id2 + var2
id1 := var3
OPT. CODIGO
var1 := id3 * 60.0
id1 := id2 + var1
GEN. CODIGO
MOV R1 ,id3
MUL R2,60.0
MOV R2,id2
ADD R1 ,R2
MOV id1 ,R1
-5-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

En algunos casos es recomendable reducir el nmero de pasadas en la revisin de un archivo de


entrada, por ejemplo, normalmente se pueden mezclar las fases lxica y sintctica en una sol a pasada.
ANALISIS LEXICOGRAFICO
El analizador lxico es la primera fase de un compilador. Las principales tareas que realiza son la
lectura de caracteres de un archivo de entrada, la provisin de un token para el parser y el
almacenamiento de atributos en una tabla de smbolos tanto como sea posible. Es frecuente aadir un
analizador lxico como una simple rutina del parser.

Pide un token

PROG. FUENTE

A. LEXICO

A. SINTACTICO

Devuelve token
TABLA DE
SIMBOLOS
Al analizador lxico se le dejan normalmente tareas como:

Eliminacin de espacios, tab's, lneas en blanco.


Eliminacin de comentarios.
En algunos casos almacenar los nmeros de lnea del archivo para relacionarlos con los
errores.
La elaboracin de una copia del programa fuente con los errores sealados.

En ocasiones se separa un analizador lexicogrfico en dos fases consecutivas "scanner" para las
tareas ms sencillas y "analizador lxico para las ms complejas". Por ejemplo, un scanner se puede
encargar nicamente de la eliminacin de espacios, tabuladores, lneas en blanco y comentarios.
Distinguiendo tokens de lexemas:

TOKEN
const
if
op_rel
id
num

LEXEMA
const
if
>, <, =, >=, <=, <>
valor, i, Precio, D1
3, 3.5, -7, -12.3e-15

Los tokens son tratados


como elementos
terminales del lenguaje

Cuando un token se asocia con ms de un lexema se debe almacenar informacin adicional para
que pueda ser distinguido en las siguientes fases, tal es el caso del token num y del token id:

-6-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

VAR1
*
3
=

<id, apuntador a la tabla de smbolos para su lexema>


<*, >
<num, valor 3>
<op_rel, igual>

Algunas tareas sofisticadas, pero que pueden confundir al parser en un analizador lxico, son:

Borrar caracteres extraos.


Insertar un carcter donde se requiera.
Remplazar un carcter incorrecto por uno correcto.
Invertir dos caracteres adyacentes, etc.

El analizador lxico es prcticamente la nica fase que leer el archivo de entrada carcter por
carcter, lo cual puede llevar mucho tiempo.
Una tcnica para agilizar esta tarea, es leer los caracteres en un buffer de tamao 2n partido por
la mitad, y colocar dos apuntadores, (Ap_inicio, Ap_avance); al principio ambos se encuentran en el
carcter de inicio del lexema a leer, y Ap_avance, avanza carcter por carct er hasta formar un lexema
que pueda ser asociado, en ese momento, se empatan Ap_inicio y Ap_avance en el inicio del siguiente
lexema, si Ap_avance llega al fin de la primera mitad del buffer, llama a la segunda mitad del buffer, si
Ap_avance llega al final de la segunda mitad, llena la primera mitad, y avanza al principio de la
primera. Esto no representa problemas si el analizador no tiene que hacer visitas adelantadas, pero si
requiriera visitas adelantadas, hay problemas en caso de que la cantidad adelan tada de caracteres sea
mayor que n.

2n
n

n
/0

Ap_ini

/0

Ap_ava

n-izq.
LENGUAJES.

ALFABETO: Conjunto finito de smbolos.


STRING: Secuencia finita de smbolos pertenecientes a un alfabeto.
LENGUAJE: Conjunto de strings sobre un determinado alfabeto.
La longitud de un string

se denota por | |. As | |=0, donde

denota la cadena vaca.

Si y son dos strings, la concatenacin de los strings denotada por


es la aadidura de
El elemento de identidad para la concatenacin es la cadena vaca , ya que
.
para

Si se piensa la concatenacin como un producto y exponenciacin, definimos


entonces

-7-

a .

, y definimos

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Existen algunos trminos asociados con strings:


PREFIJO DE S: El string obtenido quitando smbolos de S cero o ms veces desde una posicin
hasta el final, tambin es un prefijo de S.
SUFIJO DE S: El string obtenido quitando smbolos de S cero o ms veces desde el principio
hasta cierta posicin, tambin es un prefijo de S.
SUBSTRING DE S: El string obtenido borrando un PREFIJO y un SUFIJO de S. Ambos S y
substrings de S.

son

PREFIJO, SUFIJO, SUBSTRING PROPIO DE S: Un string X prefijo, sufijo o substring


respectivamente, tal que
.
SUBSECUENCIA: El string obtenido borrando 0 o ms smbolos de S no necesariamente
continuos.
Para la implementacin del anlisis lxico existen tres importantes operaciones aplicadas a
lenguajes, la unin, la concatenacin y la cerradura. Si extendemos el concepto de exponenciacin a
lenguajes, (denotando con letras maysculas un lenguaje; ej : D = {O, 1, 2, 3, 4, 5, 6, 7, 8, 9})
obtenemos las siguientes operaciones:
Unin de L y M
Concatenacin de L y M

{ |
{ |

Cerradura de L

(L es 0 o ms concatenaciones de L)

Cerradura positiva de L

(L es 1 o ms concatenaciones de L)

Ej : Sean A = { A, B, , Z, a, b, , z} y B = { 0, 1, , 9} dos alfabetos, (se pueden observar


como lenguajes). Se pueden crear algunos otros lenguajes como:
1.2.3.4.5.6.7.EXPRESIONES REGULARES
Existe una notacin con la que se pueden representar lenguajes como el ejemplo (6) anterior,
utilizando parntesis, el smbolo de alternacin |, * y +. As
|
es similar a (6).

-8-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

De esta manera, una expresin regular sobre un alfabeto puede generar un lenguaje particular,
este lenguaje se denota como L(r) dada la expresin regular r. Algunas reglas que definen una
expresin regular sobre y los lenguajes generados son :
1.-

es una expresin regular que denota el lenguaje {

}.

2.- Si a es un smbolo en , entonces a es un expresin regular que denota el lenguaje {a}.


3.- Si r y s son expresiones regulares que generan los lenguajes L(r) y L(s) respectivamente,
entonces:
a).- (r) | (s) es una expresin regular denotando
.
b).- (r)(s) es una expresin regular denotando
.
c).
es una expresin regular denotando
.
d).es una expresin regular denotando
.
Un lenguaje denotado por una expresin regular se llama conjunto regular. Pueden omitirse
muchos parntesis en un expresin regular si se asume:
1.- El operador * tiene la jerarqua ms alta.
2.- La concatenacin tiene la segunda jerarqua.
3.- La alternacin | tiene la ms baja jerarqua.
4.- Los tres anteriores son asociativos por la izquierda.
es equivalente a

|
Ej:
1).2).3).4).-

|
|

En el ejemplo (4) las dos expresiones son equivalentes denotadas con un signo igual r=s.
Las expresiones regulares tienen las siguientes propiedades
AXIOMA
|
|
| |
|

|
|
|

DESCRIPCION
| es conmutativo
| es asociativo
La concatenacin es asociativa
La concatenacin es distributiva sobre |
es el elemento idntico para la concatenacin

* es idempotente
DEFINICIONES REGULARES

Es conveniente etiquetar cada expresin regular con un nombre. Dado un alfabeto


definicin regular es una secuencia de definiciones de la forma:

, una

.
.
.

-9-

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

donde cada
{

es un nombre distinto y cada


. No se vale la recursin.

es una expresin regular de smbolos sobre

Ej 1:
| | | | | |
| | |
|

Ej 1:
| |

|
|
|

Reduciendo la notacin
1.- Utilizando la cerradura positiva, dada
entonces
y
| .
2.- Utilizando el signo (-), dada
| .

quiere decir "una o ms veces", se genera

, quiere decir "cero o una vez", entonces

3.- Utilizando parntesis cuadrados para clases de caracteres se tiene | |


, y se pueden expresar expresiones regulares como
|

genera

y | | |

| como

As la definicin regular anterior es:


| |

|
|

CONJUNTOS NO REGULARES
Existen algunos conjuntos que no pueden ser expresados con una "expresin regular", pero s con
una gramtica de contexto libre. No obstante, existen algunos conjuntos que no pueden ser
expresados ni an con una gramtica de contexto libre.
Se puede pensar que en un archivo de entrada, los identificadores van separados por espacios o
tabs o newlines. Entonces se puede hacer una definicin regular para este propsito:
|

Con lo anterior, si el analizador lexicogrfico encuentra un separador, no hay que hacer nada. El
objetivo de un analizador lexicogrfico es analizar la entrada y devolver al parser un par, el token
- 10 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

asociado y el atributo correspondiente al token, por ejemplo : Considerando LT, GE, GT, EQ como
constantes

EXPRESION
REGULAR
separador
if
then
else
id
num
<
>
>=
=

TOKEN

ATRIBUTO

if
then
else
id
num
op_rel
op_rel
op_rel
op_rel

Apuntador a la tabla de smbolos


Apuntador a la tabla de smbolos
LT
GT
GE
EQ

DIAGRAMAS DE TRANSICION
Un diagrama de transicin es una grfica que describe las acciones seguidas por un analizador
lexicogrfico cuando un token es encontrado, los diagramas de transicin se forman con flechas
etiquetadas con los caracteres que se deben asociar a la entrada, conectados a crculos llamados
estados para indicar la transicin de un estado a otro por medio de la flecha etiquetada.
El diagrama cuenta con una flecha para el estado inicial y un crculo doble indica el estado final.
Ej: para operadores relacionales

<

return(op_rel, LE)

>

return(op_rel, NE)

otro

* return(op_rel, LT)

return(op_rel, EQ)

return(op_rel, GE)

otro

* return(op_rel, GT)

>
6

El asterisco significa que hay que regresar el apuntador en el buffer (Ap_avance) una posicin
para que dicho carcter sea reledo y pasado por otro diagrama de transicin. Si no se puede hacer la
transicin de un estado a otro, y hay ms posibilidades, se trata de hacer la transicin con la siguiente
posibilidad, y si con ninguna se logra, ha ocurrido un error lxico. Se asume adems, que los
diagramas de transicin son deterministicos, es decir, entre otras cosas, no se permiten dos o ms
flechas saliendo del mismo estado. Cuando se tienen varios diagramas de transicin si no se logra
- 11 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

trazar el camino en uno de ellos por medio de la entrada, se pasa al siguiente diagrama, si ya no
existen ms diagramas donde buscar ocurre un error lxico:

digito
9

digito

10

digito

11

digito

12

digito
13

+o-

14

digito

18

15

otro

16

digito

digito
17

digito

digito

19

digito

24

20

otro

21

digito
22

digito

23

otro

digito
25

letra

26

otro

27

letra

Los diagramas equivalen a:


|
|
Es importante observar en los diagramas para reconocimiento de nmeros que el proceso requiere
en ocasiones del cambio de diagrama para llegar a un estado de aceptacin. Por ejemplo, para
reconocer un 12.5 comenzamos con el estado de inicio 9 y se leen 2 dgitos 1 y 2, y posteriormente un
. y luego un 5 quedando en el estado 12, si luego viene otra cosa como un =, no se puede hacer la
transicin as que se debe cambiar al diagrama que empieza con 17, y se vuelven a hacer todas la s
transacciones de nuevo, al repasar 1, 2, ., 5 se llega al estado 20; luego al leer = se puede llegar al
estado de aceptacin 21 con lo que el 12.5 queda reconocido. Por esto, el orden de los diagramas es
importante y es precisamente el mostrado anteriormente, de otra manera el reconocimiento puede
fallar.
En lugar de construir los 3 diagramas para el reconocimiento de nmeros, podemos construir un
nico diagrama ms robusto agregando ms estados de aceptacin y renumerando todos los estados
para tener lo siguiente:

- 12 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

digito
9

digito

10

digito
11

digito

12

digito
13

E
otro

17

+o-

14

digito

15

otro

16

digito

otro

18

digito
19

letra

20

otro

21

letra
Un diagrama de transicin para eliminar los espacios (tabs, espacios y CR) es:

delim
22

delim

23

otro

27

IMPLEMENTACION DE UN DIAGRAMA DE TRANSICION


Para implementar diagramas de transicin se hacen dos procesos fundamentales. Uno para
seleccionar que diagrama utilizar y otro para simular el recorrido a travs del diagrama.
El tamao del programa es proporcional al nmero de estados en los diagramas de transicin,
porque cada estado genera un fragmento de cdigo, si salen dos flechas a ms de un estado, se lee el
carcter siguiente, y con ste se selecciona el camino a seguir. Se asume que al leer un carcter del
buffer se recorre automticamente Ap_avance. Si hay una flecha en el estado actual que se asocie con
el carcter ledo, se transfiere el control al siguiente estado indicado por la flecha; si no se asocia con
ninguna flecha, se llama a un proceso que permita seleccionar otro diagrama de transic in. Este ltimo
proceso se muestra a continuacin; utiliza dos variables ESTADO y COMIENZO; ESTADO contiene el
nmero del estado actual, y COMIENZO contiene el nmero del estado inicial del diagrama actual. Las
rutinas para el cambio de diagrama y la simulacin de los diagramas se basan en los diagramas
mostrados anteriormente y el que sigue para identificadores:
FUNCION lee_car():carcter
carac=car[Ap_avance]
Ap_avance=Ap_avance + 1
RETURN(carac)
FIN FUN
FUNCION diagrama():entero
Ap_avance = Ap_inicio
Caso de
COMIENZ0=0:
COMIENZ0=9
COMIENZ0=9:
COMIENZ0=19
COMIENZ0=19:
COMIENZ0=22
COMIENZ0=22:
error()
Fin caso
- 13 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

return(COMIENZO)
FIN FUN
FUNCION TOKEN():cadena
Repite
Caso ESTADO=0
C=lee_car()
Caso C='<'
ESTADO=1
Caso C='='
ESTADO=5
Caso C='>'
ESTADO=6
Otro
ESTADO=diagrama()
Fin caso
Caso ESTADO=1
C=lee_car()
Caso C='='
ESTADO=2
Caso C='>'
ESTADO=3
Otro
ESTADO=4
Fin caso
Caso ESTADO=2
Ap_inicio=Ap_avance
TokenVal='EQ'
return(op_rel)
.
.
.
Caso ESTADO=4
Ap_avance=Ap_avance-1
Ap_inicio=Ap_avance
TokenVal='LT'
return(op_rel)
.
.
.
Caso ESTADO=21
Ap_avance=Ap_avance-1
TokenVal=Anexa_Lex() /* Anexa a taba, devuelve apuntador */
Ap_inicio=Ap_avance
return(id)
.
.
.
Caso ESTADO=27
Ap_avance=Ap_avance-1
ESTADO=0
Fin caso
Fin repite
FIN FUN
Comienza
Ap_inicio=1
- 14 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Ap_avance=1
escribe("Digitar cadena y al final *")
lee(cad)
Repite
ESTADO=0
COMIENZ0=0
T=TOKEN()
escribe("Token encontrado: ",T)
Ap_inicio=Ap_avance
Hasta(car[Ap_avancej="*")
Termina
AUTOMATAS NO-DETERMINISTICOS
Un autmata finito es un diagrama que permitir saber si una cadena es o no aceptada por una
expresin regular. Un NFA es un modelo matemtico que consiste de:
1.- Un conjunto S de estados.
2.- Un conjunto de smbolos de entrada .
3.- La funcin de transicin " mueve" que mapea pares estado-smbolos hacia un conjunto de
estados.
4.- Un estado de inicio .
5.- Un conjunto de estados de aceptacin o finales F.
Diagramticamente se ve como un grato dirigido. Ej:

A={a,b}

Expresin:

Estados del NFA={0,1,2,3},

F={3}

a
0

b
El autmata puede ser representado fcilmente en una computadora como una matriz.

ESTADOS
0
1
2

SIMBOLOS
a
b
{0,1}
{0}
{2}
{3}

Por ejemplo, el NFA acepta aabb como:

Se debe llegar al estado de aceptacin.


Ejemplo: para

|
- 15 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

a
1

b
AUTOMATAS FINITOS DETERMINISTICOS
Un DFA es un caso particular de un NFA en el cual:
1.- No hay estados con una
.
2.- Para cada estado S y cada smbolo "a" hay cuando ms una flecha saliendo de S etiquetada
por "a".
Si se elabora una matriz para un DFA, sta contiene exactamente como elementos un estado.
Ejemplo:
|

b
b
0

a
a

ALGORITMO PARA SIMULAR UN DFA


Se recibe una cadena de entrada y al final la marca de fin de archivo, se inicia con el estado 0, y
se usa la funcin mueve(S,C), que devuelve el siguiente estado movindose a partir del estado S a
travs de C. Adems se tiene un conjunto F de estados de aceptacin.
Comienza
S=So
C= lee_car()
Mientras C<>
S=mueve(S,C)
C = lee_car()
Fin mientras
- 16 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Si (S F) entonces
Aceptada
otro
Rechazada
Fin si
termina

CONVERSION DE UN NFA EN UN DFA


El motivo de la conversin es el siguiente: En un NFA existen muchos caminos diferentes para
hacer una transicin de un smbolo x de entrada, y es probable que seleccionando un camino se logre
reconocer una cadena de entrada, pero tambin es probable que se seleccione justamente el camino
equivocado. Como saber cul es el correcto?, pues solamente recorriendo todas las transiciones
posibles.
Si se intenta recorrer todas las transiciones posibles, puede crecer la bsqueda exponencialmente
y consecuentemente ser un proceso muy lento.
En contraparte, un DFA no permite mas que un solo camino, lo cual es mucho ms eficiente para
implementarse en un programa, pero el problema radica en que es muy difcil construir un DFA de
primera intencin. A continuacin se presenta un algoritmo que convierte un NFA (que es sencillo
elaborar) en un DFA. No obstante este algoritmo de conversin puede crecer exponencialmente en
tiempo de ejecucin.
Antes de mostrar el algoritmo se explican algunas funciones requisito para el algoritmo:
A).-

: Indica el nuevo estado de transicin de un estado

a travs de un carcter a

Ejemplo:

a
c

3
b

c
mueve(0,a) = 1
mueve(1 ,b) = 2
B).-

mueve(1,a) =1
etc.

: Donde T es un conjunto de estados, indica las transiciones sobre cada elemento del
conjunto.
Considerando el diagrama anterior. Ejemplo:

T={0,1,2}
mueve(T,a) = { 1,2 }
mueve(T,b) = { 2,3 }
C).-

: Estados de un NFA que pueden ser visitados al recorrer el NFA a travs de transiciones con comenzando por el estado S inclusive.

- 17 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Ejemplo:

= { 1,2,4,5,6,7 }
C).-

: Donde T es un conjunto de estados. Es aplicar la


de los elementos de T.
{

para cada uno

= { 1,2,3,4,6,7,8 }

ALGORITMO
D: Conjunto de conjuntos de estados
AUTO: Matriz para representar el DFA obtenido
So: Estado inicial del NFA
comienza
D contiene a -cerradura(So) sin marcar
Mientras haya un T sin marcar en D
Marcar T
Para cada smbolo a hacer
U=-cerradura(mueve(T,a))
Si U no esta en D entonces
aade U a D sin marcar
Fin si
AUTO[T,a]=U
Fin para
Fin mientras
termina
CONSTRUCCION DE UN NFA A PARTIR DE UNA EXPRESION REGULAR
A continuacin se presenta un algoritmo para construir un NFA a partir de una expresin regular
considerando la concatenacin, la alternacin y la cerradura.
ALGORITMO
Entrada.- Expresin regular "r" sobre un alfabeto .
Salida.- NFA aceptando L(r).
- 18 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Mtodo.- Primero se construyen NFA's muy sencillos para cada smbolo en , y para como se
muestra en (1) y (2).
Posteriormente, usando la estructura sintctica de la expresin regular "r", se van combinando los
incisos de (3). Los NFA's obtenidos tienen exactamente un estado inicial (al que no entran flechas) y
un estado final (del que no salen flechas).
1.- Para construir el NFA:

inicio

2.- Por cada a en construir el NFA:

a
inicio

3.- Suponga que N(s) y N(t) son NFA's para las expresiones "s" y "t" respectivamente.
a).- Para la expresin regular s|t se construye el NFA N(s|t) como:

N(s)

inicio

N(t)

b).- Para la expresin regular "st" se construye el NFA N(st) como:

N(s)
inicio

c).- Para la expresin regular

N(t)

se construye el NFA

- 19 -

como:

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

inicio

N(s)

d).- Para expresiones en parntesis como (s) usar N(s).


ALGORITMO PARA SIMULAR UN NFA
El siguiente algoritmo sirve para simular un NFA, devuelve un "si" si una cadena X es aceptada por
el autmata:
S=-cerradura({So})
a= lee_car()
MIENTRAS a <>
S=-cerradura(mueve(S,a))
a=lee_car()
FIN MIENTRAS
SI SF <> {} ENTONCES
aceptada
OTRO
no aceptada
FINSI

ANALISIS LEXICOGRAFICO
En programacin se distinguen cuatro elementos fundamentales:

Palabras reservadas (if, while, begin, end, div, mod, etc.).


Operadores (<, :=, ==, >=, +, *, etc.).
Identificadores (variables, constantes, etiquetas, proc., etc.).
Nmeros (enteros, reales, hexadecimales, etc.).

Cuando una secuencia de dgitos es encontrada en el analizador lxico, se pasa el token (#, num,
etc.) al parser; aunque en alguna parte se debe almacenar el valor del numero en cuestin. Por
ejemplo, en parejas:
19 + 20 + 21
<#,19> <+,> <#,20> <+,> <#,21>
De la misma manera, cuando se tienen identificadores, al parser se le pasa un token como "id"
simplemente, aunque el lexema y sus atributos son almacenados en alguna parte. As
CONT = CONT + SUMA

id= id + id
- 20 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Se debe conocer si un lexema ya ha sido encontrado con anterioridad, esto es viable con una
tabla de smbolos, donde se almacena el lexema, un apuntador y algunos Atributos asociados Al
lexema. La forma de distinguir entre identificadores y palabras reservadas, es fcil, ya que las palabras
reservadas son conocidas con anterioridad, normalmente se almacenan en alguna otra parte. En
muchas ocasiones el analizador lexicogrfico debe adelantarse a leer algunos caracteres ms ( >= )
para decidir que es, y hay que regresarse en ocasiones porque se est tomando un carcter de ms,
pero del siguiente token.
El analizador lexicogrfico se puede integrar al parser como un simple procedimiento.
Una forma til de implementar una tabla de smbolos es como sigue:

TABLA DE SIMBOLOS

Ap
1
2
3
4
5

Token
id
mod
num
div
id

Atributos

c o n t /0
Arreglo de lexemas

/0

/0

Lo conveniente en el anlisis lexicogrfico es la eliminacin de los espacios, los tabuladores, y la


lneas en blanco, ya que si se eliminan, no tendrn que ser analizadas por el parser. Es posible
considerarlos en la gramtica, pero resulta problemtico.
El caso de los nmeros puede ser implementado en la gramtica, haciendo producciones para la
sintaxis de un nmero, pero se deja esta tarea al analizador lxico. Este se encarga de recolectar
secuencias de dgitos; de esta manera son tratados como un simple token en al analizador sintctico.
ANALISIS SINTACTICO
Se presenta una GRAMATICA DE CONTEXTO LIBRE o BNF (Backus-Naur Form).
GRAMATICA DE CONTEXTO LIBRE.
1.2.3.4.-

Conjunto de terminales
Conjunto de no terminales
Producciones
Smbolo inicial de la gramtica.

- 21 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

1) LISTA
2) LISTA
3) LISTA
4) DIGITO

LISTA + DIGITO
LISTA - DIGITO
DIGITO
0|1|2|3|4|5|6|7|8|9

As, 9-5+2
a.- 9 es una lista, y es un dgito por 3)
b.- 9-5 es una lista por 2), 9 es lista y 5 dgito
c.- 9-5+2 es lista por 1) 9-5 es lista y2 dgito

LISTA

LISTA

LISTA

DIGITO

DIGITO

DIGITO

9
Existe la notacin de para indicar cadenas vacas.
ARBOL DE PARSER
Dada una produccin X A B C

raiz (no terminal)

X
A

Hijos(no terminal), hojas(terminal)

Un ARBOL DE PARSER se forma por:


1.2.3.4.-

La raz es el smbolo inicial de la gramtica.


Cada hoja es etiquetada por un token o por .
Cada hijo ( nodo ) es etiquetado por un no terminal.
Consecuentemente, un rbol de raz A con
o no terminales, es una produccin
.

- 22 -

como hijos, sean terminales

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

En el caso particular A, el rbol tiene un solo hijo llamado .


Una gramtica es ambigua si tiene dos o ms rboles distintos de parser por ejemplo:

EXP EXP + EXP


EXP EXP - EXP
EXP 0|1|2|3|4|5|6|7|8|9

Para 9-5+2 se puede expandir


por la derecha o por la izquierda.

Expansin por derecha izquierda.

EXP

EXP

EXP

EXP

EXP

EXP

EXP

EXP

EXP

EXP
2

En contraparte, la siguiente gramtica produce el mismo lenguaje pero no es ambigua.

LISTA
LISTA
LISTA
DIGITO

DIGITO + LISTA
DIGITO - LISTA
DIGITO
0|1|2|3|4|5|6|7|8|9

El orden natural es que ( + y -) y (* y / ) sean asociados por la izquierda, es decir, al expandir el


rbol con la gramtica anterior para 9 - 5 + 2 quedara:

LISTA
DIGITO

LISTA

DIGITO

LISTA
DIGITO
2

Perser es el proceso mediante el cual se determina si un string de tokens puede ser generado por
una gramtica. Existen mtodos top-down y bottom up.
Para hacer la expansin de un rbol de sintaxis e ir asociado con el rbol una cadena de entrada,
se comienza con el smbolo inicial de la gramtica, y se toma el primer token de la entrada y se busca
la produccin que derive el no-terminal y que comience con el token de entrada. Con dicha produccin
se construyen las ramas para el nodo. En caso de que uno de los hijos se asocie con uno de los
smbolos de entrada, se recorre el rbol de izquierda a derecha hacia el siguiente hijo y tambin se
toma el siguiente token de la entrada.
- 23 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

TIPO SIMPLE | id | array [SIMPLE] of TIPO


SIMPLE integer | char | #..#
Probar la entrada : array [ # .. #] of integer
En este caso se puede presentar "backtrack", porque se seleccione una produccin incorrecta.
Existen m,todos en los cuales no ocurre el backtrack, estos son los parsers predictivos.
En el anlisis sintctico es recomendable utilizar un modelo matemtico conocido como gramtica
de contexto libre (BNF), ya que:
Una BNF expresa una estructura sintctica clara.
Con algunas clases de gramticas es muy fcil construir un programa metdico que revise
sintaxis, adems que la BDF muestra posibles ambigedades en el diseo de la gramtica
que podran no ser detectadas sin su elaboracin.
Un diseo adecuado por medio de una gramtica permite una fcil translacin a cdigo
intermedio u objeto.
Es ms sencillo hacer correcciones o ampliar el lenguaje.

FRONTERA PARSER-LEXICO
En la construccin de un compilador es recomendable utilizar una gramtica de contexto libre para
especificar sintaxis y una definicin regular para la estructura de tokens, es decir, el anlisis lxico, as
considere la gramtica:

AFIRMACION
AFIRMACION
AFIRMACION
EXP
TERMINO

if EXP then AFIRMACION


IF EXP then AFIRMACION else AFIRMACION

TERMINO op_rel TERMINO | TERMINO


id | num

Para los terminales if, then, else, op_rel, id, num construimos una definicin regular como:

|
| |
| |

| |
| | | |
|
|

|
|

- 24 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Peticion
Programa
Fuente

ANALIZADOR
LEXICO

ANALIZADOR
SINTACTICO

Arbol de Parser

RESTO DEL
FRONT END

Token

TABLA DE
SIMBOLOS
Existen mtodos generales para procesos de parser, pero son demasiado ineficientes, por lo cual
se prefieren mtodos como el top-down y el bottom-up El primero construye rboles sintcticos de la
raz a las hojas y el segundo de las hojas a la raz. En ambos casos se revisa la entrada de izquierda a
derecha tomando un smbolo a la vez.
Los parsers top-down y bottom-up ms eficientes trabajan sobre subclases de gramticas como
las LL o las LR, y con estas gramticas se pueden implementar prcticamente todos los lenguajes
actuales de programacin.
PARSER RECURSIVO-DESCENDENTE
Es un mtodo de parser top-down. Este m,todo asocia un procedimiento, o una funcin por cada
elemento no terminal de la gramtica. El procedimiento seleccionado esta en funcin del smbolo de
entrada. La ejecucin de los procedimientos durante la ejecucin, implcitamente define el rbol de
parser para la entrada. Se aade un procedimiento para la asociacin de los tokens de entrada con los
tokens de la gramtica.
Ejemplo:

TIPO SIMPLE | ^id | array [SIMPLE] of TIPO


SIMPLE integer | char | #..#

PROC asocia(token)
comienza
Si CABEZA = token entonces
CABEZA = SIG_CABEZA
otro
Error()
Fin si
termina
PROC tipo()
comienza
CASO DE
CABEZA ={integer o char o #}
simple()
CABEZA = ^
asocia(^)
asocia(id)
CABEZA = array
asocia(array)
asocia([)
simple()
asocia(])
asocia(of)
- 25 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

tipo()
OTRO
Error()
FIN CASO
Termina
PROC simple()
comienza
CASO DE
CABEZA = integer
asocia(integer)
CABEZA = char
asocia(char)
CABEZA = #
asocia(#)
asocia(.)
asocia(.)
asocia(#)
OTRO
Error()
FIN CASO
termina
Este parser utiliza informacin sobre los primeros smbolos de la parte derecha de las
producciones; esto es, sobre los conjuntos FIRST.
As
FIRST(simple) = {integer,char,#}
FIRST(^id) = {^}
FIRST(array [SIMPLE] of TIPO) = {array}
Cuando se tienen producciones A y A , el parser recursivo descendente requiere que
FIRST( )<>FIRST( ) para poder decidir por medio del smbolo de entrada que produccin tomar, si
CABEZA esta en FIRST( ) se toma A , si CABEZA esta en FIRST( ) se toma A . Si la gramtica
no est diseada como se indica, habr que factorizarla.
En caso de que se tengan -producciones, se deben tratar con cuidado. El parser recursivo
descendente usa una -produccin cuando no existe el smbolo de entrada en el FIRST de la parte
derecha de la produccin en cuestin.
FACTORIZACION DE UNA GRAMATICA
Si se tienen producciones de la forma

A a | a
el parser no podr decidir que produccin usar porque ambas comienzan en la parte derecha con
"a". Esto se soluciona reemplazando las producciones por

A aA'
A' |
Esta regla se puede generalizar como sigue:
Para cada no terminal A se encuentra el prefijo ms grande comn a dos o ms producciones y
- 26 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

se reemplazan las A-producciones

por

NOTA: puede ser


| |

Para el diseo de un parser recursivo descendente se requiere:


1.- Una gramtica
2.- Eliminar recursin izquierda y factorizarla.
3. - Adems:
- El parser decide qu produccin usar por medio del token de entrada. Se selecciona la
produccin que contiene el token de entrada en el FIRST() donde es la parte derecha de la
produccin. Si hay un conflicto con los lados derechos y el token de entrada, no se puede utilizar el
mtodo.
- El mtodo usa un procedimiento por cada no-terminal, simulando la parte derecha de la
produccin. Un no-terminal es la llamada a un procedimiento (derivacin de una produccin) y un
terminal llama a un proceso de asociacin entre l y el smbolo de entrada, si no se puede asociar,
ocurre un error. En caso de que el no-terminal derive a , si el token de entrada no puede usar
ninguna de las partes derechas, se selecciona justamente la produccin de (es decir, no se debe
hacer nada, ya que si existe error ser detectado posteriormente).
RECURSION IZQUIERDA
Una gramtica no debe ser recursiva izquierda para construir un parser recursivo descendente.
Por ejemplo:

A A
A
Si se usan producciones corno esta, el proceso en computadora entra a un loop sin fin. El proceso
de eliminacin es sencillo y se trata de eliminar la recursividad izquierda convirtindola a recursividad
derecha:

A A'
A' A' |

Esta regla se puede generalizar como:


Se agrupan todas las producciones de A en la forma:
|

| | |

donde ninguna ai comienza con A. Despus se sustituyen las producciones de A por:


|

Existen casos en que la recursin no es inmediata y hay que aplicar otro proceso.
CALCULO DEL CONJUNTO FIRST
Aplquense las 3 reglas siguientes para todos los smbolos gramaticales (terminales y no-

- 27 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

terminales), hasta que no se puedan aadir ms elementos al conjunto.


1.- Si X es un terminal, entonces FIRST(X ) es {X }.
2.- Si X es una produccin, aadase al FIRST(X ).
3.- Si X es un no-terminal y adems
es una produccin, entonces aadase al
FIRST(X ) el FIRST( ) excepto . Si FIRST( ) contiene a entonces tambin debe aadirse
FIRST( ) a FIRST(X ) excepto . Si FIRST( ) y FIRST( ) contiene a , deber aadirse
FIRST( ) a FIRST(X ) excepto , y as sucesivamente. Y por ltimo, si ocurre que para toda i
el FIRST( ) contiene a , entonces deber incluirse una sola vez en FIRST(X).
Una vez comprendidas las reglas anteriores, tambin se puede calcular el First de cualquier
cadena
. Este proceso es similar a la regla 3 mencionada arriba.
Se aade al FIRST(
) el FIRST( ) excepto . Si FIRST( ) contiene a entonces
tambin debe aadirse FIRST( ) a FIRST(
) excepto . Si FIRST( ) y tambin FIRST( )
contiene a , deber aadirse FIRST( ) a FIRST(
) excepto , y as sucesivamente. Y por
ltimo, si ocurre que para i=1,2,...,n el FIRST( ) contiene a , entonces deber incluirse una sola vez
en FIRST(
).
PARSERS CON TABLAS PREDICTIVAS
Estos mtodos tienen la ventaja de permitir la generalidad, es decir, se pueden construir
generadores de revisores sintcticos (parsers) en funcin de una gramtica de contexto libre. El
esquema general de funcionamiento es

Entrada

Pila
X
Y

ANALIZADOR
SINTACTICO

Emite un
diagnstico

TABLA
PREDICTIVA
(Selecciona la
produccin
adecuada)
La tabla predictiva es un arreglo matricial que permite seleccionar la produccin adecuada para ir
asociando los tokens de la cadena de entrada por medio de la pila.
Para la construccin de los parsers con tabla predictiva, es necesario la elaboracin de otros
conjuntos, los FOLLOW's.
CALCULO DE CONJUNTOS FOLLOW
Para construir el conjunto FOLLOW( A) para todos los no-terminales A, se aplican las reglas
siguientes hasta que no se pueda aadir nada ms a los conjuntos FOLLOW:
1.- Aadase al FOLLOW(S ) dnde S es el smbolo inicial de la gramtica.
- 28 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

2.- Si hay una produccin A B , FOLLOW(B ) contiene a FIRST() excepto .


3.- Si hay una produccin A B o una produccin A B
todo lo que est en FOLLOW(A ) se aade al FOLLOW(B ).

donde FIRST() contenga ;

GRAMATICAS LL(1)
Las gramticas LL(1) son un subconjunto de las gramticas de contexto libre que cumplen con
que dadas dos producciones distintas de G como A | :
1.- Para ningn terminal "a" y derivan a la vez cadenas que comienzan con "a".
2.- A lo sumo una de y puede derivar .
3.- Si *, no deriva ninguna cadena que comience con un terminal en el FOLLOW( A ).
La primera L quiere decir "left to right", recorrido de la cadena de izquierda a derecha, y la
segunda L por leftmost derivation", derivaciones por la izquierda. El 1, es porque se utiliza el anlisis
de un solo smbolo de entrada a la vez para las decisiones del parser.
Para este tipo de gramticas se puede construir una tabla predictiva LL(1) con la cual se puede
seleccionar la produccin adecuada durante la revisin de una cadena de entrada. La tabla es un
arreglo matricial de
donde los renglones se encabezan con los no-terminales y las columnas con
los terminales inclusive , o viceversa.
CONSTRUCCION DE UNA TABLA LL(1)
Para cada produccin A de la gramtica hacer:
1.- Por cada terminal "a" en el FIRST() adase A a M[A,a].
2.- Si est en FIRST(), adase A a M[A,b] para cada terminal "b" del FOLLOW( A ). Si
est en FIRST() y est en FOLLOW(A ), adase A a M[A,].
3.

Cada entrada no definida en la tabla es error.


PRUEBA DE UNA CADENA DE ENTRADA CON EL PARSER LL(1)

El parser funciona con una pila, que en un principio contiene en el fondo el smbolo terminal de la
gramtica(), y en el tope el smbolo inicial de la gramtica. La cadena a ser revisada debe tener hasta
el final el smbolo terminal de la gramtica. El parser toma el elemento X del tope de la pila, y un
elemento "a" de la cadena a ser revisada, con estos dos elementos el parser decide que accin realizar,
a saber, hay cuatro posibilidades :
1.- Si X=a= el anlisis ha terminado y quiere decir que la cadena ha sido revisada con xito.
2.- Si X=a<> el parser saca a X de la pila y lee el siguiente token de la cadena de entrada.
3.- Si X<>a y X es un terminal hay error.
4.- Si X es un no terminal, se consulta el elemento M[X,a] de la tabla predictiva, este elemento de
la tabla ser una produccin o un error. Si la entrada de la tabla es una produccin, por ejemplo,
M[X,a]=X A + C, se sustituye X por la parte derecha de la produccin en orden inverso C + A, de tal
modo que quede A en el tope de la pila. Si M[X,a]=error, el parser llama a una rutina de error.
Pseudocdigo:

- 29 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

a=lee_token()
Repite
pop(X)
Si(a= y X=) entonces
Aceptada
Otro
Si(X es terminal) entonces
Si(X=a) entonces
a= lee_token()
otro
Error()
Fin si
otro
Si(M[X,a]=XY1 Y2 ... Yk) entonces
Para i= k hasta 1
Push (Yk)
Finpara
otro
Error()
Finsi
Finsi
Hasta (X=)

NOTA: Por facilidad de manejo, en la tabla predictiva se guarda con frecuencia solamente un
nmero que indica la produccin por la que hay que reducir en la pila.
RECUPERACION DE ERRORES EN PARSERS LL(1)
Una tcnica que pudiera ser til para la recuperacin de los errores en este mtodo, es hacer lo
siguiente:
Se agregan a la tabla las entradas M[A,a]=sinc (sincronizacin) donde "a" son los elementos de
FOLLOW(A). Si existe colisin con una produccin, se prefiere (obviamente) la produccin.
La forma de utilizar la tabla es, si M[A,a]=sinc se saca el no-terminal del tope de la pila y se
contina con el anlisis. Si M[A,a] est en blanco, el parser se salta el token de entrada y continua con
el anlisis. Utilizando este mtodo hay posibilidad de que si se detecta un error, se ignore (previa
indicacin de que ha ocurrido un error), y pueda seguir la revisin. La tcnica anterior es heurstica,
por lo cual puede variar dependiendo de la gramtica, adems debemos tener cuidado en que la
tcnica no entre a un ciclo sin fin.
Quizs la tcnica puede mejorarse si se hace un anlisis ms a conciencia de los posibles errores
que pueden ocurrir, y con esto, colocar en la tabla en lugar de la palabra "si nc" o dejarla en blanco, la
llamada a un procedimiento especfico para recuperar ese error particular y hacer la indicacin.
ANALIZADORES SINTACTICOS LR
Otra tcnica para la revisin sintctica, son los analizadores LR que viene del ingls "L -left to
right" que es el recorrido de la cadena de entrada de izquierda a derecha, y la "R-rightmost derivation"
que son derivaciones por la derecha, ya que en este mtodo se parte de las hojas del rbol para llegar
a la raz (al inverso del LL(1)), y el 1 porque se utiliza un slo smbolo de entrada a la vez para tomar
las decisiones del parser.
Estos analizadores sintcticos requieren de mayor trabajo y mayor espacio para su
funcionamiento, no obstante, aceptan una gama ms amplia de gramticas. Se vern tres tipos del
- 30 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

mtodo LR.
El esquema de funcionamiento de los parsers LR es el siguiente : Entrada a*C+(3*x):

Entrada

Pila
Em
Xm
Em-1
Xm-1
.
.
.
E1
X1
E0

ANALIZADOR
SINTACTICO

Emite un
diagnstico

TABLA LR
ACCIOGOTO's
NES

La pila contiene las cadenas de elementos intercalados, los


son smbolos gramaticales
(terminales o no-terminales), y los
son smbolos llamados estados.
Como se muestra en la figura la tabla predictiva est formada por dos partes, la de acciones, y la
de goto's que en realidad son transiciones de un DFA que construyen los mtodos LR.
La pila se maneja diferente al mtodo LL(1), en un principio contiene en el fondo a
del DFA), y la cadena de entrada debe tener al final .

(el estado 0

Las tres acciones que marca la tabla predictiva son:


1. Shift( ).- Introduccin de i en la pila para el estado

2. Reduce(j ).- Reduccin en la pila por la produccin nmero j.


3. Goto( ).- Transicin del DFA en la pila hacia el estado i.
NOTA: Por sencillez, se abrevia la notacin como: Shift( )=

, Reduce( j )=

, Goto( )=

La tabla es un arreglo matricial, cuyos renglones son los estados


son el conjunto de elementos terminales inclusive , y elementos no terminales.

y cuyas columnas

El parser decide que hacer tomando en cuenta el siguiente esquema de trabajo:


La pila contiene la configuracin

Donde el fondo es

y el tope es

Sea a el smbolo ledo de la cadena de entrada, y sea


- 31 -

el estado en el tope de la pila


Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

1. Si M[

, a]=

se introduce a en la pila y despus se introduce el nuevo estado j dado

2. Si M[ , a]= , la produccin j tiene la forma A , y r es la longitud de denotadoa como


r=||. El parser saca de la pila 2r elementos quedando en el tope algn estado , se introduce
en la pila A y se introduce despus el nuevo estado p, donde M[ , A]= .
3. Si M[

, a]= Aceptar, la revisin ha concluido con xito.

4. Si la entrada M[

, a], est vaca, ha ocurrido un error.

Pseudocdigo:
a=lee_token()
Repite
S=Tope de la pila
Si M[S,a]=Si entonces
push(a)
push(i)
a=lee_token()
otro
Si M[S,a]=Rj (A) entonces
Para k=1 hasta 2*||
pop(e)
Fin para
push(A)
push(M[e,A])
otro
Si M[S,a]=Ac entonces
aceptada()
otro
error()
Finsi
Finsi
Finsi
Fin repite
El algoritmo para la revisin de un texto de entrada es el mismo para los tres casos de parser LR,
lo nico que vara son las tablas.
PARSER SLR(1)
A continuacin se muestra el mtodo para construir una tabla SLR(1) (Simple LR). Pero antes de
continuar se deben conocer algunos otros conceptos.
ITEMS LR(0)
Un item LR(0) es una produccin con un punto en alguna posicin de la parte derecha. Por
ejemplo la produccin A A+A tiene cuatro items LR(0)
[A A + A]
[A A + A]
[A A + A]
[A A + A ]

- 32 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Al caso particular A , genera un solo tem, [A ] . A una serie de tems LR(0) se le denomina
coleccin cannica LR(0).
OPERACION DE CERRADURA
Si I es un conjunto de tems en G se construye cerradura(I) como:
1. Todos los elementos de I estn en cerradura(I).
2. Si hay un tem como [A B] y B es una produccin, se aade el tem [B ]. Se
repite esta regla hasta que ya no se puedan aadir ms tems.
OPERACION GOTO
La operacin GOTO que se escribe como goto(I,X), donde I es un conjunto de tems y X un
smbolo gramatical, se define como la cerradura del conjunto de todos los tem s [A X] tales que
[A X] estn en I.
Con las operaciones anteriores se puede encontrar la coleccin cannica de tems LR( 0), y los
estados del DFA, para posteriormente construir una tabla predictiva. Primero se obtiene a partir de G
una gramtica aumentada G', que consiste en agregar una produccin al principio y cambiar
consecuentemente el smbolo inicial de la gramtica, S' S. Posteriormente se calcula la cerradura
para S' S, y se comienzan a realizar las operaciones gto sobre el conjunto encontrado. Ejemplo :
0)
1)
2)
3)
4)
5)
6)
7)
8)

F'
F
MENOS
MENOS
EXP
S
S
OP
OP

F
f ( x ) = MENOS EXP

# S
OP EXP

TERMINALES={f, (, x, ), =, -, #, +, }
NO TERMINALES = {F', F, MENOS, EXP, S, OP}
0) F'
F

F
f ( x ) = MENOS EXP

1) F'

2) F

f ( x ) = MENOS EXP

goto(2,()=3

3) F

f ( x ) = MENOS EXP

goto(3,x)=4

4) F

f ( x ) = MENOS EXP

goto(4,))=5

5) F

f ( x ) = MENOS EXP

goto(5,=)=6

6) F
MENOS
MENOS

f ( x ) = MENOS EXP

goto(6,MENOS)=7
goto(6,-)=8

goto(0,F)=1
goto(0,f)=2

- 33 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

7) F
EXP

f ( x ) = MENOS EXP
# S

8) MENOS

9) F

f ( x ) = MENOS EXP

10) EXP
S
S
OP
OP

11) EXP

# S

12) S
EXP

OP EXP
# S

13) OP

14) OP

15) S

OP EXP

goto(7,EXP)=9
goto(7,#)=10

# S
OP EXP

goto(10,S)=11
goto(10,OP)=12
goto(10,-)=13
goto(10,+)=14

goto(12,EXP)=15
goto(12,#)=10

TABLA SLR(1)
Una vez construido el conjunto cannico, se siguen las reglas:
1. Si goto (i,a)= j, donde a es terminal, M[i,a]= Shift(j).
2. Si goto (i,A)= j, donde A es no-terminal, M[i,A]=Goto(j).
3. Si A est en i, M[i,b]=Reduce(j) (reduce por la produccin nmero j), para todo b en el
FOLLOW(A), y AS'.
4. Si S' S est en i, M[i,]=Acceptar.
5. Todas las dems entradas no definidas son error.
Si existen colisiones se dice que la gramtica no es SLR.
PARSER LR(1)
ITEMS LR(1)
Para la construccin de la tabla LR(1) se requiere calcular el conjunto cannico de tems LR(1). Se
modifica la operacin de cerradura.
Los tems del conjunto LR(1) tienen la forma [A B, a], (tienen el nuevo elemento a llamado
smbolo de anticipacin) y la cerradura para un conjunto de tems I se calcula como:
1. Para cada tem de la forma [A B, a] en I, sea B una produccin, se aade el tem
[B , b] para cada b en FIRST(a). Se repite esta regla hasta que no se pueda aadir nada ms.

- 34 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Para construir el conjunto cannico de tems LR(1) dada una gramtica, primero se calcula la
cerradura para el tem [S' S, ], con lo que se crea el primer estado, y posteriormente se comienzan
a hacer las operaciones goto hasta que ya no puedan ser aadidos ms tems.
CONSTRUCCION DE LA TABLA LR(1)
1. Si goto (i,a)= j, donde a es terminal, M[i,a]= Shift(j).
2. Si goto (i,A)= j, donde A es no-terminal, M[i,A]=Goto(j).
3. Si [A , a] est en i, M[i,a]=Reduce(j) (reduce por la produccin j), y AS'.
4. Si [S' S, ] est en i, M[i,]=Aceptar.
5. Todas las dems entradas no definidas son error.
Una de las desventajas de este mtodo es que produce tablas predictivas demasiado grandes, por
lo que en ocasiones se utiliza un parser LALR que tiene mayor cobertura que un SLR, y produce tablas
ms pequeas que las LR.
PARSER LALR(1)
Este mtodo se basa en los ncleos de los tems LR(1), agrupando los ncleos iguales en un solo
estado, para reducir el nmero de estados. Se buscan los elementos LR(1) con mismos ncleos y se
reemplazan por su unin. El nico conflicto posible es el de reduccin/reduccin, y entonces, se dice
que la gramtica no es LALR. Para construir la tabla se realiza el siguiente mtodo. Las siglas del
mtodo quieren decir "look ahead-LR", anlisis sintctico LR con smbolo de anticipacin.
1. Constryanse el conjunto

de tems LR(1).

2. Bsquense todos los conjuntos con ncleos iguales y sustityanse por su unin obteniendo el
{
nuevo conjunto que llamaremos
. Al realizar la operacin goto(J,X)= , J puede
ser la unin de varios conjuntos I, es decir
, y si m no existe como conjunto
independiente porque m forma parte de alguna unin
, goto(J,X)=L.
3. Aplquense todos los pasos utilizados en la construccin de la tabla LR(1). Si existe algn
conflicto, se dice que la gramtica no es LALR(1).
TRASLACION DIRIGIDA POR SINTAXIS
NOTACION POSTFIJA.
1. Si E es variable o constante el postfijo de E es E.
2. Si E es una expresin de forma
con op como operador binario, el postfijo de E es
donde
y
son los postfijos de
y .
3. Si E es de la forma (

), el postfijo E es el postfijo de

(9-5)+2 = 9 5 - 2 +
9-(5+2) = 9 5 2 + Durante el proceso de traslacin, un compilador puede ir almacenando ciertas cantidades que
servir n para la generacin de cdigo. En este punto es donde se consideran los atributos asociados
con algn elemento.
Un formalismo para implementar estas actividades se llamado "SYNTAX DIRECTED DEFINITION"
(definicin dirigida por sintaxis). Esta especifica los atributos con los componentes sintcticos de

- 35 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

alguna definicin.
Una DDS usa una gramtica de contexto libre para especificar la estructura de una cadena, con
cada smbolo de la gramtica se asocia un conjunto de atributos, y con cada produccin de la
gramtica, una regla semntica. La gramtica y las reglas semnticas forman la SDD. Una translacin
es el mapeo de una entrada en una salida por medio de la DDS. Para producir la salida, primero se
construye un rbol de perser para X. Se escribe X.a para denotar el valor del atributo a en el nodo n. El
valor de X.a en el nodo n es calculado por la regla semntica asociada con la X-produccin.
Por ejemplo:
PRODUCCIONES

EXP
EXP
EXP
TERM
TERM

REGLA SEMANTICA

EXP + TERM
EXP - TERM
TERM
num
id

EXP.a := EXP.a T RM a
EXP.a := EXP.a T RM a EXP.a := TERM.a
TERM.a := num.val
TERM.a := id.val

Estas reglas semnticas trasladan una expresin en notacin infija a notacin postfija, el smbolo
significa concatenacin.
Para 9-5+2 se expande el rbol

EXP
EXP
EXP

+
TERM

TERM

EXP.a=95-2+
TERM

EXP.a=95-

EXP.a=9

TERM.a=2
TERM.a=5

TERM.a=9

La notacin postfija tiene una importante ventaja ya que solo hay una forma de codificarla debido a la
posicin y nmero de argumentos. La manera de interpretarla siempre es la misma y es muy sencilla.
Se recorre la cadena de izquierda a derecha hasta encontrar un operador, luego se toman los dos
operandos previos al operador encontrado, se evala el operador con sus operandos y se sustituyen
por el resultado luego se contina. Este proceso se repite hasta terminar con todas las evaluaciones.
Ejemplo:
Sea a=5, m=7 y d=3
dia := (1461*a) div 4 + (153*m + 2) div 5 + d
entonces dia=2043
Ahora la notacin postfija es:
dia 1461 a * 4 div 153 m * 2 + 5 div d + + :=
- 36 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

Al evaluar de izquierda a derecha:


dia 1461 a * 4 div 153 m * 2 + 5
dia
7305
4 div 153 m * 2 + 5
dia
1826
153 m * 2 + 5
dia
1826
1071 2 + 5
dia
1826
1073
5
dia
1826
214
dia
1826
dia
2043

div
div
div
div
div

d
d
d
d
d
d

217

+
+
+
+
+
+

+
+
+
+
+
+
+

:=
:=
:=
:=
:=
:=
:=
:=

entonces dia=2043
Por ejemplo: ROBOT ( Tarea ).
Procedimiento recursivo para evaluar un rbol con reglas semnticas y atributos.
PROCEDURE VISITA (n:nodo)
inicio
Por cada hijo m del nodo n de izquierda a derecha HACER
VISITA(m)
Evaluar las reglas semnticas para n
fin procedimiento
ESQUEMAS DE TRANSLACION.
Un esquema de translacin es una gramtica de contexto libre en la cual se introducen
fragmentos de cdigo en la parte derecha de las producciones, prcticamente, es lo mismo que una
DDS, slo que el orden de evaluacin de las reglas semnticas es explcito.
La accin a ejecutar, es simplemente un nodo ms en un rbol sintctico. Cuando una DDS es
"simple" el orden de los no terminales de la gramtica conserva su posicin, y solamente se aaden
algunos strings adicionales. Una forma sencilla de construir un esquema de translacin para una
gramtica, es aadir los caracteres agregados de la regla semntica en la DDS. El esquema de
traslacin queda:

EXP
EXP
EXP
TERM
TERM

EXP + TERM
EXP - TERM
TERM
num
id

{ print '+' }
{ print '-' }
{ print num.val }
{ print id.val }

IMPLEMENTACION DE CODIGO INTERMEDIO CON PILA


El front-end de un compilador debe generar cdigo intermedio, es decir, una representacin
intermedia del programa fuente. Una forma de implementarlo es mediante una pila. Este esquema
trabaja con un rea de memoria para instrucciones y otra reservada para datos, y to das las
operaciones aritmticas son hechas sobre una pila.

- 37 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

1
2
3
4
5
6
7

PROGRAMA
mete(5)
rvalor(2)
opsum
rvalor(3)
opmul

PILA
16
7

tope

1
2
3
4

DATOS
0
11
7

pc

En este diseo, las operaciones aritmticas se realizan en forma postfija. La pila y la memoria de
datos se manejan con estas instrucciones:
mete(x)

mete x a la pila.

rvalor(x)

mete en la pila el contenido de la direccin x del segmento de datos.

lvalor(d(x))

mete en la pila la direccin d(x) del segmento de datos.

saca

saca el tope de la pila.

opabs

saca el tope de la pila e introduce su valor absoluto.

copia

mete una copia del tope de la pila en la pila.

opsum

Saca los dos ltimos elementos de la pila, los suma y el resultado


lo introduce en la pila. Todos los siguientes trabajan de la misma
manera.

opdif

Hace la resta.

opmul

Hace la multiplicacin.

opcoc

Hace la divisin

opdiv

Hace la divisin entera.

opmod

Hace el mdulo.

opand

Hace la conjuncin (0 es falso, no cero es verdadero).

opor

Hace la disyuncin (0 es falso, no cero es verdadero).

opnot

Hace la negacin, saca el tope de la pila y si es 0 introduce un 1, y si


es cualquier valor diferente de 0, introduce un 0.

asig

el rvalor del tope de la pila es colocado en el lvalor debajo de l,


y los dos elementos son sacados de la pila.

ira(x)

Salta a la direccin x del segmento del programa. Es decir IP=x.

irfalso(x)

Saca el tope de la pila y si es 0 salta a la direccin x del segmento del


programa. Es decir IP=x.

irverdad(x)

Saca el tope de la pila y si es distinto de 0 salta a la direccin x del


segmento del programa. Es decir IP=x.

fin

Termina la ejecucin del programa.


- 38 -

Hctor Torres Aguilar

Universidad Autnoma del Estado de Mxico


Facultad deIngeniera

El cdigo para una suma como 3 + 5 es:


mete(3)
mete(5)
opsum
Tomando el segmento de datos de arriba, el cdigo para guardar en la direccin 1 el resultado de
la multiplicacin de las direcciones 2 y 3 es el siguiente:
lvalor(d(1))
rvalor(2)
rvalor(3)
opmul
asig
Para las expresiones booleanas el valor de 0 es falso y todos los valores diferentes de cero
significan verdadero.
Las comparaciones con los operadores =, <>, >, <, >=, <= se pueden hacer con las operaciones
bsicas descritas anteriomente, por ejemplo la igualdad se puede resolver con operaciones aritmticas.
3 <> 1 debe arrojar un valor verdadero es decir, diferente de 0. En tanto que
3 <> 3 debe arrojar un valor igual a 0 que es falso. En tanto que
3 = 1 debe arrojar un 0 porque esto es falso y
3 = 3 debe arrojar algo diferente de cero porque esto es verdadero.
Nos percatamos que si hacemos la resta de los dos elementos que se comparan, siempre nos dar
como resultado un cero si los elementos son iguales, y algo diferente de 0 si son diferentes es decir:

{
Es decir, si hacemos la diferencia (a-b) dado a=b, nos dar falso si son iguales y verdadero si son
diferentes. Por lo que simplemente basta negar el valor. As la expresin la podemos traducir con
operaciones aritmticas:

De la misma manera se pueden buscar frmulas para

- 39 -

Hctor Torres Aguilar

You might also like