You are on page 1of 61

REPASO DE SINTAXIS

Programacin de sistemas.
Conjunto de reglas para crear soluciones a problemas computables. Conjunto de
herramientas que nos permiten crear software de base que son de utilidad para
interactuar con la mquina.
Software de base.
Compilador, Sistema Operativo, Cargador.
Autmata.
Son las cadenas posibles que aceptan un lenguaje.
Expresiones regulares.
Conjunto de smbolos que aceptan una palabra reservada.
Gramtica.
Reglas para escribir las sentencias del lenguaje.
Lenguaje de programacin.
Un lenguaje de programacin est formado por un conjunto de smbolos bsicos
(alfabeto) y un conjunto de reglas que especifican como manipularlos. Tambin debe
darle significado a las cadenas formadas al manipular los smbolos bsicos.
Los lenguajes de programacin pueden clasificarse de acuerdo a su semejanza con
el lenguaje maquina (bajo nivel) o a su semejanza con el lenguaje humano,
generalmente ingls (Lenguajes de alto nivel).Entre los lenguajes de bajo nivel se
encuentra el lenguaje ensamblador.
Un programa escrito en un lenguaje de programacin necesita pasar por un proceso
de compilacin, es decir, ser traducido al lenguaje de mquina, o ser interpretado
para que pueda ser ejecutado por el ordenador.
Los lenguajes son sistemas de comunicacin. Un lenguaje de programacin consiste
en todos los smbolos, caracteres y reglas de uso que permiten a las personas
comunicarse con las computadoras. Existen por lo menos varios cientos de
lenguajes y dialectos de programacin diferentes. Algunos se crean para una
aplicacin especial, mientras que otros son herramientas de uso general ms
flexibles que son apropiadas para muchos tipos de aplicaciones.
En todo caso los lenguajes de programacin deben tener instrucciones que
pertenecen a las categoras ya familiares de entrada/salida, clculo/manipulacin de
textos, lgica/comparacin y almacenamiento/recuperacin.
No obstante, aunque todos los lenguajes de programacin tienen un conjunto de
instrucciones que permiten realizar dichas operaciones, existe una marcada
diferencia en los smbolos, caracteres y sintaxis de los lenguajes de mquina,
lenguajes ensambladores y lenguajes de alto nivel.

Traductores
Un traductor es un programa que recibe como entrada cdigo escrito en un cierto
lenguaje (programa fuente) y produce como salida cdigo en otro lenguaje
(programa objeto). Generalmente el lenguaje de entrada es de ms alto nivel que el
de salida. Ejemplos de traductores son los ensambladores y los compiladores.
Un ensamblador es un programa que traduce de un lenguaje ensamblador a
lenguaje mquina, mientras que un compilador es un programa que traduce de un
lenguaje de alto nivel a un lenguaje de bajo nivel o a lenguaje mquina. Si el fuente
es un lenguaje de alto nivel y si el objetivo es un lenguaje de ensamble de bajo nivel
o de mquina, el traductor es un compilador.
Diseo de lenguajes. El lenguaje de programacin puede definirse al describir
1. Lo que parecen sus programas (la sintaxis del lenguaje)
2. lo que significan sus programas (la semntica del lenguaje).
La sintaxis es la disposicin de palabras como elementos en una oracin para
mostrar su relacin, describe la serie de smbolos que constituyen programas
validos. El enunciado en C: X=Y+Z representa una serie vlida de smbolos, en tanto
que X,Y+- no representa una secuencia valida de smbolos para un programa en C.
La sintaxis suministra informacin significativa que se necesita para entender un
programa y proporciona informacin imprescindible para la traduccin del programa
fuente o un programa objeto. Ejemplo de la expresin: 2+3*4 tiene el valor de 14 y
no 20, se puede especificar una u otra interpretacin, si se desea, por sintaxis y con
ello guiar al traductor a la generacin de las operaciones correctas para evaluar esta
expresin.
Como en la expresin ambigua en espaol, nada en el agua, el solo desarrollo de
una sintaxis de lenguaje es insuficiente para especificar sin ambigedad la
estructura de un enunciado. En un enunciado como X= 2.45+3.67, la sintaxis no nos
puede decir si se declar la variable X, o si X se declaro como tipo real.
Los resultados de X=5, X=6 y X=6.12, son todos posibles si X y + denotan enteros, X
denota un entero y + es adicin de nmeros reales, y X y + denotan valores reales,
respectivamente. Se necesita algo ms que solo estructuras sintcticas, para la
plena descripcin de un lenguaje de programacin. Otros atributos, bajo el trmino
general de semntica, como en el uso de declaraciones, operaciones, control de
secuencia y entornos de refinamiento, afecta a una variable y no siempre estn
determinados por reglas de sintaxis.
Criterios generales de sintaxis.
El propsito primordial de la sintaxis es proveer una notacin para la comunicacin
entre el programador y el procesador de lenguajes de programacin. Sin embargo, la
eleccin de estructuras sintcticas particulares esta restringida slo ligeramente por
la necesidad de comunicar elementos particulares de informacin. A continuacin se
citan criterios generales de sintaxis.

Legibilidad
Facilidad de escritura
Facilidad de verificacin
Facilidad de traduccin
Carencia de ambigedad
ELEMENTOS SINTCTICOS DE UN LENGUAJE

Conjunto de caracteres
Smbolos de operadores
Palabras clave y palabras reservadas
Palabras pregonadas
Comentarios
Espacios en blanco
Delimitadores y corchetes
Formatos de campos libres y fijos
Expresiones
Enunciados

EJEMPLO DE SMBOLOS QUE COMPONEN UN PROGRAMA:


SIMBOLOS ESPECUALES
FUNCIONES
SIMBOLOS QUE RECHAZA EL LENGUAJE
IDENTIFICADORES

ARITMETICOS
LENGUAJE

LOGICOS

PASCAL

AND
NOT
OR

RELACIONALES

<
>
>
<
=
=

ASIGNACION

:=

DELIMITADORES
OPERACIONALES

PALABRAS
RESERVADAS

+,-,*,/,MOD

CICLOS
DECLARACION DE VARIABLES
DECLARACION DE CONSTANTES

La sintaxis del lenguaje se presenta ampliamente con una notacin denominada


gramtica libre de contexto o BNF. (Backus-Naur Form).
La semntica del lenguaje es ms difcil de expresar que la sintaxis y generalmente
se decide por especificarla usando descripciones informales y ejemplos.
Ambas situaciones deben ser consideradas por quien disea un nuevo lenguaje para
satisfacer las necesidades de los usuarios potenciales.

ESTRUCTURA DE UN COMPILADOR

La estructura de un compilador, esta dividida en cuatro grandes mdulos, cada uno


independiente del otro, se podra decir que un compilador esta formado por cuatros
mdulos mas a su vez. El primero de ellos es el preprocesador, es el encargado de
transformar el cdigo fuente de entrada original en el cdigo fuente puro. Es decir en
expandir las macros, incluir las libreras, realizar un preprocesado racional
(capacidad de enriquecer a un lenguaje antiguo con recursos ms modernos),
extender el lenguaje y todo aquello que en el cdigo de entrada sea representativo
de una abreviatura para facilitar la escritura del mismo.
El segundo modulo es el de compilacin que recibe el cdigo fuente puro, este es l
modulo principal de un compilador, pues si ocurriera algn error en esta etapa el
compilador no podra avanzar. En esta etapa se somete al cdigo fuente puro de
entrada a un anlisis lxico grfico, a un anlisis sintctico, a un anlisis semntico,
4

que construyen la tabla de smbolos, se genera un cdigo intermedio al cual se


optimiza para as poder producir un cdigo de salida generalmente en algn
lenguaje ensamblador.
El tercer modulo es el llamado modulo de ensamblado, este modulo no es ni ms mi
menos que otro compilador pues recibe un cdigo fuente de entrada escrito en
ensamblador, y produce otro cdigo de salida, llamado cdigo binario no enlazado.
Si por un momento viramos a este modulo como un programa independiente,
veramos que en este caso los trminos programa compilador y proceso de
compilacin son los mismos. Pues este modulo no es mas que un compilador, que
en su interior realiza como su antecesor un anlisis lxico grfico, un anlisis
sintctico, un anlisis semntico, crea una tabla de smbolos, genera un cdigo
intermedio lo optimiza y produce un cdigo de salida llamado cdigo binario no
enlazado, y a todo este conjunto de tares se los denomina proceso de compilacin.
Como se puede ver este compilador (llamado ensamblador) a diferencia de los
dems compiladores no realiza una expansin del cdigo fuente original (cdigo
fuente de entrada), tiene solamente un proceso de compilacin y por supuesto no
enlaza el cdigo fuente. Es un compilador que carece de los mdulos de
preprocesado y enlazado, y donde los mdulos de compilacin y ensamblado son
los mismos.
El cuarto y ultimo modulo es el encargado de realizar el enlazado del cdigo de
fuente de entrada (cdigo maquina relocalizable) con las libreras que necesita,
como as tambin de proveer al cdigo de las rutinas necesarias para poder
ejecutarse y cargarse a la hora de llamarlo para su ejecucin, modifica las
direcciones relocalizables y ubica los datos en las posiciones apropiadas de la
memoria. Este ultimo modulo es el que produce como salida el cdigo binario
enlazado. Ya sea dinmico o esttico, al decir dinmico se refiere a que el cdigo
producido utiliza libreras dinmicas (libreras ya cargadas en el sistema), esto
implica que se obtendr un cdigo ms corto y que se actualizara automticamente
si aparece alguna nueva versin de las libreras, mientras que el esttico se refiere
al echo que no se realiza enlace con ninguna librera y por lo tanto se obtendr un
cdigo mas largo con una copia de las rutinas de librera que necesita.

Estructura del proceso de Compilacin:


Analizando en detalle el proceso de compilacin, se divide en dos grandes fases,
una de Anlisis y la otra de Sntesis.
Fase de Anlisis:
En el llamado anlisis lexicogrfico o lxico, el compilador revisa y controla que
las "palabras" estn bien escritas y pertenezcan a algn tipo de token (cadena)
definido dentro del lenguaje, como por ejemplo que sea algn tipo de palabra
reservada, o si es el nombre de una variable que este escrita de acuerdo a las
pautas de definicin del lenguaje.

En esta etapa se crea la tabla de smbolos, la cual contiene las variables y el tipo de
dato al que pertenece, las constantes literales, el nombre de funciones y los
argumentos que reciben etc.
En el anlisis sintctico como su nombre lo indica se encarga de revisar que los
tokens estn ubicados y agrupados de acuerdo a la definicin del lenguaje. Dicho de
otra manera, que los tokens pertenezcan a frases gramaticales validas, que el
compilador utiliza para sintetizar la salida. Por lo general las frases gramaticales son
representadas por estructuras jerrquicas, por medio de rboles de anlisis
sintctico. En esta etapa se completa la tabla de smbolos con la dimensin de los
identificadores y los atributos necesarios etc.
El anlisis semntico se encarga de revisar que cada agrupacin o conjunto de
token tenga sentido, y no sea un absurdo. En esta etapa se rene la informacin
sobre los tipos para la fase posterior, en esta etapa se utiliza la estructura jerrquica
de la etapa anterior y as poder determinar los operadores, y operandos de
expresiones y preposiciones.
Fase de Sntesis:
Etapa de generacin de cdigo intermedio, aunque algunos compiladores no la
tienen, es bueno saber de su existencia, en esta etapa se lleva el cdigo del
programa fuente a un cdigo interno para poder trabajar mas fcilmente sobre l.
Esta representacin interna debe tener dos propiedades, primero debe ser fcil de
representar y segundo debe ser fcil de traducir al cdigo objeto.
Optimizacin de cdigo, se busca obtener el cdigo mas corto y rpido posible,
utilizando distintos algoritmos de optimizacin.
Generacin de cdigo, se lleva el cdigo intermedio final a cdigo maquina o
cdigo objeto, que por lo general consiste en un cdigo maquina relocalizable o
cdigo ensamblador. Se selecciona las posiciones de memoria para los datos
(variables) y se traduce cada una de las instrucciones intermedias a una secuencia
de instrucciones de maquina puro.
La tabla de smbolos no es una etapa del proceso de compilacin, sino que una
tarea, una funcin que debe realizar el proceso de compilacin.
En ella se
almacenan los identificadores que aparecen en el cdigo fuente puro, como as
tambin los atributos de los mismos, su tipo, su mbito y en el caso de los
procedimientos el nmero de argumentos el tipo de los mismos etc.
En otras palabras una tabla de smbolos es una estructura de datos, que contiene un
registro por cada identificador, y sus atributos.
La tabla de smbolo es accedida tanto para escritura como parar lectura por todas
las etapas.
Detector de errores o manejador de errores, al igual que la tabla de smbolos no es
una etapa del proceso de compilacin, si no que es una funcin, muy importante,
pues al ocurrir un error esta funcin debe tratar de alguna forma el error para as

seguir con el proceso de compilacin (la mayora de errores son detectados en las
etapas de anlisis lxico, anlisis sintctico, anlisis semntico).
Supongamos que un compilador tiene que analizar la siguiente preposicin:
Preposicin: suma = var1 + var2 + 10;

Anlisis Lxico
El analizador lxico lee los caracteres del programa fuente, y verifica que
correspondan a una secuencia lgica (identificador, palabra reservada etc.). Esta
secuencia de caracteres recibe el nombre componente lxico o lexema. En este
caso el analizador lxico verifica si el identificador id1 (nombre interno para "suma")
encontrado se halla en la tabla de smbolos, si no esta produce un error porque
todava no fue declarado, si la preposicin hubiese sido la declaracin del
identificador "suma" en lenguajes C, C++ (int suma;) el analizador lxico agregara
un identificador en la tabla de smbolos, y as sucesivamente con todos los
componentes lxicos que aparezcan.
id1= id2+ id3 * 10

Anlisis Sintctico
El analizador sintctico impone una estructura jerrquica a la cadena de
componentes lxicos, generada por el analizador lxico, que es representada en
forma de un rbol sintctico.
=
/ \
id1 +
/ \
id2 +
/ \
id3 10

Anlisis Semntico
El analizador semntico verificara en este caso que cada operador
operandos permitidos.

tenga los

=
/ \
id1 +
/ \
id2 +
/ \
id3 tipo_ent
|

10
Generador de cdigo intermedio.
Esta etapa se lleva la preposicin a una representacin intermedia como un
programa para una maquina abstracta.
temp1= tipo_ent(10)
temp2= id3 * temp1
temp3= id2 + tem2
id1= temp3
Optimizacin de cdigo.
El cdigo intermedio obtenido es representado de una forma mas optima y eficiente.
temp1= id3 * 10.0
id1= id2 + temp1
Generador de cdigo.
Finalmente lleva el cdigo intermedio a un cdigo objeto que en este caso es un
cdigo relocalizable o cdigo ensamblador (tambin llamado cdigo no enlazado).
MOVF id3, R2
MULT #10.0, R2
MOVF id2, R1
ADDF R2, R1
MOVF R1, id1
Este el cdigo objeto obtenido que es enviado al modulo de ensamblado. Para
entender todo esto veamos un ejemplo utilizando como lenguaje en este caso al
popular lenguaje de programacin C creado por Kernighan y Ritchie. El siguiente
cdigo esta definido de acuerdo al standard ANSI C.
#include<stdio.h>
void main()
{
char* frase= " Hola Mundo...!!!";
printf("%s", frase );
}
Al pasar por l modulo de preprocesado, el cdigo fuente queda de la siguiente
manera.
# 1 "hmundo.c"
# 1 "c:/compilador/include/stdio.h" 1 3
# 1 " c:/compilador/include/sys/types.h" 1 3
# 12 " c:/compilador/include/stdio.h" 2 3
typedef void *va_list;
typedef long unsigned int size_t;
typedef struct {
int _cnt;
char *_ptr;

char *_base;
int _bufsiz;
int _flag;
int _file;
char *_name_to_remove;
} FILE;
El nuevo cdigo contiene el encabezado o prototipo de la/s funcines que se
encuentran en el archivo de cabecera stdio.h, y que sern posiblemente utilizadas
en el cdigo fuente original. Este cdigo es pasado al modulo de compilacin quien
luego de analizarlo y verificar si se encuentra correcto, transformara el cdigo fuente
puro (expandido) en cdigo ensamblador y lo enva al modulo de ensamblado.
.file "hmundo.c"
compiler_compiled.:
___compiled_c:
.text
LC0:
.ascii " Hola Mundo...!!!\0"
LC1:
Este cdigo ser analizado por l modulo de ensamblado, que lo llevara a cdigo
binario no enlazado, y lo enviara al modulo de enlazado. El cdigo de salida enviado
al modulo de enlazado es el siguiente.
L&#0;(7&#0;.text&#0;
@&#0;&#0;&#0;&#0; &#0;
.............
.data&#0;@&#0;@&#0;@&#0;
.bss&#0;@&#0;@&#0;&#128;
Hola Mundo...!!!&#0;%s&#0;v&#0;
UE&#0;EPh&#0;
v&#0;.file&#0;&#0;
ghmundo.c&#0;&#0;&#0;&#0;.

CARGADORES
La programacin de sistemas se refiere a la creacin de programas cuya finalidad es
servir a otros programas.
Entre los programas que se manejan en la programacin de sistemas se encuentran:
los sistemas operativos, los compiladores, los manejadores de base de datos.
Un cargador es un programa que coloca en la memoria para su ejecucin, el
programa guardado en algn dispositivo de almacenamiento secundario.
Dependiendo de la manera en que se manejan los procesos de ligas y carga,
podemos clasificar a los cargadores en: cargadores iniciales, absolutos, con
reubicacin y ligadores.

Cargadores Iniciales: son aquellos que indican ala PC la forma de poner en


memoria principal, unos datos almacenados en un perifrico de memoria
externa (cintas, discos, etc.) sirven para cargar con la memoria pequeos
programas que inician el funcionamiento de la computadora.

Cargadores Absolutos: como ya se menciono, el programa cargador pone en


memoria las instrucciones guardadas en sistemas externos. Si dichas
instrucciones se almacenan siempre en el mismo espacio de memoria (cada
vez que se ejecute el programa cargador), se dice que es un cargador
absoluto.

Cargadores con publicacin: en ocasiones, un mismo programa necesita


ejecutarse en diferentes posiciones de memoria. Para esto, la introduccin
debe realizarse de forma adecuada, es decir, sin emplear referencias
absolutas a direcciones de memoria, si no referencias relativas a una
direccin especial llamada Direccin de Reubicacin.

El calculo de las direcciones de reubicacin las hace el mismo cargador a medida


que va cargando las instrucciones en el espacio de memoria que le indique al
usuario o el sistema operativo de la maquina.

Cargadores ligadores: conocidos tambin como Link Editor por su trmino


en ingles o simplemente Linker, ala accin de motor se le llama vulgarmente
Lindar.

Montar un programa consiste en aadir al programa objeto. Obteniendo en la


traduccin las rutinas externas a las que hace referencia dicho programa.
El ensamblador debe permitir dichas referencias y las rutinas debe estar a su vez en
lenguaje maquina guardadas en algn elemento accesible al montaje.
Generalmente dichas rutinas se encuentran guardadas en ficheros especiales
llamados Libreras; donde estn almacenadas todas las rutinas externas
susceptibles a ser empleados por los diferentes programas del usuario.
10

All va el programa ligador cuando esta realizando el montaje de un programa a


buscarlas y las adjunta al programa objeto.
En el proceso de carga reubicable (relocalizable), un mismo programa puede
ejecutarse en diferentes posiciones de memoria. Para esto, el programa objeto debe
utilizar referencias a relativas a una direccin especial llamada direccin de
reubicacin.
EI clculo de las direcciones reubicables es realizado por el cargador a medida quo
va ubicando las instrucciones en el espacio de memoria que le indique el sistema
operativo.
Cuando se utilizan subrutinas en un programa, el cdigo ejecutable de cada una de
ellas debe encontrarse en memoria al tiempo de ejecucin. Para esto, antes de
cargar un programa, debe ligarse su cdigo objeto con los cdigos objeto
(guardados en uno o ms archivos) de cada una de las subrutinas invocadas por l,
obteniendo as un programa ejecutable que contiene tanto el cdigo del mdulo
invocador como el cdigo de los mdulos invocados. En este punto, es posible
guardar el resultado del proceso de liga en un archivo que podr ser utilizado por un
cargador, o el mismo programa ligador puede tambin realizar la tarea de carga.
Esto ltimo evita el tener que guardar el cdigo ejecutable en un archivo, con lo que
se ahorra espacio en disco. Este ahorro de espacio en disco se paga con el tiempo
gastado al tener que ligar todos los mdulos cada vez que se necesite ejecutar el
programa.
Este enlace se llama esttico porque se realiza antes de ejecutar el programa.
Existe otro proceso llamado enlace dinmico, el cual consiste en enlazar en tiempo
de ejecucin los mdulos que contienen a las subrutinas.

ENSAMBLADORES
Que es ensamblador y para que sirve?
Cuando se empezaron a utilizar smbolos nemotcnicos, se escribieron programas
para traducir automticamente los programas escritos en lenguaje ensamblador a
lenguaje mquina. A estos programas traductores se les llamo ensambladores.
La entrada para un ensamblador es un programa fuente escrito en lenguaje
ensamblador. La salida es un programa objeto, escrito en lenguaje de mquina. El
programa objeto incluye tambin la informacin necesaria para que el cargador
pueda preparar el programa objeto para su ejecucin.
Para evitar confusiones, de aqu en adelante llamaremos lenguaje ensamblador al
conjunto de nemotcnicos y a las reglas para su manejo. Al programa que traduce
un programa objeto a partir de un programa escrito en lenguaje ensamblador lo
llamaremos ensamblador

11

Motivos para utilizarlo

Rapidez
Mayor control de la computadora
Independencia del lenguaje
La mayora de las computadoras pueden ensamblarlo

Motivo para no utilizarlo

Dependencia de hardware
Mayor tiempo de codificacin
Comprensin mas profunda de la computadora
Errores mas frecuentes en el programa

Tipos de Ensambladores.
Aunque todos los ensambladores realizan bsicamente las mismas tareas, podemos
clasificarlos de acuerdo a caractersticas.
As podemos clasificarlos en:

Ensambladores Cruzados (Cross-Assembler).

Se denominan as los ensambladores que se utilizan en una computadora que


posee un procesador diferente al que tendrn las computadoras donde va a
ejecutarse el programa objeto producido.
El empleo de este tipo de traductores permite aprovechar el soporte de medios
fsicos (discos, impresoras, pantallas, etc.), y de programacin que ofrecen las
mquinas potentes para desarrollar programas que luego los van a ejecutar
sistemas muy especializados en determinados tipos de tareas.

Ensambladores Residentes.

Son aquellos que permanecen en la memoria principal de la computadora y cargan,


para su ejecucin, al programa objeto producido. Este tipo de ensamblador tiene la
ventaja de que se puede comprobar inmediatamente el programa sin necesidad de
transportarlo de un lugar a otro, como se haca en cross-assembler, y sin necesidad
de programas simuladores.
Sin embargo, puede presentar problemas de espacio de memoria, ya que el
traductor ocupa espacio que no puede ser utilizado por el programador. Asimismo,
tambin ocupar memoria el programa fuente y el programa objeto. Esto obliga a
tener un espacio de memoria relativamente amplio. Es el indicado para desarrollos
de pequeos sistemas de control y sencillos automatismo empleando
microprocesadores.
La ventaja de estos ensambladores es que permiten ejecutar inmediatamente el
programa; la desventaja es que deben mantenerse en la memoria principal tanto el
ensamblador como el programa fuente y el programa objeto.

12

Macroensambladores.

Son ensambladores que permiten el uso de macroinstrucciones (macros). Debido a


su potencia, normalmente son programas robustos que no permanecen en memoria
una vez generado el programa objeto. Puede variar la complejidad de los mismos,
dependiendo de las posibilidades de definicin y manipulacin de las
macroinstrucciones, pero normalmente son programas bastantes complejos, por lo
que suelen ser ensambladores residentes.

Microensambladores.

Generalmente, los procesadores utilizados en las computadoras tienen un repertorio


fijo de instrucciones, es decir, que el intrprete de las mismas interpretaba de igual
forma un determinado cdigo de operacin.
El programa que indica al intrprete de instrucciones de la UCP cmo debe actuar
se denomina microprograma. El programa que ayuda a realizar este microprograma
se llama microensamblador. Existen procesadores que permiten la modificacin de
sus microprogramas, para lo cual se utilizan microensambladores.

Ensambladores de una fase.

Estos ensambladores leen una lnea del programa fuente y la traducen directamente
para producir una instruccin en lenguaje mquina o la ejecuta si se trata de una
pseudoinstruccin. Tambin va construyendo la tabla de smbolos a medida que van
apareciendo las definiciones de variables, etiquetas, etc.
Debido a su forma de traduccin, estos ensambladores obligan a definir los smbolos
antes de ser empleados para que, cuando aparezca una referencia a un
determinado smbolo en una instruccin, se conozca la direccin de dicho smbolo y
se pueda traducir de forma correcta. Estos ensambladores son sencillos, baratos y
ocupan poco espacio, pero tiene el inconveniente indicado.

Ensambladores de dos fases.

Los ensambladores de dos fases se denominan as debido a que realizan la


traduccin en dos etapas. En la primera fase, leen el programa fuente y construyen
una tabla de smbolos; de esta manera, en la segunda fase, vuelven a leer el
programa fuente y pueden ir traduciendo totalmente, puesto que conocen la totalidad
de los smbolos utilizados y las posiciones que se les ha asignado.
Estos ensambladores son los ms utilizados en la actualidad.
El proceso de ensamble de uno, dos o ms pasos.
Como se vio en la seccin anterior, existen ensambladores que realizan su tarea en
una o ms fases o pasos.

13

El proceso de ensamble de un paso consiste en leer una lnea de programa fuente y


traducirla a lenguaje mquina cuando se trata de una instruccin, o se ejecuta si es
una seudoinstruccin.
La tabla de smbolos se va construyendo a medida que se avanza en la lectura de
las lneas del programa fuente.
Para que el ensamble de un paso funciones, todos los smbolos deben estar
definidos antes de emplearse. Esto debido a que, para traducir correctamente cada
instruccin, se debe conocer la direccin de cada uno de los smbolos que
intervienen en ella. En otras palabras, no pueden quedar referencias pendientes
porque ya no habr otra oportunidad de resolverlas.
Tampoco podrn hacerse saltos hacia lneas posteriores. No es posible saltar hacia
una lnea cuya etiqueta todava no ha sido definida.
Para resolver el problema que presenta el proceso de ensamble de un paso, se
utiliza el proceso de ensamble de dos pasos o fases. En la primera fase, se lee el
programa fuente y se construye la tabla de smbolos.
En la segunda fase, se vuelve a leer el programa fuente y se traduce totalmente ya
que se conoce la totalidad de los smbolos utilizados (incluyendo las etiquetas) y las
posiciones de memoria que se les han asignado. Como ya se conocen las
direcciones de las etiquetas utilizadas, pueden realizarse saltos hacia adelante.
Literales y Expresiones.
En computacin, las literales son mecanismos mediante los cuales se reservan
espacios de memoria para guardar valores de cierto tipo. Generalmente, el trmino
literal se asocia un smbolo para representar la direccin del primer byte de espacio
asignado. En el espacio asignado se pueden almacenar valores constantes o
variables.
Las expresiones son combinaciones de literales y operadores. En lenguaje
ensamblador las expresiones involucran valores constantes y operadores. Los
resultados se almacenan como constantes ya que los clculos ocurren durante el
ensamble, no durante la ejecucin. Los operadores que se utilizan en las
expresiones de lenguaje ensamblador no tienen ningn efecto en tiempo de
ejecucin del programa ensamblado. No debe confundirse el manejo de expresiones
en lenguaje ensamblador con el manejo de expresiones en los lenguajes de alto
nivel. En los lenguajes de alto nivel, la evaluacin de las expresiones se hace en
tiempo de ejecucin.
Cada traductor dar sus reglas de construccin de expresiones y, muy
importante, de cmo las evala.

14

MACROPROCESADORES
USOS DE UN MACROPROCESADOR
Con el fin de evitar al programador la tediosa repeticin de partes idnticas de
un programa, los ensambladores y compiladores cuentan con macroprocesadores
que permiten definir una abreviatura para representar una parte de un programa y
utilizar esa abreviatura cuantas veces sea necesario.
Para utilizar una macro, primero hay que declararla. En la declaracin se
establece el nombre que se le dar a la macro y el conjunto de instrucciones que
representar.
El programador escribir el nombre de la macro en cada uno de los lugares donde
se requiera la aplicacin de las instrucciones por ella representadas.
La declaracin se realiza una sola vez, pero la utilizacin o invocacin a la
macro (macrollamada) puede hacerse cuantas veces sea necesario.
La utilizacin de macros posibilita la reduccin del tamao del cdigo fuente,
aunque el cdigo objeto tiende a ser mayor que cuando se utilizan funciones.
Es tan comn el empleo de macroinstrucciones se les considera como una
extensin de los lenguajes. De manera similar se considera al procesador de
macroinstrucciones o macroprocesador como una extensin del ensamblador o
compilador utilizado.
El macroprocesador se encarga, en una primera pasada, de registrar todas
las declaraciones de macros y de rastrear el programa fuente para detectar todas las
macrollamadas. En cada lugar donde encuentre una macrollamada, el
macroprocesador har la sustitucin por las instrucciones correspondientes. A este
proceso de sustitucin se le denomina expansin de la macro.
El macroprocesador elabora dos tablas para el manejo de las macros:
Una tabla de macronombres que consiste de los nombres de las macros y un ndice
que le permite localizar la definicin de la macro en otra tabla llamada tabla de
macrodefiniciones.
Como su nombre lo indica, la tabla de macrodefiniciones contiene las
definiciones de todas las macros a utilizar en el programa.
En ocasiones es conveniente agrupar macros, de acuerdo a las tareas que
realizan, y almacenarlas en archivos que se constituyen en bibliotecas de macros.
De esta manera, cuando se requiera la utilizacin de alguna macro en
particular, se incluye en el programa fuente el archivo de la biblioteca de macros
correspondiente.

15

La mayora de los ensambladores y compiladores permiten el uso de


pseudoinstrucciones condicionales del tipo IF ... ELSE, por medio de las cuales se
puede controlar la traduccin de ciertos bloques de programa.

COMPILADORES
La necesidad de establecer comunicacin con dispositivos de cmputo para
un creciente nmero de usuarios ha obligado a construir herramientas que permitan
que esta comunicacin se realice de manera ms efectiva y con menor consumo de
tiempo.
Se le atribuye a Grace Murray Hopper la acuacin de este trmino y se
refera al trabajo que estaba detrs de la programacin en aquellos tiempos: exista
una biblioteca de programas constituida de un conjunto de rutinas, cada una de ellas
probada individualmente; cuando se necesitaba un programa, se elegan las rutinas
necesarias de esa biblioteca y se integraban para conformar el proceso que
ejecutara la computadora. Quin realizaba este trabajo de acopio de rutinas y de
integracin se le denominaba compilador, de ah que los nuevos lenguajes tuviesen
sus propios "compiladores" para la integracin del proceso que programar
representaba.
En nuestros das, el trmino an se conserva aunque con un sentido
ligeramente diferente al planteado por Hopper. Hoy en da, un compilador es un
traductor que facilita la comunicacin entre el programador y la mquina, por medio
de un proceso de transformacin.
Un compilador es un programa que lee las lneas escritas en un lenguaje de
programacin (como Pascal) y las traduce a otro que pueda ejecutar la
computadora. Los programas compilados se ejecutan ms rpido que los
interpretados, debido a que han sido completamente traducidos a lenguaje de
mquina y no necesitan compartir memoria con el intrprete.
A grandes rasgos un compilador es un programa que lee un programa escrito
es un lenguaje, el lenguaje fuente, y lo traduce a un programa equivalente en otro
lenguaje, el lenguaje objeto. Como parte importante de este proceso de traduccin,
el compilador informa a su usuario de la presencia de errores en el programa fuente.
Clasificacin de Compiladores
El programa compilador traduce las instrucciones en un lenguaje de alto nivel a
instrucciones que la computadora puede interpretar y ejecutar. Para cada lenguaje
de programacin se requiere un compilador separado.
El compilador traduce todo el programa antes de ejecutarlo. Los compiladores
son, pues, programas de traduccin insertados en la memoria por el sistema
operativo para convertir programas de cmputo en pulsaciones electrnicas
ejecutables (lenguaje de mquina). Los compiladores pueden ser de:

16

una sola pasada: examina el cdigo fuente una vez, generando el cdigo o
programa objeto.

pasadas mltiples: requieren pasos intermedios para producir un cdigo en


otro lenguaje, y una pasada final para producir y optimizar el cdigo producido
durante los pasos anteriores.

Optimacin: lee un cdigo fuente, lo analiza y descubre errores potenciales


sin ejecutar el programa.

Compiladores incrementales: generan un cdigo objeto instruccin por


instruccin (en vez de hacerlo para todo el programa) cuando el usuario
teclea cada orden individual. El otro tipo de compiladores requiere que todos
los enunciados o instrucciones se compilen conjuntamente.

Ensamblador: el lenguaje fuente es lenguaje ensamblador y posee una


estructura sencilla.

Compilador cruzado: se genera cdigo en lenguaje objeto para una mquina


diferente de la que se est utilizando para compilar. Es perfectamente normal
construir un compilador de Pascal que genere cdigo para MS-DOS y que el
compilador funcione en Linux y se haya escrito en C++.

Compilador con montador: compilador que compila distintos mdulos de


forma independiente y despus es capaz de enlazarlos.

Autocompilador: compilador que est escrito en el mismo lenguaje que va a


compilar. Evidentemente, no se puede ejecutar la primera vez. Sirve para
hacer ampliaciones al lenguaje, mejorar el cdigo generado, etc.

Metacompilador: es sinnimo de compilador de compiladores y se refiere a un


programa que recibe como entrada las especificaciones del lenguaje para el
que se desea obtener un compilador y genera como salida el compilador para
ese lenguaje. El desarrollo de los metacompiladores se encuentra con la
dificultad de unir la generacin de cdigo con la parte de anlisis. Lo que s se
han desarrollado son generadores de analizadores lxicos y sintcticos.
desarrollados para UNIX. Los inconvenientes que tienen son que los
analizadores que generan no son muy eficientes.

Descompilador: es un programa que acepta como entrada cdigo mquina y


lo traduce a un lenguaje de alto nivel, realizando el proceso inverso a la
compilacin.

17

ANLISIS LXICO

EL ANALIZADOR LXICO
El analizador lxico lee los caracteres del programa fuente, y verifica que
correspondan a una secuencia lgica (identificador, palabra reservada etc.). Esta
secuencia de caracteres recibe el nombre componente lxico o lexema.
FUNCIN DEL ANALIZADOR LXICO

Su principal funcin consiste en leer los caracteres de entrada y elabora


como salida una secuencia de componentes lxicos (tokens) que utiliza el
analizador sintctico para hacer el anlisis.
Es la parte del compilador que lee el texto fuente.
Recibida la orden "obtn el siguiente componente lxico" del analizador
sintctico, el analizador lxico lee los caracteres de entrada hasta que
pueda identificar el siguiente componente lxico.
Elimina del programa fuente comentarios, espacios en blanco, caracteres
TAB y de lnea nueva.
Otra funcin es relacionar los mensajes de error del compilador con el
programa fuente.
En algunos compiladores, el analizador lxico se encarga de hacer una
copia del programa fuente en el que estn marcados los mensajes de
error.

El analizador Lxico dentro del modelo de un compilador.


En algunas ocasiones, los analizadores lxicos se dividen en dos fases; la
primera llamada "examen", y la segunda, "anlisis lxico". El examinador se encarga
de realizar tareas sencillas, mientras que el analizador lxico es el que realiza las
operaciones ms complejas.
El objetivo del anlisis lxico es gestionar el "bajo nivel" de la entrada (en este
caso, texto) y suministrarle al analizador sintctico la misma ya "filtrada", es decir,
conteniendo solamente terminales de la gramtica a definir.
En ese trabajo se engloba facilitar la definicin de la gramtica ya que, el
hecho de tener que incluir todas las reglas hasta llegar a los terminales ms bajos
(caracteres) aumenta indeseablemente la gramtica.

18

Este tipo de trabajos ms sencillos (como reconocer nmeros, buscar


palabras clave, obviar espacios y dems separadores...) se suelen dejar al
analizador lxico, que ser un programa muy sencillo y funcionar siempre en
tiempo lineal (si le asignamos un trabajo mayor es que seguramente lo estaremos
sobrecargando con funciones de anlisis sintctico, lo cual nunca debiera ocurrir).
Realmente, el hecho de esta separacin simplemente busca simplificar al
mximo la gramtica independiente del contexto trabajando con las unidades ms
abstractas posibles.
La gramtica que queda para el anlisis lxico, siempre debe ser regular, ya
que cada unidad lxica puede venir determinada, por una expresin regular.
La relacin entre el analizador lxico y el sintctico son los tokens y la tabla
de smbolos, ya que la funcin principal del anlisis lxico es leer los caracteres de
entrada y genera como salida una secuencia de componentes lxicos previamente
definidos en expresiones regulares.
ASPECTOS A CONSIDERAR PARA EL ANLISIS LXICO
Un diseo sencillo de un analizador lxico corresponde a unas reglas del
lenguaje meramente sencillas, sin embargo estas son algunas consideraciones
importantes:

Mientras menos complicadas sean las gramticas, ms fcil ser


realizar un compilador, slo que previamente se deben considerar las
expresiones regulares.
Hay que considerar si se debe o puede mejorar la eficiencia del
compilador.
Tambin mejorar la transportabilidad del compilador, ya que las letras
del alfabeto y los errores propios de los dispositivos pueden limitar al
analizador lxico.
El trabajo bsico es reconocer los terminales (que podemos llamar ya unidades
lxicas), y para ello podemos hacer una tabla con todas las posibilidades que
encontraremos en el fichero de la entrada y agruparlos en los tipos necesarios.
Caracteres que corresponden directamente con la unidad lxica.
Unidades lxicas (terminales) que pueden contener varios caracteres.
Caracteres que pueden figurar en el texto pero que no se consideran (se
desechan).
Cualquier otro carcter es errneo, y producir, por ello, un error lxico.
Bajo esta fase se generan los tokens. La generacin de los tokens se ha llevado
a cabo mediante la carga del fichero que contiene el cdigo fuente en una lista, tras
esto se procede a convertir tabuladores y saltos de lnea en espacios para despus
dejar estrictamente los necesarios para diferenciar las distintas palabras introducidas
en el archivo fuente.
Por ejemplo, una entrada del tipo:

19

Si

a>b

Entonces

a=c+d:
FinEntonces:
pasara a ser Si a>b Entonces a=c+d: FinEntonces: en nuestra lista de entrada.
Una vez que tenemos la lista de entrada limpia se procede a la creacin de
los tokens; para ello, se ha definido otro tipo de lista llamado Tokens que contendr
el nombre del token (cadena leda por la pantalla) junto con el tipo al que pertenece.
La implementacin del analizador lxico responde al mtodo general de
programacin visto en teora, por lo tanto se manejan dos punteros, uno al ltimo
carcter ledo y otro al ltimo carcter aceptado con lo cual podemos movernos por
la lista de entrada en bsqueda del siguiente token sin perder la posicin desde
donde comenzamos la presente bsqueda. Los tokens, o smbolos terminales de la
gramtica, han sido representados mediante dos tablas, una para los que van
acompaados de un parntesis y otra para los que no.
El motivo de esta separacin ha sido el trato distinto que se les ha dado a
ambos para no tener que distinguir, dentro de las rdenes que lleva un parmetro, si
entre el final de la orden y el parntesis que rodea al parmetro hay o no espacios.
As las ordenes Mira (id) y Mira(id) son tratadas como el mismo token y toman el ``(''
como parte de l.
Los smbolos separadores (espacios, ``:'', etc.) han sido recogidos del mismo
modo en otra tabla dado el trato distinto de los anteriores que recibirn.
Con esta forma de recoger los tokens que reconoce este analizador hemos
conseguido no tener que realizar grandes modificaciones sobre esta fase del
compilador, si algn da fuera modificado el conjunto de smbolos terminales de la
gramtica.
ANLISIS LXICO: DESARROLLO
Objetivo
El objetivo bsico del scanner o analizador lxico es separar el programa
fuente en unidades mnimas y asociarles una determinada clase o token.
Por qu?

Formalmente, para separar lo lineal de lo jerrquico. En el scanner no hay que


mirar hacia atrs: las unidades lxicas se forman con caracteres siempre
consecutivos y no pueden solaparse dos unidades lxicas. Hay que tener en
cuenta que las reglas lxicas son bastante sencillas y no necesitan una notacin
tan poderosa como una gramtica; las expresiones regulares son ms sencillas y
fciles de entender que una gramtica.

20

Eficiencia, porque es el nico proceso que lee el programa fuente y por ello
pueden estudiarse tcnicas especializadas de manejo de dispositivos de
almacenamiento (la eficiencia es ms fcilmente alcanzable partiendo de
expresiones regulares que de gramticas).
Diseo modular del compilador, relacionado con esto ltimo.
Portabilidad, ya que la mayora de diferencias del mismo lenguaje entre distintos
entornos suele ser en caracteres especiales, capitalizacin, cdigos de
caracteres, etc. y as se encapsulan en el scanner.
Funciones del scanner
Las funciones bsicas del scanner son:

Leer el programa fuente

Delimitar los lexemas

Identificar cada token

Asignar atributo a cada unidad lxica


Para hacer la interaccin con el parser, lo ms habitual es convertir al scanner en
una subrutina del parser, para que as pueda responder a la orden "obtener la
siguiente unidad lxica" recibida del parser.
Como el scanner lee el programa fuente, tambin realiza ciertas funciones
secundarias como son eliminar comentarios y caracteres no significativos (espacios,
tabuladores, retornos de carro...) o preprocesar las macros.
Otra funcin secundaria del analizador lxico es relacionar los mensajes de error
con el programa fuente (ya que para que al usuario le sean significativos es
necesario que no se pierda esta relacin).
En este sentido, en algunos compiladores el scanner va produciendo una copia
del fuente en la que se marcan los mensajes de error, se expanden las macros, etc.
La ltima funcin del scanner es detectar los errores lxicos que puedan
producirse. A este nivel, los errores se restringen a localizar caracteres no
reconocidos, combinaciones de caracteres imposibles, o intentos de lectura por
detrs del fin de fichero.
Tipos de unidades lxicas: concepto de patrn
Hay dos clases de unidades lxicas:

Las definidas por el lenguaje: palabras clave, operadores, smbolos especiales.


Nmero finito (quizs 1) de lexemas.
Las definidas por el programador (bajo ciertas normas genricas): identificadores,
literales, comentarios. Normalmente, el nmero "posible" de lexemas es infinito.
El patrn de las primeras es la simple enumeracin de los lexemas; de las
segundas, una serie de normas que describen todas las cadenas que corresponden
al mismo token.

21

El patrn permite identificar el token y asignar el atributo (suponiendo delimitado


el lexema). Es decir, una vez delimitado el lexema, cumplir algn patrn, y ese es el
que marca el token. Se dice que el patrn concuerda con el lexema que cumple ese
patrn.
De este modo, lo primero que debe definirse en todo lenguaje de programacin
es una tabla con todos los patrones lxicos del lenguaje indicando token y atributo
para cada patrn.
Por ejemplo, tomando un subconjunto de JAVA:
Token

Lexemas ejemplo

Descripcin del patrn

pc-then

then

(t/T)(h/H)(e/E)(n/N)

pc-while

while

while

pc-printf

write

write

op-rel

<

<

>

>

par-ab

par-cer

ident

Hola, A77aH,
pepe

Letra seguida de letras y dgitos

lit-ent

34, 23442, 1

Dgito no cero seguido de dgitos

lit-real

34.0, 23.4e-5

Dgito no cero seguido de dgitos seguido


opcionalmente de punto decimal y dgitos,
seguido opcionalmente de 'E' o 'e' y dgitos

lit-string

'Hola', 'pe pe '

Caracteres entre ', excepto '

En la mayora de los lenguajes se consideran tokens las construcciones:


palabras clave, operadores, identificadores, literales y signos de puntuacin. Por
supuesto, dependiendo del lenguaje se subdividirn en varios componentes lxicos
ms.
Normas lxicas
El problema ahora es cmo delimitamos el lexema? En un principio,
podramos pensar en utilizar un carcter fijo para delimitar lexemas, por ejemplo el
espacio. De este modo, la sentencia
if A < 50 then write ( 4 )
puede verse fcilmente separada en los lexemas "if", "A", "<", "50", "then", "write",
"(", "4", ")", simplemente observando las series de caracteres separadas por
espacios. Dado cada uno de estos lexemas, ser muy sencillo ver si cumple algn
patrn y devolver el token y atributo correspondiente al patrn que se cumple.

22

En este funcionamiento es fundamental, por ello, la influencia de las distintas


normas lxicas: si las palabras clave pueden usarse como identificadores, cules
son los separadores, etc. De hecho, la evolucin de los distintos lenguajes de
programacin ha ido tendiendo a utilizar reglas lxicas que hagan cada vez ms
sencillo el desarrollo del scanner.
Vamos a enunciar brevemente las ms influyentes en este sentido:

En general, los espacios (y tambin tabuladores y retornos) no son significativos


(es decir, no forman parte de ningn lexema ni constituyen un token) pero s son
separadores.

Las palabras clave suelen ser reservadas. Cuando no lo son (por ejemplo, en
PL/I), el scanner debe distinguir entre palabras clave e identificadores, lo cual
suele ser complicado.

Por ejemplo:
if then then then = else ; else else = then;

El scanner, no puede diferenciar entre identificadores y palabras clave, o bien


diferenciarlos le supone trabajo "extra".

En caso de conflicto, se elige el lexema ms largo. Por ejemplo, ifa es el


identificador ifa y no la palabra clave if seguida del identificador a. Esto es lgico
porque si no limitaramos mucho los identificadores, al no poder indicar ninguna
variable ni nombre de procedimiento o funcin empezada por do, ni por if, ni por
or, ni por and ... (imaginemos lo que ocurrira con lenguajes con muchas palabras
reservadas).

El problema del anlisis lxico, se reduce entonces a reconocer el cumplimiento


de patrones por determinados lexemas. Hay dos herramientas formales que nos
permiten hacer este trabajo de un modo muy sencillo:

Los autmatas finitos.


Son las posibles cadenas que acepta un lenguaje. Se compila una expresin
regular en un reconocedor construyendo un diagrama de transicin que es una
instrumentacin de un modelo formal denominado autmatas finitos, conocidos
tambin como mquinas de estado finito o (con menos frecuencia en la
actualidad) mquinas secuenciales.
Es la representacin grfica de las posibles cadenas que acepta un lenguaje
dentro de un conjunto de smbolos, se conforma por una quntupla donde:
Q es el conjunto de posibles estados
representa al alfabeto

23

representa la funcin de transicin y los estados por los que se acepta cada
uno de los smbolos
qo estado inicial
F conjunto de estados finales

Las expresiones regulares.

Son los posibles smbolos que puede aceptar un lenguaje los cuales se pueden
representar con un autmata. Conjunto de smbolos para aceptar una palabra
reservada.
Una expresin regular es una frmula para denotar "ciertos" lenguajes.
Advirtase que decimos lenguaje, no cadena de caracteres. Una expresin
regular nica denota un conjunto de cadenas, es decir un lenguaje, no una
simple cadena. Las expresiones regulares se pueden usar para especificar
unidades lxicas presentes en un lenguaje de programacin. No todos los
lenguajes pueden ser expresados utilizando una expresin regular.
Sea un alfabeto . La expresin regular sobre y los conjuntos que denotan se
definen de manera recursiva como sigue:
1. es una expresin regular y denota al conjunto vaco {}.
2. Para cada a , a es una expresin regular y denota al conjunto {a}.
3. Si r y s son expresiones regulares que denotan a los lenguajes R y S.;
respectivamente, entonces tenemos lo siguiente.
r+s
(r)
rs
r*
r+
ri

es una expresin regular que denota a los conjuntos R S.


es una expresin regular que denota al conjunto R.
es una expresin regular que denota a los conjuntos RS.
es una expresin regular que denota al conjunto R*, equivale desde
cero a ms repeticiones del lenguaje R.
es una expresin regular que denota al conjunto R+, equivale a una
o ms repeticiones del lenguaje R.
es una expresin regular que denota al conjunto Ri, a s mismo.

Errores Lxicos
Son pocos los errores detectables en el analizador lxico porque se tiene una
visin restringida del programa, ya que no se puede distinguir entre un error de
escritura de un identificador y una palabra reservada, as como la declaracin y
utilizacin de una funcin, porque todas las consideran en esta fase como un
identificador vlido y los errores se empiezan a detectar entre el analizador
semntico o el analizador sintctico, segn sea el caso.
Tcnicas de correccin de errores

24

Existen algunas tcnicas de correccin que son utilizadas en compiladores,


sin embargo no es conveniente modificar la idea original, ni la lgica de
programacin del usuario.
Las tcnicas son las siguientes:
a) Modo de pnico. Donde se guardan los caracteres sucesivos de la entrada
restante, hasta encontrar un componente lxico vlido.
b) Borrar un carcter extrao que no haya sido declarado o definido dentro del
lenguaje
c) Insertar un carcter que falte
d) Reemplazar un carcter faltante
e) Intercambiar caracteres adyacentes
TABLAS DE SMBOLOS
Es una estructura de datos que contiene un registro por cada token o
identificador que define los atributos de ellos mismos. La estructura de datos permite
encontrar rpidamente el registro para ser almacenado o consultado por otras fases.
Cuando el anlisis lxico detecta un token en el programa fuente, este se
introduce e la tabla de smbolos, sin embargo, sus atributos no pueden determinarse
durante el anlisis lxico.
Por ejemplo, dada la siguiente instruccin:
Var
inicial, velocidad: integer ;
Token

Valor

;
integer
:
velocidad
,
inicial
Var

Delimitador
P. R. Int
S. Punt.
Id
Separador
Id
P. R. Var

Posicin en
memoria

Utilizado
por

El tipo entero no se conoce cuando el analizador lxico pasa por toda la


instruccin, las fases restantes introducen informacin sobre los tokens en la tabla y
despus hace uso de ella.
Cuando se hace el anlisis semntico y la generacin de cdigo intermedio se
necesita saber los tipos de cada uno de los identificadores para comprobar si el
programa fuente los usa en forma vlida y as generar las operaciones apropiadas
con ellos.
MTODOS GENERALES PARA LA IMPLANTACIN DE UN ANALIZADOR LXICO

25

a) Utilizar un generador de analizador lxico automtico. Por ejemplo: La


herramienta Lex, que proporciona rutinas para leer la entrada y generar
componentes lxicos.
b) Describir el analizador lxico en un lenguaje convencional de programacin
utilizando subrutinas de entrada / salida.
c) Escribir el analizador lxico en lenguaje ensamblador.

26

ANLISIS SINTCTICO
El objetivo fundamental del anlisis sintctico es "construir un rbol sintctico"
con la cadena de entrada (el "programa"), en la forma de unidades lxicas que
determina el analizador lxico, como se muestra en la siguiente figura:

El Analizador Sintctico dentro del modelo de un compilador.


Si esto se consigue, el programa es (sintcticamente) correcto; y es incorrecto
en caso contrario. Se supone que el analizador sintctico informar de cualquier
error de sintaxis de manera inteligible. Tambin deber recuperarse de los errores
que ocurren frecuentemente para poder continuar procesando el resto de su
entrada.
Existen tres tipos generales de analizadores sintcticos para gramticas. Los
mtodos universales de anlisis sintctico, como el algoritmo de Cocke-YoungerKasami y el de Earley, pueden analizar cualquier gramtica. Estos mtodos sin
embargo, son demasiado ineficientes para usarlos en la produccin de
compiladores. Los mtodos empleados generalmente en la produccin de
compiladores se clasifican como descendentes o ascendentes.
Los dos tipos principales de anlisis sintctico son:
Descendente: construye el rbol desde la raz hacia las hojas.
Ascendente: construye el rbol desde las hojas hacia la raz.
En ambos casos, se examina la entrada al analizador sintctico de izquierda a
derecha, un smbolo a la vez. Los mtodos descendentes y ascendentes ms
eficientes trabajan slo con subclases de gramticas.
La salida del analizador sintctico es una representacin del rbol de anlisis
sintctico para la cadena de componentes lxicos producida por el analizador lxico.
En la prctica, hay varias tareas que se pueden realizar durante el anlisis sintctico,
como recoger informacin sobre distintos componentes lxicos en la tabla de
smbolos, realizar la verificacin de tipo y otras clases de anlisis semntico. Para la
implementacin del analizador sintctico debe de ser necesaria la redefinicin de la
gramtica dada en la prctica de modo que sea ``entendible'' por la computadora.
Dentro de la gramtica generada se deber eliminar la recursividad a izquierdas.
Se sabe que los programas pueden contener errores de muy diversos tipos.
Por ejemplo los errores pueden ser:
27

Lxicos, como escribir mal un identificador, palabra clave u operador.


Sintcticos, como una expresin aritmtica con parntesis no equilibrados.
Semnticos, como un operador aplicado a un operando incompatible.
Lgicos, como una llamada infinitamente recursiva.

A menudo, gran parte de la deteccin y recuperacin de errores en un


compilador se centra en la fase de anlisis sintctico. Una razn es que muchos
errores son de naturaleza sintctica o se manifiestan cuando la cadena de
componentes lxicos que proviene del analizador lxico desobedece la reglas
gramaticales que definen el lenguaje de programacin. Otra razn es la precisin de
los mtodos modernos de anlisis sintctico, que pueden detectar la presencia de
errores dentro de los programas de una forma muy eficiente. La deteccin exacta de
la presencia de errores semnticos y lgicos en el momento de la compilacin es
mucho ms difcil.
El manejador de errores en un analizador sintctico tiene objetivos fciles de
establecer:

Debe de informar de la presencia de errores con claridad y exactitud.


Se debe de recuperar de cada error con la suficiente rapidez como para
detectar errores posteriores.
No de be retrazar de manera significativa el procesamiento de programas
correctos.

Afortunadamente lo errores ms comunes son simples y a menudo basta con un


mecanismo sencillo de manejo de errores. sin embargo, en algunos casos un
error pudo haber ocurrido mucho antes de la posicin en que se detect su
presencia, y puede ser muy difcil deducir su naturaleza precisa de error. En los
casos difciles, el manejador de errores quiz tenga que adivinar qu tena en
mente el programador cuando escribi el programa.
Varios mtodos de anlisis sintctico, detectan un error lo antes posible. Es decir,
tienen la propiedad del prefijo viable, la cual quiere decir que detectan la presencia
de un error nada ms con ver un prefijo de la entrada que no es prefijo de ninguna
cadena del lenguaje.
Cmo debe informar un manejador de errores de la presencia de un error ?, al
menos debe informar del lugar en el programa fuente donde se detecta el error,
porque es muy probable que el error real se haya producido en alguno de los
componentes lxicos anteriores. Una estrategia comn empleada por muchos
compiladores e imprimir la lnea errnea con un apuntador a la posicin donde se
detecta el error. Si hay una posibilidad razonable de saber cul es realmente el error,
tambin se incluye un mensaje de diagnstico informativo y comprensible; por
ejemplo "Falta punto y coma en esta posicin".
Una vez detectado el error, Cmo se debe de recuperar el analizador
sintctico ?, En la mayora de los casos, no es adecuado que el analizador sintctico
abandone despus de detectar el primer error, porque el posterior procesamiento de

28

la entrada podra revelar ms errores. Normalmente, hay alguna forma de


recuperacin del error donde el analizador sintctico intenta volver l mismo a un
estado en el que el procesamiento de la entrada pueda continuar con una esperanza
razonable de que har el anlisis de la entrada correcta o de que ser manejada
correctamente por el compilador.
Una estrategia conservadora para un compilador es inhibir los mensajes de
error que provengan de errores descubiertos demasiado cerca uno de otros en la
cadena de entrada. Despus de descubrir un error sintctico, el compilador podra
exigir que varios componentes lxicos se analizarn sintcticamente con xito antes
de permitir otro mensaje de error. En algunos casos, puede haber demasiados
errores como para que el compilador contine un procesamiento razonable. Parece
que una estrategia de recuperacin de errores tiene que ser un compromiso
cuidadosamente considerado, teniendo en cuenta la clase de errores que se pueden
presentar y que sean de procesamiento razonable. Algunos compiladores intentan
reparar el error proceso en el cual el compilador intenta adivinar lo que pretenda
escribir el programador.
Hay muchas estrategias generales distintas que puede emplear un analizador
sintctico para recuperarse de un error sintctico. Aunque ninguna de ellas ha
demostrado ser la aceptacin universal, algunos mtodos tienen una amplia
aplicabilidad. Mencionaremos algunas estrategias, entre las cuales estn:

Recuperacin en modo de pnico: Este es el mtodo ms sencillo de


implantar y pueden utilizarlo la mayora de los mtodos de anlisis sintctico.
Al descubrir un error, el analizador sintctico desecha smbolo de entrada, de
uno en uno, hasta que encuentra uno perteneciente a un conjunto designado
de componente lxicos de sincronizacin. Estos componente lxicos de
sincronizacin son generalmente delimitadores, como el punto y coma o la
palabra clave end, cuyo papel en el programa fuente est claro. Es evidente
que quien disea el compilador debe seleccionar los componentes lxicos de
sincronizacin adecuados para el lenguaje fuente. Aunque la correccin en
modo de pnico a menudo omite una cantidad considerable de entrada sin
comprobar la existencia de errores adicionales, tiene la ventaja de la sencillez
y, a diferencia de otros mtodos, esta garantizado contra lazos infinitos. En
situaciones en donde son raros los errores mltiples en la misma proposicin,
este mtodo puede resultar bastante adecuado.

Recuperacin a nivel de frase: Al descubrir un error, el analizador sintctico


puede realizar una correccin local de la entrada restante; es decir, puede
sustituir un prefijo de la entrada restante por alguna cadena que permita
continuar al analizador sintctico. Una correccin local tpica sera sustituir
una coma por un punto y coma, suprimir un punto y coma sobrante e insertar
un punto y coma que falta. La eleccin de la correccin local corresponde al
diseador del compilador. Por supuesto se debe de tener cuidado de elegir
sustituciones que no conduzcan a lazos infinitos.
Este tipo de sustitucin puede corregir cualquier cadena de entrada y ha sido
empleado en varios compiladores que corrigen los errores. El mtodo se us por
primera vez en el anlisis sintctico descendente. Su principal desventaja es su

29

dificultad para afrontar situaciones en que el error real se produjo antes del punto de
deteccin.

Producciones de error: Si se tiene una buena idea de los errores comunes


que puede encontrarse, se puede aumentar la gramtica del lenguaje con
producciones que generen la construcciones errneas. Entonces se usa esta
gramtica aumentada con las producciones de error para construir el
analizador sintctico. Si el analizador sintctico usa una produccin de error,
se pueden generar diagnsticos de error apropiados para indicar la
construccin errnea reconocida en la entrada.

Correccin global: Idealmente, sera deseable que un compilador hiciera el


mnimo de cambios posibles al procesar una cadena de entrada incorrecta.
Existen algoritmos para elegir una secuencia mnima de cambios para
obtener una correccin global de menor costo. Dada una cadena de entrada
incorrecta x y la gramtica G, estos algoritmos encontrarn un rbol de
anlisis sintctico para una cadena relacionada y, tal que el nmero de
inserciones, supresiones y modificaciones de componentes lxicos
necesarios para transformar x en y sea el mnimo posible. Por desgracia, la
implantacin de estos mtodos es en general demasiado costosa en trminos
de tiempo y espacio, as que estas tcnicas en la actualidad slo son de
inters terico.

Se debe sealar que un programa correcto ms parecido al original puede no


ser lo que el programador tena en mente. Sin embargo, la nocin de correccin de
costo mnimo proporciona una escala para evaluar las tcnicas de recuperacin de
errores, y se ha usado para encontrar cadenas de sustitucin ptimas para
recuperacin a nivel de frase.
Gramticas.
Las gramticas describen lenguajes. Los lenguajes naturales como el
espaol, o el ingles, son con frecuencia descritos por una gramtica que agrupa las
palabras en categoras sintcticas tales como sujetos, predicados, frases
preposicionales, etc.
Expresndolo en forma matemtica, una gramtica es un dispositivo formal
para expresar un lenguaje potencialmente infinito, en una manera finita, puesto que
es imposible enumerar todas las cadenas de caracteres en un lenguaje, ya sea
espaol ingls o Pascal. Al mismo tiempo un gramtica impone una estructuras a la
sentencias en el lenguaje. Es decir una gramtica, G, define un lenguaje L(G)
mediante la definicin de una manera de para derivar todas las cadenas en el
lenguaje.
De una manera mas general:
Una gramtica es un sistema para definir un lenguaje, como tambin una
herramienta para imponer a las cadenas del lenguaje una estructura til.
Una gramtica G es una 4-tupla G = {N,,P, S} donde:

30

N : alfabeto de no-terminales " n N n


: alfabeto terminal
P : Conjunto finito de producciones consistente de expresiones de la forma
con (N )+ y (N )*
S : smbolo inicial S N
NS =
GRAMTICAS Y LENGUAJES SENSIBLES AL CONTEXTO.
Una forma de definir un lenguaje es mediante un reconocedor que acepte
las palabras que pertenecen a l. Los lenguajes sensibles al contexto contienen,
propiamente, a los lenguajes independientes al contexto a su vez, los lenguajes
recursivos contienen propiamente a los lenguajes sensibles al contexto.
DEFINICION FORMAL MATEMATICA DE LAS GRAMTICAS SENSIBLES AL
CONTEXTO (CSGS)

Es una 4-TUPLA formada por (N, S ,S ,P) donde:


N: Coleccin de smbolos no terminales.
: Alfabeto del lenguaje.
S: Smbolo especial llamado smbolo inicial.
P: Conjunto de producciones si todas las producciones son de la forma ,
donde , (N U )+ y | | <= | |.
El conjunto de los lenguajes sensibles al contexto contiene el conjunto de los
lenguajes independientes del contexto. La restriccin de que el lado derecho de las
producciones en una gramtica sensible al contexto sea al menos tan largo como el
lado izquierdo hace que la gramtica sea no contrctil. Puesto que la cadena vaca
tiene longitud c
L(G), para cualquier
gramtica que es sensible al contexto. A veces es conveniente que la cadena
pertenezca al lenguaje que ha sido generado por una gramtica sensible al contexto.
Clasificacin de las Gramticas.
Lenguaje

Gramtica

Autmata

Ejemplo

Lenguajes

Gramtica Regular

Detector deterministico
no deterministico
finito

a*

Regulares

+ Gramtica-lineal
Derecha
+
Gramtica-lineal
Izquierda

Lenguaje libre
de contexto

+ Gramtica libre de
contexto

Autmata pushdown
no

ab

31

deterministico
Lenguaje sensible al +Gramtica Sensible
contexto
al contexto
Lenguajes
Recursivos
Enumerables

+ Gramtica norestringida

Autmata LinealVinculada

abc

Maquina de Turng

Cualquier
Funcin
Computable

Jerarqua de Chomsky.
En 1959, Noam Chomsky clasific las gramticas en cuatro tipos de lenguajes
y esta clasificacin es conocida como la jerarqua de Chomsky, tal como se muestra
en al Tabla 3.1, en la cual cada lenguaje es descrito por el tipo de gramtica
generado. Estos lenguajes sirven como base para la clasificacin de lenguajes de
programacin.
Los cuatro tipos son: lenguajes recursivamente enumerables, lenguajes
sensibles al contexto, lenguajes libres de contexto y lenguajes regulares. Dichos
lenguajes tambin se identifican como lenguajes de tipo 0,1,2 y 3.
Las gramticas sensibles al contexto reciben el nombre de gramticas de tipo
1, porque del lado izquierdo puede haber ms de un elemento, lo que implica que un
smbolo puede reemplazarse en el contexto de otros.
Una gramtica es de tipo 1 si se exige que la longitud del miembro derecho de
toda regla de produccin sea mayor o igual que la longitud del izquierdo. Con esto
se impide que las cadenas que se obtengan en el transcurso de la aplicacin de las
reglas sean de longitud decreciente, y se impide as mismo el caso extremo de que
mediante una gramtica de tipo1 puedan desaparecer cadenas de smbolo.
Gramtica y lenguaje
Reconocedor
Que genera
Autmatas lineal
TIPO 1
(Sensible al contexto)
Entre las gramticas no restringidas y la forma restringida de las gramticas
independientes al contexto, se pueden definir varias gramticas con diferentes
niveles de restriccin.
Existe una exacta correspondencia entre cada uno de estos tipos de
lenguajes y particulares arquitecturas de mquinas en el sentido que por cada
lenguaje tipo T hay una arquitectura de mquina A que reconoce el lenguaje A hay
un tipo T tal que todos los lenguajes reconocidos por A son de tipo T. La
correspondencia entre lenguajes y arquitectura son mostrados en la siguiente tabla:
Tipo Lenguajes
0

Recursivamente
Enumerables

Sensibles

Tipo
Mquina

de

Mquina
Turing

de

al Autmata

32

contexto

Lineal Acotado

Libres de contexto

Autmatas
Pila

Autmatas
Lenguajes
Finitos
Regulares
Expresiones
Regulares
Los cuatro tipos de gramticas.

de

Sobre un alfabeto dado, el conjunto de lenguajes recursivamente


enumerables contiene propiamente al conjunto de lenguajes recursivos que contiene
propiamente al conjunto de lenguajes sensibles al contexto que contiene
propiamente al conjunto de lenguajes libres de contexto, que a su vez contiene
propiamente a los lenguajes regulares, tal como se muestra:

Gramticas Ambiguas

Si una oracin en espaol tiene mas de un significado, se dice que es ambigua. Con
frecuencia tales oraciones pueden analizarse sintcticamente en mas de una forma.
La oracin:
El tiempo vuela como una flecha.

33

Puede interpretarse tiempo como sustantivo, vuela como verbo y una flecha,
como una frase adverbial. Esta interpretacin es un comentario acerca del rpido
paso del tiempo. Sin embargo, si "tiempo" se interpreta como adjetivo, "vuela" como
sustantivo, "como" como un verbo y flecha como un sujeto directo, la oracin se
convertira en un comentario acerca de la vida amorosa de alguna especie.
En forma similar, se asigna significado a las construcciones en los lenguaje de
programacin con base en sus sintaxis. Por consiguiente, preferimos que las
gramticas de los lenguajes de programacin describan programas sin ambigedad
alguna.
Una sentencia es ambigua si hay mas de una derivacin distinta. Si una
sentencia es ambigua, su rbol de anlisis sintctico no es nico; podemos
crear mas de un rbol sintctico para la misma sentencia.
Una gramtica se dice que es ambigua si hay dos o ms rboles de
derivacin distintos para la misma cadena.
Para ver lo anterior consideraremos esta gramtica. O lo que es lo mismo:
Es la gramtica que produce mas de una derivacin por la derecha o por la
izquierda para la misma frase
S SbS | ScS | a
Podemos derivar la cadena "abaca" de dos formas distintas como sigue:
S SbS SbScS SbSca Sbaca abaca
S ScS SbScS abScS abacS abaca
El rbol de derivacin para la derivacin 1 es el que se muestra en la Figura:

Primer rbol de derivacin para la gramtica dada.


mientras que el rbol para la derivacin 2 es el que se muestra en la siguiente figura:

34

Segundo rbol de derivacin para la gramtica dada.


Obsrvese que los dos rboles son distintos, aunque las cadenas producida
son la misma. La ambigedad puede ser un problema para ciertos lenguajes en los
que su significado depende, en parte, de su estructura, como ocurre con los
lenguajes naturales y los lenguajes de programacin. Si la estructura de un lenguaje
tienen ms de una composicin y si la construccin parcial determina su significado,
entonces el significado es ambiguo.
La ambigedad no siempre es una propiedad inherente de los lenguajes; existen
gramticas ambiguas y no ambiguas para algunas construcciones.
Para demostrar que una gramtica es ambigua, lo nico que hay que
hacer es encontrar una cadena de componentes lxicos que tanga mas de un
rbol sintctico. Como una cadena que cuenta con mas de un rbol sintctico
suele tener mas de un significado, para aplicaciones de compilacin es necesario
disear gramticas no ambiguas o utilizar gramticas ambiguas con reglas
adicionales para resolver las ambigedades.
Recurdese que una gramtica independiente del contexto es ambigua si hay
dos derivaciones por la izquierda que son distintas para la misma cadena. La
gramtica independiente del contexto:
S ASB |SS |
B b
Es ambigua, ya que hay dos derivaciones por la izquierda de a2b2.
Por desgracia, en general no es posible determinar si una gramtica
independiente del contexto es ambigua. Es decir, la cuestin de la ambigedad de
gramticas independientes del contexto.
CONCEPTOS:

35

SMBOLO TERMINAL: Es un smbolo que no aparece en el lado izquierdo de


ninguna produccin.
NO TERMINALES: Los no-terminales son los nodos no-hojas en un rbol de anlisis
sintctico.
PRODUCCIONES: Se pueden pensar como un conjunto de reglas de reemplazo.
SMBOLO DE INICIO: El smbolo de partida o de inicio, tambin denominado
smbolo meta es un no- terminal especial diseado como el nico a partir del cual
todas las cadenas son derivadas.
FORMA SENTENCIAL: Una forma sentencial es cualquier cadena de caracteres
derivada desde el smbolo de inicio.
SENTENCIA: una sentencia es una forma que consiste solamente de terminales
tales como a + a * a

MTODOS DESCENDENTES O TOP-DOWN.


El anlisis sintctico descendente crea una derivacin ms a la izquierda, los
pasos son:
1)
2)

Comenzar con el smbolo de inicio como la raz del rbol de anlisis


sintctico.
En cada paso, reemplace el no terminal del lado izquierdo en la forma
sentencial actual.

Se puede considerar el anlisis sintctico descendente como un intento de


encontrar una derivacin por la izquierda para una cadena de
entrada. Equivalentemente puede ser visto como el intento de construir un rbol de
anlisis sintctico para la entrada comenzando desde la raz y creando los nodos del
rbol en orden previo. Por ejemplo considere la gramtica:
S cAd
A ab | a
y la cadena de entrada w = cad. Para construir un rbol de anlisis sintctico
descendente para esta cadena, primero se crea un rbol formado por un solo
nodo etiquetado con S. Un apuntador a la entrada apunta a c, el primer smbolo
de w. Despus se utiliza la primera produccin de S para expandir el rbol y
obtener el rbol de la Fig.(a).
Se empareja la hoja ms a la izquierda, etiquetada con c, con el primer
smbolo de w, y a continuacin se aproxima el apuntador de entrada a a, el segundo
smbolo de w, y se considera la siguiente hoja etiquetada con A. Entonces se puede
expandir A utilizando la primera alternativa de A para obtener el rbol de la Fig. (b).

36

Como ya se tiene una concordancia para el segundo smbolo de la entrada,


se lleva el apuntador de entrada a d, el tercer smbolo de la entrada, y se compara d
con la hoja siguiente, etiquetada con b. Como b no concuerda con d, se indica fallo y
se regresa a A para saber si existe otra alternativa de A que no se haya intentado,
pero se puede dar lugar a un emparejamiento.
Al regresar a A, se debe restablecer el apuntador de entrada a la posicin 2,
aquella que tenia al ir a A por primera vez, se intenta a continuacin la segunda
alternativa de A para obtener el rbol de la Fig. (c).
Se empareja la hoja a con el segundo smbolo de w, y la hoja d, con el tercer
smbolo. Como ya se ha producido un rbol de anlisis sintctico par w, se para y se
anuncia el xito de la realizacin completa del anlisis sintctico.

Pasos en el Anlisis Sintctico Descendente.


Anlisis Sintctico por Descenso Recursivo.
Un analizador sintctico de descenso recursivo se compone de un procedimiento
para cada smbolo no terminal de la gramtica, cuando se llama un procedimiento
este intenta encontrar una subcadena de la entrada, empezando por el
componente lxico actual, que se pueda interpretar como el no terminal con el
cul est asociado al procedimiento.

Durante este proceso puede llamar a otros procedimientos o llamarse a s


mismo recursivamente, para buscar otros no terminales. Si un procedimiento
encuentra el no terminal que pretende, devuelve una indicacin con xito a quin lo
llam, y tambin avanza el apuntador al componente lxico situado despus de la
subcadena que acaba de reconocer. Si el procedimiento es incapaz de encontrar
una subcadena que pueda interpretarse como el no terminal deseado, devuelve una
37

indicacin de fallo o invoca a una rutina de diagnstico y recuperacin de errores.


A

modo

de

ejemplo

considrese

la

siguiente

gramtica:

<lect> ::=READ(<lista_id)>
<lista_id> ::=id | <lista_id>,id

que definen la sintaxis de la proposicin READ del lenguaje PASCAL.

El procedimiento para <lect> es un analizador sintctico de descenso


recursivo examina primero los 2 siguientes componentes lxicos de entrada
buscando READ y (. Si se encuentran, entonces el procedimiento para <lect> llama
el procedimiento para <lista_id>. Si ese procedimiento tiene xito, el procedimiento
<lect>, examina el siguiente componente lxico buscando un ). Si todas estas
pruebas tienen xito el procedimiento <lect> devuelve una indicacin de xito a
quien lo llama y avanza al prximo componente lxico que sigue a ). En otro caso el
procedimiento
devuelve
una
indicacin
de
fallo.
El procedimiento es ligeramente ms complicado cuando hay varias opciones
definidas por la gramtica para un no terminal. En este caso el procedimiento debe
decidir que opcin intentar. Para la tcnica de descenso recursivo, se debe poder
decidir qu opcin utilizar examinando el siguiente componente lxico de entrada.
Hay otros mtodos descendentes que eliminan este requisito, aunque no son tan
eficientes
como
el
descendente
recursivo.
Si se intentara escribir los procedimientos para la gramtica anterior, se descubrira
un problema. El procedimiento para <lista_id>, sera incapaz de decidir entre sus
dos opciones, pues tanto id, como <lista_id> pueden comenzar con id. Sin embargo
hay una dificultad ms importante, si el procedimiento hubiera decidido intentar la
segunda opcin <(lista_id,id)>, se llamara de inmediato a si mismo recursivamente
para encontrar una <lista_id>. Esto podra producir otra llamada recursiva inmediata,
que dara lugar a una cadena sin fin. La razn de esto es que una de las opciones
para <lista_id> empieza con <lista_id>. Los analizadores sintcticos descendentes
no pueden usarse directamente con una gramtica que contenga esta clase de
recursin
por
la
izquierda
inmediata.

A continuacin se muestra la gramtica anterior por la recursin por la izquierda


eliminada:

<lect> ::= READ(<lista_id>)


<lista_id> ::= id<mas_id>
<lista_id> ::= , id <mas_id>|
Pudindose representarse tambin as:

38

<lect> ::= READ(<lista_id>)


<lista_id> ::= id{,id}
Esta notacin, que es una extensin comn a BNF, especifica que los
trminos entre { y } se pueden omitir o repetir una o mas veces. De esta forma la
gramtica define a <lista_id> compuesta de un id seguida de cero o mas ocurrencias
de ",id". Con la definicin revisada, el procedimiento para <lista_id> simplemente
busca primero un id, y despus sigue explorando la entrada mientras los dos
siguientes componentes lxicos sean una como(,) e id. Esto elimina el problema de
la recursin por la izquierda y tambin la dificultad de decidir que opcin intentar
para
<lista_id>.

Anlisis Sintctico descendente recursivo de una proposicin READ.


La Fig. anterior ilustra el anlisis sintctico descendente recursivo de la
proposicin READ, con la gramtica anterior. En el apartado (1), se ha llamado el
procedimiento LECT y se han examinado los componentes lxicos READ y "(" del
flujo de entrada (indicado con lneas punteadas). En el apartado (2), LECT ha
llamado a LISTA_ID (indicado con lnea continua), que ha examinado el componente
id. En el apartado (3), LISTA_ID ha vuelto a LECT indicando que ha tenido xito; por
lo que LECT ha examinado el componente lxico de entrada ), con esto se completa
el anlisis de la proposicin fuente. El procedimiento READ regresara ahora a quin
lo llam, indicando que se encontr satisfactoriamente un <lect>. Obsrvese que la
secuencia de llamadas a procedimientos y la exploracin de componentes lxicos ha
definido por completo la estructura de la proposicin READ.

39

Ejemplo Descendente Recursivo


Gramtica

Programa

Sentencias

Sentencias'

Sentencia

Asignacin

Expresin

Expresin'

Termino

Termino'

Factor
|
|

Sentencias
Sentencia Sentencias'
Sentencias |
Asignacin ;
Id := Expresin
Termino Expresin'
+ Termino Expresin' |
Factor Termino'
* Factor Termino' |
( Expresin )
Id
Literal

Anlisis sintctico Predictivo.


Un analizador sintctico predictivo, llamado tambin anlisis sintctico
descendente recursivo es un mtodo descendente en el que se ejecuta un conjunto
de producciones para procesar una entrada, a cada smbolo no terminal de una
gramtica se le asocia con una produccin. Es una forma eficiente de implementar el
anlisis sintctico descendente implcitamente manteniendo una pila, en vez de
hacerlo implcitamente mediante llamadas recursivas. El modelo sintctico predictivo
puede verse en la figura de abajo. Un analizador sintctico es guiado por una tabla
en la que se encuentran las producciones.

40

Modelo de un analizador sintctico predictivo.


Caractersticas:
Es una forma eficiente de un analizador sintctico recursivo.
Mantiene una PILA en vez de hacer llamadas recursivas.
El analizador sintctico predictivo tiene una ENTRADA, una TABLA de
anlisis sintctico y una SALIDA, adems de la
PILA.
La Pila contiene una secuencia de smbolos de alguna gramtica que debe
de finalizar con un $ (delimitador).
El elemento inicial de la gramtica debe de ser la cima de la PILA.
La TABLA es un arreglo bidimensional (matriz), M [smbolo_no_terminal ,
smbolo_terminal_$]
El analizador sintctico esta controlado por un programa que trabaja como sigue.
El programa determina a X, el smbolo en la cima de la pila, y a, el smbolo de la
entrada actual. Estos dos smbolos determinan la accin del analizador sintctico:
hay tres posibilidades:
1.Si X = a = $, el analizador sintctico se detiene y anuncia el xito de la
realizacin del anlisis sintctico.
2.Si X = a$, el analizador sintctico saca a X dela pila y avanza el apuntador
de entrada al siguiente smbolo de entrada.
3.Si X es un smbolo no terminal el programa consulta la entrada M[X,a] de la
tabla de anlisis sintctico. Esta entrada podra ser una produccin cualquiera de la
gramtica o un error. Si M[X,a] = {XUVW}, el analizador sintctico reemplaza a X
en la cima de la pila por WVU (con U en la cima). Si M[X,a] = error el analizador
sintctico llama a una rutina de recuperacin de error.
Se puede describir el comportamiento del analizador sintctico en trminos de
su configuracin, la cual es dada por el contenido de la pila y la entrada restante.
Inicialmente el analizador sintctico esta en la configuracin:
Pila
Entrada
$S
w$

41

donde S es el smbolo de inicio dela gramtica y w es la cadena que ha de ser


analizada.
Gramtica
E TE'
E' TE' |
T FT'
T' FT |
F (E) | id
Algoritmo
1.
Si X = a = $, el analizador sintctico se detiene y anuncia el xito de la
realizacin del anlisis sintctico.
2.
Si X = a $,el analizador sintctico saca a X de la pila y avnzale
apuntador de entrada al siguiente smbolo de entrada.
3.
Si X es un smbolo no terminal el programa consulta la entrada M[X,a]
de la tabla de anlisis sintctico. Esta entrada podra ser una produccin cualquiera
dela gramtica o un error. Si M[X,a] = {XUVW}, el analizador sintctico reemplaza
a X en la cima dela pila por WVU (con U en la cima). Si M[X,a] = error el analizador
sintctico llama a una rutina de recuperacin de error.
Se puede describir el comportamiento del analizador sintctico en trminos de
su configuracin, la cual es dada por el contenido de la pila y la entrada restante.
Inicialmente el analizador sintctico esta en la configuracin:
Pila
Entrada
$S
w$
donde S es el smbolo de inicio dela gramtica y w es la cadena que ha de ser
analizada.
Matriz de precedencia resultante
id
E

E TE
E E

E +TE
T FT

T FT
T

T
F

E TE

E
T

F id

T *FT

F(E)

Anlisis
Se analizar la cadena siguiente:
id + id * id $

42

Paso 1
Inicialmente la pila contiene el smbolo de inicio de la gramtica precedido por el
delimitador "$", as que tenemos en la pila a "$E". Y en la entrada tenemos a la
cadena completa.
Paso Pila
Entrada
Salida
1

$E

id + id * id $

Paso 2
En la cima de la pila tenemos a "E" verificamos en la gramtica y tenemos que es un
no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = E por su
produccin la cual es TE'. Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' T", y la salida ser la produccin del no terminal "E".
Paso 3
En la cima de la pila tenemos a "T" verificamos en la gramtica y tenemos que es un
no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = T por su
produccin la cual es FT'. Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' T' F", y la salida ser la produccin del no terminal "T".
Paso 4
Como la cima de la pila esta X= F y este produce el smbolo de la cadena leda, se
sustituye por su produccin que es el terminal "id" y avanza el apuntador de entrada
al siguiente smbolo de la cadena, ahora tendremos en la pila "$ E' T' id", y la salida
ser la produccin de "F".
Paso 5
Como "id" es igual al smbolo de entrada actual se compara y se saca de la pila y
avanza el apuntador al siguiente smbolo de entrada.
Paso 6
En la cima de la pila tenemos a "T'" verificamos en la gramtica y tenemos que es un
no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = T' por su
produccin la cual es . Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' " "$ E' ", y la salida ser la produccin del no terminal "
T' ".
Paso 7
En la cima de la pila tenemos a " E' " verificamos en la gramtica y tenemos que es
un no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = E' por su
produccin la cual es +TE'. Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' T +" y la salida ser la produccin del no terminal " E' ".
Paso 8
Como "+" es igual al smbolo de entrada actual se compara y se saca de la pila y
avanza el apuntador al siguiente smbolo de entrada.
Paso 9
En la cima de la pila tenemos a " T " verificamos en la gramtica y tenemos que es
un no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = T por su
produccin la cual es FT'. Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' T' F" y la salida ser la produccin del no terminal " T ".

43

Paso 10
Como la cima de la pila esta X= F y este produce el smbolo de la cadena leda, se
sustituye por su produccin que es el terminal "id" y avanza el apuntador de entrada
al siguiente smbolo de la cadena, ahora tendremos en la pila "$ E' T' id", y la salida
ser la produccin de "F".
Paso 11
Como "id" es igual al smbolo de entrada actual se compara y se saca de la pila y
avanza el apuntador al siguiente smbolo de entrada.
Paso 12
En la cima de la pila tenemos a " T' " verificamos en la gramtica y tenemos que es
un no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = T' por su
produccin la cual es *FT'. Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E' T' F *" y la salida ser la produccin del no terminal " T' ".
Paso 13
Como "*" es igual al smbolo de entrada actual se compara y se saca de la pila y
avanza el apuntador al siguiente smbolo de entrada.
Paso 14
Como la cima de la pila esta X= F y este produce el smbolo de la cadena leda, se
sustituye por su produccin que es el terminal "id" y avanza el apuntador de entrada
al siguiente smbolo de la cadena, ahora tendremos en la pila "$ E' T' id", y la salida
ser la produccin de "F".
Paso 15
Como "id" es igual al smbolo de entrada actual se compara y se saca de la pila y
avanza el apuntador al siguiente smbolo de entrada.
Paso 16
En la cima de la pila tenemos a " T' " verificamos en la gramtica y tenemos que es
un no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = T' por su
produccin la cual es . Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E'" "$ E' " y la salida ser la produccin del no terminal " T'
".
Paso 17
En la cima de la pila tenemos a " E' " verificamos en la gramtica y tenemos que es
un no terminal, ocupamos la regla 3 del algoritmo, y reemplazamos X = E' por su
produccin la cual es . Introduciremos la produccin en el orden inverso, y
tendremos en la pila "$ E'" "$ E' " y la salida ser la produccin del no terminal " T'
".
Paso

Pila

Entrada

$E

id + id * id $

$ E' T

id + id * id $

Salida
E TE

44

$ E' T' F

id + id * id $

T FT

$ E' T' Id

id + id * id $

F id

$ E' T'

+ id * id $

$ E'

+ id * id $

$ E' T +

+ id * id $

E +TE

$ E' T

id * id $

$ E' T' F

id * id $

T FT

10

$ E' T' Id

id * id $

F id

11

$ E' T'

* id $

12

$ E' T' F *

* id $

13

$ E' T' F

id $

14

$ E' T' Id

id $

15

$ E' T'

16

$ E'

17

T *FT
F id

En la cima de la pila tenemos a " $ " y este es igual al smbolo ledo y a su vez es
igual al delimitador, entonces el analizador sintctico se detiene y anuncia el xito de
la realizacin del anlisis de la cadena.

MTODOS ASCENDENTES O BOTTOM UP.


El anlisis sintctico por desplazamiento intenta construir un rbol de anlisis
sintctico para una cadena de entrada que comienza por las hojas (el fondo) y
avanza hacia la raz (la cima). Se puede considerar este proceso como de "reducir"
una cadena w al smbolo inicial de la gramtica. En cada paso de reduccin se
sustituye una subcadena determinada que concuerde con el lado derecho de una
produccin por el smbolo del lado izquierdo de dicha produccin y si en cada paso
se elige correctamente la subcadena, se traza una derivacin por la derecha en
sentido inverso.
Considrese la siguiente gramtica:
S aABe
A Abc | b
Bd
La frase "abbcde" se puede reducir a S por los siguientes pasos:
abbcde
aAbcde
aAde
aABe
S

45

Se examina abbcde buscando una subcadena que concuerde con el lado


derecho de alguna produccin. La subcadenas b y d sirven. Eljase la b ms situada
a la izquierda y sustityase por A, el lado izquierdo de la produccin A b; as se
obtiene la cadena aAbcde. A continuacin, las subcadenas Abc, b y d concuerdan
con el lado derecho de alguna produccin. Aunque b es la subcadena situada ms a
la izquierda que concuerda con el lado derecho de una produccin, se elige sustituir
la subcadena Abc por A, que es el lado derecho de la produccin A Abc. Se
obtiene ahora aAde. Sustituyendo despus d por B que es el lado izquierdo de la
produccin B d, se obtiene aABe, ahora se puede sustituir toda la cadena por S.
Por tanto, mediante una secuencia de cuatro reducciones se puede reducir abbcde a
S. De hecho, estas reducciones trazan la siguiente derivacin por la derecha en
orden inverso:
S aABe aAde aAbcde abbcde

Anlisis Sintctico de Precedencia Simple.


Este mtodo realiza el anlisis sintctico buscando rpidamente el mango
(frase simple mas a la izquierda) u de la forma sentencial actual y reducindola a un
no terminal U, usando una regla U u . El problema en cualquier analizador
sintctico ascendente es encontrar el mango, entonces saber a que no terminal se
reducir.
Dada una forma sentencial X, considerar dos smbolos R y S en el
vocabulario V de una gramtica G . Suponer que hay una forma sentencial ...RS... .
En algn punto cualquiera R o S (o ambas), deben de estar en un mango. Las
siguientes tres posibilidades surgiran:
R es parte de un mango pero S no Fig. (a). En este caso escribimos R > S y decimos
que R es mas grande que S, o que R tiene precedencia sobre S, porque deber ser
reducido primero. Note que R deber ser el smbolo final de alguna regla U ...R.
Note que debido a que el mango esta a la izquierda de S, S deber ser un terminal.
R y S estn ambos en un mango Fig.(b). Decimos que R S, ellos tienen la misma
precedencia y debern ser reducidos al mismo tiempo. Obviamente deber existir
una regla U ...RS... en la gramtica.
S es parte de un mango pero R no Fig. (c), decimos que R < S o que R es menor
que S y S deber ser la cabeza de alguna regla U S...
Si no hay una funcin sentencial ...RS... entonces decimos que no hay relacin entre
el par ordenado(R,S).

46

Ilustracin de las Relaciones de Precedencia.


Algoritmo de Anlisis de Precedencia Simple.
Cuando se usan las relaciones de precedencia para reconocer sentencias, lo
mejor es usar una forma compacta para representarlas, la tcnica usual es tener la
matriz P con los valores:
P[i,j] = 0
P[i,j] = 1
P[i,j] = 2
P[i,j] = 3

si no existe relacin entre Si y Sj


si Si < Sj
si Si = Sj
si Si > Sj

Podemos hacer esto para una gramtica de precedencia porque sabemos


que a lo sumo una relacin existe entre los entre dos smbolos cualquiera.
Las reglas deben estar en una tabla, estructurada de tal forma que, dado un
lado derecho, podamos encontrarlo en las reglas y encontrar el correspondiente lado
izquierdo.
El algoritmo trabaja como sigue: Los smbolos de la cadena de entrada son
procesados de izquierda a derecha y almacenados en una pila S, hasta que la
relacin de precedencia > exista entre el smbolo de la cima de la pila y el siguiente
smbolo entrante. Esto significa que el smbolo de la cima de la pila es el final del
mango, y por lo tanto el mango entero esta en la pila. Este mango es entonces
encontrado en la lista de reglas y reemplazado en la pila, por el correspondiente no
terminal el cual debe ser reducido. El proceso se repite hasta que la pila contenga Z
y el siguiente smbolo de entrada sea $ (delimitador). Cada forma sentencial est
encerrada entre los smbolos $ y $ (asumiendo que $ no es un smbolo de la
gramtica). Adems se establece que $ < S y S > $ para cualquier smbolo S de la
gramtica.
En la Fig. se muestra un diagrama de flujo para el analizador sintctico
usando la siguiente notacin:
S es una pila usada para mantener los smbolos; su contador es i.
j es un ndice usado para hacer referencia los elementos en la cima de la pila.
La sentencia a ser analizada sintcticamente es TiT2...Tn. Empezamos con el
delimitador de la sentencia $ en la pila y asumimos que ha sido anexada a la
sentencia como T[n+1].

47

Q y R son variables para mantener ciertos smbolos durante el proceso de


anlisis.
Note que la cadena T1...Tn no es una sentencia, entonces el algoritmo parar
e indicar esto.

Analizador sintctico de precedencia simple.


BLOQUE 1: Inicializar la pila S para mantener el delimitador de sentencia ($).
Poner el ndice de la sentencia apuntando al primer smbolo.
BLOQUE 2: Obtener el siguiente smbolo, colocarlo en R e incrementar k.
BLOQUE 3 - 4: Si (S(i),R) no esta en >, el mango no esta completamente en
la pila, entonces metemos R en la pila y obtenemos el siguiente smbolo.
BLOQUE 5 - 7: Si S(i) >R, el mango deber estar en la pila. Estos bloques
buscan la cabeza del mango.
BLOQUE 8 - 9 :Checar la cadena S(j)...S(i). Si no esta en la parte derecha de
una regla, el proceso ha terminado. La cadena fue una sentencia si y solamente si 1
= 2 y S(i) = Z. Si es la parte derecha de una regla, borramos el mango de la pila
(bloque 9), metemos en la pila el smbolo el cual es reducido y regresamos al bloque
3 para buscar el siguiente mango.
Una ventaja acerca de este y otros analizadores sintcticos similares es que
la cadena completa de los smbolos de entrada no necesitan estar en memoria al
mismo tiempo. Los smbolos son ledos uno a la vez de la entrada y almacenados en
48

la pila, pero como el mango es reducido, estos desaparecen. Solamente si el mango


est en el final derecho de la cadena necesita que la cadena completa est
almacenada.
Ejemplo
Gramtica
E E + T | T
T T * F | F
F ( E ) | id
Matriz de precedencia resultante
E

id

>

>

>

>

>

*
(

<

<

<

<

<

<

<

<

<

>

>

>

id

>

>

>

Anlisis
Se analizar la cadena siguiente:
(x+y)
Pas
Relaci
Toke
Pila
R
o
n
n
0

<

( x+y)$

$(

<

x +y)$

$(x

>

y)$

$(E

y)$

$(E+

<

)$

$(E+y

>

$(E+
T

>

$(E

$(E)
>
$
$
Anlisis Sintctico LR.

El nombre de esta tcnica de anlisis sintctico LR(k) proviene de L por el


exmen de la entrada de izquierda a derecha (en ingls Left-to-Right), la R por

49

construir una derivacin por la derecha (en ingls rightmost derivation) en orden
inverso, y la k por el nmero de smbolos de entrada de examen por anticipado
utilizados para tomar las decisiones del anlisis sintctico. Cuando sta se omite, se
asume que k es 1. Esta tcnica de anlisis sintctico resulta conveniente por varias
razones:
Se puede construir analizadores sintcticos LR para reconocer prcticamente
todas las construcciones de los lenguajes de programacin para los que se
pueden escribir gramticas libres de contexto.
El mtodo de anlisis sintctico LR es el mtodo de anlisis por
desplazamiento y reduccin sin retroceso ms general que se conoce y sin embargo
se puede aplicar tan eficientemente como los otros mtodos de desplazamiento y
reduccin.
La clase de gramticas que pueden analizarse con los mtodos LR es un
supraconjunto de la clase de gramticas que se puedan analizar con analizadores
sintcticos predictivos.
Un analizador sintctico predictivo LR puede detectar un error sintctico tan
pronto como sea posible hacerlo en un examen de izquierda a derecha de la
entrada.
El principal inconveniente del mtodo es que supone demasiado trabajo
construir un analizador sintctico LR a mano para una gramtica de un lenguaje de
programacin tpico. Se necesita una herramienta especializada: un generador de
analizadores sintcticos LR, por ejemplo YACC. Con este generador se puede
escribir una gramtica libre de contexto y el generador produce automticamente un
analizador sintctico para dicha gramtica .

Modelo de un analizador sintctico LR.


En la Fig se muestra de forma esquemtica de un analizador sintctico LR.
Consta de una entrada, una salida, una pila, un programa conductor y una tabla de
anlisis sintctico de dos partes (accin, ir_a). El programa conductor es el mismo
para todos los analizadores sintcticos LR; solo cambian las tablas de un analizador
a otro. La tabla de anlisis sintctico consta de dos partes, la funcin accin que

50

indica una accin del analizador, y la funcin ir_a, que indica las transiciones entre
los estados.

Realizacin
Gramtica
EE+T
ET
TT*F
TF
F(E)
F id
Algoritmo
inicializar la pila al estado cero
agregar $ al final de la entrada
apuntar al
Accin
smbolo de
Estado
repetir
id
+
*
(
)
0
d5
d4
estado de
1
d6
la pila y
el smbolo
actual
accin
desplazar

ir_a
E T F
1 2 3

Aceptar

primer
la entrada
begin
sea s el
la cima de
a
de entrada
if
[s,a] =
# then
begin

meter a y despus # (el nuevo estado) en la pila


avanzar al siguiente smbolo de entrada
end
else if accin [s,a] = reducir A then
begin
sacar 2*| | smbolos de la pila
sea S el estado que ahora esta en la cima de la pila
meter a y despus ir_a[s,a] en la pila.
end
else if accin[s,a] = aceptar then
Return
else error()
end.
Matriz de precedencia resultante

51

Anlisis

2
3
4
5
6

d5
d5

d4

d5

d4

8
9
10
11

r2
r4

d7
r4

r6

r6

r2
r4

r2
r4

r6

r6

d4

d6
r1
r3
r5

d7
r3
r5

8 2 3
9 3
1
0
d11
r1
r3
r5

r1
r3
r5

Inicializa la pila al estado cero, agregar el smbolo $ al final de la cadena de


entrada, paso 1:
id*(id+id)

Pila
(1) 0

Entrada Accin S a
id*(id+id)$

0 id

Como [S,a] = [0,id], tenemos a S5 que es = desplazar, entonces se mete a


(id) y despus a # (5) (el nuevo estado) en la pila, avanzar al siguiente smbolo, paso
2:
Verificando en la tabla tenemos (R6), como [S,a] = [5,*] = reducir A , =
1 tenemos que sacar 2*||, ahora el tope de la pila es 0 y F el lado izquierdo de la
produccin 6, meter A que es F y el 3 obtenido en la interseccin 0,F, paso 3:
Verificando en la tabla tenemos (R4), como [S,a] = [3,*] = reducir A , =
1 tenemos que sacar 2*||, ahora el tope de la pila es 0 y T el lado izquierdo de la
produccin 4, meter A que es T y el 2 obtenido en la interseccin 0,T, paso 4:

Verificando en la tabla tenemos (S7), como [S,a] = [2,*] = desplazar, entonces


se mete a(*) y despus a # (7) (el nuevo estado) en la pila, avanzar al siguiente
smbolo, paso 5:
Verificando en la tabla tenemos (S4), como [S,a] = [7,(] = desplazar, entonces
se mete a(() y despus a # (4) (el nuevo estado) en la pila, avanzar al siguiente
smbolo, paso 6:
Verificando en la tabla tenemos (S5), como [S,a] = [4,id] = desplazar,
entonces se mete a(id) y despus a # (5) (el nuevo estado) en la pila, avanzar al
siguiente smbolo, paso 7:

52

Verificando en la tabla tenemos (R6), como [S,a] = [5,+] = reducir A , =


1 tenemos que sacar 2*||, ahora el tope de la pila es 4 y F el lado izquierdo de la
produccin 6, meter A que es F y el 3 obtenido en la interseccin 4,F, paso 8:
Verificando en la tabla tenemos (R4), como [S,a] = [3,+] = reducir A , =
1 tenemos que sacar 2*||, ahora el tope de la pila es 4 y T el lado izquierdo de la
produccin 4, meter A que es T y el 2 obtenido en la interseccin 4,T, paso 9:
Verificando en la tabla tenemos (R2), como [S,a] = [2,+] = reducir A , =
1 tenemos que sacar 2*||, ahora el tope de la pila es 4 y E el lado izquierdo de la
produccin 2, meter A que es E y el 8 obtenido en la interseccin 4,E, paso 10:
Verificando en la tabla tenemos (S6), como [S,a] = [8,+] = desplazar, entonces
se mete a(+) y despus a # (6) (el nuevo estado) en la pila, avanzar al siguiente
smbolo, paso 11:
Verificando en la tabla tenemos (S5), como [S,a] = [6,id] = desplazar,
entonces se mete a(id) y despus a # (5) (el nuevo estado) en la pila, avanzar al
siguiente smbolo, paso 12:
Verificando en la tabla tenemos (R6), como [S,a] = [5,)] = reducir A , = 1
tenemos que sacar 2*||, ahora el tope de la pila es 6 y F el lado izquierdo de la
produccin 6, meter A que es F y el 3 obtenido en la interseccin 6,F, paso 13:
Verificando en la tabla tenemos (R4), como [S,a] = [3,)] = reducir A , =
1 tenemos que sacar 2*||, ahora el tope de la pila es 6 y T el lado izquierdo de la
produccin 4, meter A que es T y el 9 obtenido en la interseccin 6,T, paso 14:
Verificando en la tabla tenemos (R1), como [S,a] = [9,)] = reducir A , =
3 tenemos que sacar 2*||, ahora el tope de la pila es 4 y E el lado izquierdo de la
produccin 1, meter A que es E y el 8 obtenido en la interseccin 4,E, paso 15:
Verificando en la tabla tenemos (S11), como [S,a] = [8,)] = desplazar,
entonces se mete a()) y despus a # (11) (el nuevo estado) en la pila, avanzar al
siguiente smbolo, paso 16:
Verificando en la tabla tenemos (R5), como [S,a] = [11,$] = reducir A ,
= 3 tenemos que sacar 2*||, ahora el tope de la pila es 7 y F el lado izquierdo de la
produccin 5, meter A que es F y el 10 obtenido en la interseccin 7,F, paso 17:
Verificando en la tabla tenemos (R3), como [S,a] = [10,$] = reducir A ,
= 3 tenemos que sacar 2*||, ahora el tope de la pila es 0 y T el lado izquierdo de la
produccin 3, meter A que es T y el 2 obtenido en la interseccin 0,T, paso 18:
Verificando en la tabla tenemos (R2), como [S,a] = [2,$] = reducir A , = 1
tenemos que sacar 2*||, ahora el tope de la pila es 0 y E el lado izquierdo de la
produccin 2, meter A que es E y el 1 obtenido en la interseccin 0,E, paso 19:
Pila

Entrada

Accin

53

(1) 0

id*(id+id)$

S5

id

(2) 0 id 5

*(id+id)$

R6

(3) 0 F 3

*(id+id)$

R4

(4) 0 T 2

*(id+id)$

S7

(5) 0 T 2 * 7

(id+id)$

S4

(6) 0 T 2 * 7 ( 4

id+id)$

S5

id

(7) 0 T 2 * 7 ( 4 id 5

+id)$

R6

(8) 0 T 2 * 7 ( 4 F 3

+id)$

R4

(9) 0 T 2 * 7 ( 4 T 2

+id)$

R2

(10) 0 T 2 * 7 ( 4 E 8

+id)$

S6

(11) 0 T 2 * 7 ( 4 E 8 + 6

)$

S5

id

(12) 0 T 2 * 7 ( 4 E 8 + 6 id 5

)$

R6

(13) 0 T 2 * 7 ( 4 E 8 + 6 F 3

)$

R4

(14) 0 T 2 * 7 ( 4 E 8 + 6 T 9

)$

R1

(15) 0 T 2 * 7 ( 4 E 8

)$

S11

(16) 0 T 2 * 7 ( 4 E 8 ) 11

R5

11

(17) 0 T 2 * 7 F 10

R3

10

(18) 0 T 2

R2

(19) 0 E 1

Verificando en la tabla tenemos (Aceptar), por lo tanto la cadena ha sido


completamente aceptada
Matrices de Transicin.
Una matriz de transicin es una matriz o tabla M, cuyos renglones
representan las "cabezas" (cadenas de smbolos, las cuales terminan en un smbolo
terminal) de los lados derechos de las reglas de las gramticas, las cuales pueden
aparecer en la pila, y cuyas columnas representan los smbolos terminales,
incluyendo el delimitador $. Los elementos de la matriz sern nmeros o direcciones
de subrutinas.
La Tabla muestra la estructura de una matriz de transicin para la siguiente
gramtica (parcialmente llena).
Gramtica:
<prog>
<estado>
<estado>
<expr>
<var>

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

<estado>
IF <expr> THEN <estado>
<var> := <expr>
<expr> + <var> | <var>
id
$
$
IF

IF
1

THEN := + id
1

54

IF <expr>
THEN
<var> :=
<expr> +
id
Tabla parcialmente llena para la gramatica dada.
El analizador sintctico utiliza la tpica pila S y la variable para el smbolo
entrante R. Aunque la estructura de la pila tiene una pequea diferencia; en lugar de
slo smbolos, se permitir que cadenas de smbolos aparezcan en la pila. Las
cadenas que aparezcan aqu sern cabezas (las cuales terminan en un smbolo
terminal) de las partes derechas de las reglas. Por ejemplo, si la pila convencional
en algn momento contiene:
$ IF <expr> THEN IF <expr> THEN <var>:=
La pila podra verse como:
<var>:=
IF <expr> THEN
IF <expr> THEN
$
Note que todo lo que se hace es mantener juntos todos esos smbolos; los
cuales sabemos, debern ser reducidos al mismo tiempo. Tambin se utilizar una
variable U, sta estar vaca o contendr el smbolo el cual la ltima frase ha sido
reducida. As, si la cadena parcial analizada hasta el momento es:
$ IF <expr> THEN IF <expr> THEN <var>:= <expr>
Entonces la pila se vera como arriba y <expr> estara en U.
El analizador sintctico usa la matriz como sigue. En cada paso el elemento
en la cima de la pila corresponde a algn rengln de la matriz, debido a que ambas
representan la cabeza (terminando en un smbolo terminal) de alguna parte derecha.
El smbolo terminal entrante determina una columna de la matriz. Estas dos juntas
determinan un elemento de la matriz el cual es el nmero de subrutina a ejecutar.
Esta subrutina ejecuta la reduccin necesaria o mete en la pila a R y obtiene el
siguiente smbolo de entrada.
Realizacin del Anlisis de Matriz de Transicin.
Para llevar a cabo el anlisis sintctico y al mismo tiempo construir la matriz,
se har uso de una pila S que en cuestin a su estructura es algo diferente a las ya
conocidas, ya que en estas podemos almacenar no nicamente smbolos sino
tambin cadenas de smbolos, stas cadenas sern las cabezas que definimos
como renglones de la matriz y tambin se hace uso de una variable (R) que
especificar el smbolo o los smbolos que puedan entrar a la pila.
Ejemplo: Podemos tener en X momento esta expresin dentro de la pila:

55

$ IF <expr> THEN IF <expr> THEN <var>:=


La pila podra verse como:
<var>:=
IF <expr> THEN
IF <expr> THEN
$
Tambin se hace uso de una variable U, la cual estar vaca o contendr el
smbolo de la ltima frase reducida.
En cada paso el elemento que se encuentre en la cima de la pila
corresponder a algn rengln de la matriz, el smbolo terminal R determinar la
columna de la matriz y los elementos pertenecientes a la matriz sern los nmeros
de subrutinas a ejecutar, las subrutinas tendrn la tarea de meter a R en la pila o de
llevar a cabo una reduccin.
Ejemplo:
Cuando iniciamos el anlisis $ esta en la pila y la variable U est vaca, de
acuerdo a la gramtica que usamos en este ejemplo, el smbolo entrante debe ser IF
e id debido a que estas inician partes derechas, por lo que colocaremos el nmero 1
(que corresponde a la primera subrutina) en el rengln $ que es el elemento en la
cima de la pila y en las columnas IF e id, despus realizaremos la subrutina.
U=
R=

$
$
$
IF
IF <expr>
THEN
<var> :=
<expr> +
id

IF
1

THEN := + id
1

Subrutina 1: IF U <> " " then ERROR;


i := i + 1 ;
S(i) = R ;
SIGCOMPLEX.
La funcin SIGCOMPLEX coloca el siguiente smbolo de la cadena de
entrada en R.

id
IF
$

U=
R=

56

Ahora haremos un recorrido en la matriz para ver o indicar en que otras


posiciones en la matriz se puede realizar la subrutina 1, para esto se debe de
analizar que posible smbolo terminal de la columna podra seguirle al elemento
terminal del rengln.
En el rengln IF basndonos en la regla 2, <expr> le sigue al smbolo IF y
como vemos en la regla 4 <expr>:= <var> y en la regla 5 <var>:= id ; por lo tanto id
puede ser un smbolo que le siga a IF por lo tanto colocamos en nmero 1 en la fila
IF columna id.
En el rengln IF <expr> THEN, basndonos en la regla 2, <estado> le sigue al
smbolo THEN y como vemos en la misma regla 2 <estado>:= IF <expr> THEN
<estado>; por lo tanto IF puede ser un smbolo que le sigue a THEN y colocamos
tambin el nmero 1 de la subrutina en la fila IF <expr> THEN columna IF; tambin
vemos en la regla 3 que <estado>:= <var>:= <expr> y en la regla 5 <var>:= id por lo
tanto tambin id puede ser un smbolo que le siga a THEN y tambin colocamos el
nmero 1 en la misma fila pero en la columna id.
Valindose de estas reglas la matriz al terminar este paso queda:
$
$
IF
IF <expr>
THEN
<var> :=
<expr> +
id

IF
1
1

THEN := + id
1
1
1
1
1

como vemos ahora en la cima de la pila se encuentra el smbolo id, por lo que
iremos al rengln id de la matriz y analizaremos que smbolo (de las columnas)
puede ser vlido en R, es decir, que smbolo podra seguirle a id y vemos que los
smbolos $, THEN, := + son vlidos, esto es porque se puede tener una expresin
como la siguiente:
IF id THEN id:= id + id $
por lo tanto la matriz queda:
$
$
IF
IF <expr>
THEN
<var> :=
<expr> +
id

IF
1
1

THEN := + id
1
1
1

1
1
2 2 2

Subrutina 2: IF U <> " " then ERROR;


i: = i - 1;
U = '<var>'.
Aqu se hace una reduccin y la pila queda:

57

IF
$

U = ' <var> '


R=

Ahora en la cima de la pila se encuentra el smbolo IF por lo que iremos al


rengln IF de la matriz y analizaremos que smbolo (de las columnas) puede ser
vlido en R, es decir que smbolo podra seguir a IF pero tomando e cuenta que
tenemos a <var> en U. Vemos que en el rengln IF la nica que satisface tal
condicin es el smbolo + , as como tambin en el rengln <var>:=.
Por lo tanto la matriz quedar:
$ IF THEN := + id
$
1
1
IF
3 1
IF <expr>
1
1
THEN
<var> :=
3 1
<expr> +
1
id
2
2
2 2 2
Subrutina 3: IF U <> '<expr>' and U <> '<var>'then ERROR;
i := i + 1 ;
S(i) = '<expr>'+
SIGCOMPLEX.

'<expr>+'
U = ' <var> '
IF
R=
$
Ahora nos posicionamos en la fila <expr>+ de la matriz y analizaremos que
smbolo (de las columnas) puede ser vlido en R, es decir que smbolo podra seguir
a <expr>+ tomando en cuenta tambin a <var> que esta en U y vemos que los
smbolos $, THEN + son vlidos, porque se puede tener una expresin como la
siguiente:
IF <expr>+<var> THEN <var>:= <expr>+<var>+<var> $
<expr>

+<var>

Por lo tanto la matriz quedar:


$ IF
$
1
IF
IF <expr>
1
THEN
<var> :=
<expr> +
4
id
2
Subrutina 4: IF U <> "<var>" then ERROR;
i := i - 1 ;
U = '<expr>'

THEN := + id
1
3 1
1

4
2

3 1
4 1
2 2 2

58

'<expr>+'
U = ' <var> ' := '<expr>'
IF
R=
$
Se hizo aqu otra reduccin.
Se siguen los mismos procedimientos, aunque cabe aclarar que en la
subrutina 5, se hace una parada.
Subrutina 5: IF U <> '<prog>' and U <> '<estado>' then ERROR;
STOP
de tal forma que as quedara la tabla:
$ IF THEN := + id
$
5 1
1
IF
3 1
IF <expr>
1
1
THEN
<var> :=
3 1
<expr> +
4
4
4 1
id
2
2
2 2 2
La matriz completa y las subrutinas para la gramtica de ejemplo se muestran a
continuacin:

$
IF
IF <expr>
THEN
<var> :=
<expr> +
id

$
5
0
7

IF
1
0
1

THEN
0
9
0

8
4
2

0
0
0

0
4
2

:=
6
0
6

+
0
3
0

0 3 1
0 4 1
2 2 0

6:

if U <> '<var> then ERROR;


U := '';
i := i + 1;
S (i) = '<var> :=',
SIGCOMPLEX.

7:

if U<> '<estado>' then ERROR;


i := i - 1;
U :='<estado>'.

8:

9:

id
1
1
1

if U <> '<var>' and


U <> '<expr>' then ERROR;
i := i - 1;
U:= '<estado>';
if U <> '<var>' and
U <> '<expr>' then ERROR;

59

S (i) := 'IF <expr> THEN';


U := '';
SIGCOMPLEX.
0:

ERROR;
STOP.

60

61

You might also like