Você está na página 1de 103

MANUAL DE PROGRAMACIN DE SISTEMAS I

Programacin de Sistemas 1
Semestre: Sexto Nm. Horas/semana: 4 Crditos: 8 Objetivos generales: El alumno estar capacitado para disear, construir e implementar de la manera ms eficiente los analizadores lxicos y sintcticos de un compilador las caractersticas y funcionamiento de cargadores, emsambladores y macroprocesadores. Bibliografa Bsica: COMPILADORES Principios, tcnicas y herramientas Aho, Sethi & Ullman Ed. Addison-Wesley iberoamericana MODERN COMPILER IMPLEMENTATION IN C Basic techniques Appel, Andrew W. Ed. Cambridge FUNDAMENTOS DE COMPILADORES Cmo traducir al lenguaje de computadora Lemone, Karen A. Ed. CECSA COMPILADORES Conceptos fundamentales Teufel, Schmidt & Teufel Ed. Addison-Wesley iberoamericana

PLAN

DE

TRABAJO

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

1.

Datos Generales. Terica/Prctica Horas de Clase por semana: 4 Hrs. Horas de clase por semestre: 60 Hrs. Carrera en que se imparte: Ing. en Sist. Comp. Semestre: Sexto

Materia:

2.

Ubicacin de la materia. A. Ubicacin terica. Se imparte en sexto semestre; sus antecedente son las materias de Lenguajes y Autmatas y Admn. De Archivos. Materias paralelas: ninguna Materias subsecuentes: Programacin de Sistemas II Ubicacin practica. Tipo de Alumnos: diversos; algunos trabajan. Son de clase baja-media-alta, ambos sexos. Grupo: 20 alumnos por grupo promedio. Horario: matutino Recursos: saln austero en todo o con clima, Sala Audiovisual, TV, Video, PC, Proy. De acetatos.

B.

3.

Objetivos generales de aprendizaje. A. Objetivos informativos. Aplicar las estructuras bsicas de diseo de compiladores (NFAs, e.r. y C.F.G.s) Comprender el funcionamiento de traductores, ensambladores, etc. Conocer y manejar las herramientas para diseo de sw de base (Java CC). Disear una CFG para la construccin de un Lenguaje de Programacin en sus dos primeras fases (lxica y sintctica) B. Objetivos formativos.

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Intelectual. Que el alumno aprenda a preparar exposiciones profesionales y exponer sus ideas de manera clara y por escrito. Intelectual. Que el alumno aprenda a pensar, razonar, analizar, sintetizar, resumir y esquematizar. Intelectual. Que el alumno realice investigacin y a discutir lo investigado con otros. Humano. Que el alumno tenga un deseo de superacin continua, espritu de profesionalismo, calidad y excelencia. Social. Que el alumno aprenda a convivir con diferentes grupos, con un espritu de colaboracin y participacin. Profesional. Que el alumno identifique la diferencia en el perfil de un Ingeniero en Sistemas Computacionales en relacin con el resto de los usuarios de computadoras. Profesional. Que el alumno disee herramientas (software de base) para la generacin de nuevo conocimiento. 4. Metodologa de trabajo.

En este curso se planean exposiciones de temas de repaso, reforzando la investigacin con dinmicas grupales. Adems se forman equipos de trabajos para el desarrollo de proyectos de software de base (equipos no mayores de 3 integrantes) pudiendo ser estas agrupaciones al azar o a gusto de los integrantes. Se utiliza, para realzar la clase equipo audiovisual como TV, PC y Proyector de acetatos. La revisin del proyecto final se realiza en dos partes para mayor facilidad del alumno.

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

UNIDAD I INTRODUCCIN CONCEPTOS


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 Cargador. BASE: Compilador, Querys, Sistema Operativo,

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.

LENGUAJES DE PROGRAMACIN
LENGUAJE DE PROGRAMACIN: Es la notacin formal para la descripcin de algoritmos, basada en un conjunto de instrucciones en alto nivel, que finalmente pasarn a bajo nivel para interactuar con el hardware y generar herramientas de trabajo. 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.

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

EJEMPLO DE SMBOLOS QUE COMPONEN UN PROGRAMA :


SIMBOLOS ESPECUALES FUNCIONES SIMBOLOS QUE RECHAZA EL LENGUAJ E IDENTIFICADORES

ARITMETICOS LENGUAJ E PASCAL LOGICOS

+,-,*,/,MOD

AND NOT OR < > > < = = :=

DELIMITADORES OPERACIONALES RELACIONALES

ASIGNACION

PALABRAS RESERVADAS

CICLOS DECLARACION DE VARIABLES DECLARACION DE CONSTANTES

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 sntaxis de los lenguajes de mquina, lenguajes ensambladores y lenguajes de alto nivel. Lenguaje de mquina El lenguaje de mquina de una computadora consta de cadenas de nmeros binarios (ceros y unos) y es el nico que "entienden" directamente los procesadores. Todas las instrucciones preparadas en cualquier lenguaje de mquina tienen por lo menos dos partes. La primera es el comando u operacin, que dice a la computadora cul es la funcin que va a realizar. Todas las computadoras tiene un cdigo de

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

operacin para cada una de sus funciones. La segunda parte de la instruccin es el operando, que indica a la computadora donde hallar o almacenar los datos y otras instrucciones que se van a manipular; el nmero de operandos de una instruccin vara en las distintas computadoras. Lenguaje ensamblador La comunicacin en lenguaje de mquina es particular de cada procesador que se usa, y programar en este lenguaje es muy difcil y tedioso, por lo que se empez a buscar mejores medios de comunicacin con sta. A principios de la dcada de 1950, y con el fin de facilitar la labor de los programadores, se desarrollaron cdigos mnemotcnicos para las operaciones y direcciones simblicas. Uno de los primeros pasos para mejorar el proceso de preparacin de programas fue sustituir los cdigos de operacin numricos del lenguaje de mquina por smbolos alfabticos, que conforman un lenguaje mnemotcnico. Todas las computadoras actuales tienen cdigos mnemotcnicos aunque, naturalmente, los smbolos que se usan varan en las diferentes marcas y modelos. La computadora sigue utilizando el lenguaje de mquina para procesar los datos, pero los programas ensambladores traducen antes los smbolos de cdigo de operacin especificados a sus equivalentes en lenguaje de mquina. Los lenguajes ensambladores tienen ventajas sobre los lenguajes de mquina. Ahorran tiempo y requieren menos atencin a detalles . Se incurren en menos errores y los que se cometen son ms fciles de localizar. Adems, los programas en lenguaje ensamblador son ms fciles de modificar que los programas en lenguaje de mquina. Pero existen limitaciones. La codificacin en lenguaje ensamblador es todava un proceso lento. Adems, una desventaja importante de estos lenguajes es que tienen una orientacin a la mquina. Es decir, estn diseados para la marca y modelo especfico de procesador que se utiliza. En el principio de la computacin este era el lenguaje que tena que "hablar" el ser humano con la computadora y consista en insertar en un tablero miles de conexiones y alambres y encender y apagar interruptores.

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Aunque en la actualidad ya no se emplea, es importante reconocer que ya no es necesario que nos comuniquemos en este lenguaje de "unos" y "ceros", pero es el que internamente una computadora reconoce o "habla". Lenguajes de alto nivel Los primeros programas ensambladores producan slo una instruccin en lenguaje de mquina por cada instruccin del programa fuente. Para agilizar la codificacin, se desarrollaron programas ensambladores que podan producir una cantidad variable de instrucciones en lenguaje de mquina por cada instruccin del programa fuente. Dicho de otra manera, una sola macroinstruccin poda producir varias lneas de cdigo en lenguaje de mquina. El desarrollo de las tcnicas mnemotcnicas y las macroinstrucciones condujo, a su vez, al desarrollo de lenguajes de alto nivel que a menudo estn orientados hacia una clase determinada de problemas de proceso. A diferencia de los programas de ensamble, los programas en lenguaje de alto nivel se pueden utilizar con diferentes marcas de computadoras sin tener que hacer modificaciones considerables. Esto permite reducir sustancialmente el costo de la reprogramacin cuando se adquiere equipo nuevo.

Los lenguajes de programacin se dividen en 4 principales paradigmas: imperativo, funcional, orientado a objetos y lgico.
Lenguajes imperativos Son llamados as porque estn casados en comandos que actualizan variables que estn en almacenamiento. En 1950, cuando los programadores reconocieron que las variables y comandos de asignacin constituyen una simple pero til abstraccin de memoria que se actualiza. Debido a su relacin cerrada con las arquitecturas de las mquinas, los lenguajes de programacin imperativa pueden ser implementados eficientemente. La razn fundamental de la

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

programacin imperativa est relacionado a la naturaleza y propsito de la programacin. ADA C CLIPPER & XBASE ENSAMBLADOR QUICKBASIC BASIC EUPHORIA FORTRAN PASCAL Lenguajes funcionales Los lenguajes funcionales se basan en el concepto de funcin, por tanto, el objeto bsico y fundamental que manejamos son las funciones, que se pueden considerar las principales estructuras de control en este tipo de lenguajes. La base fundamental para comprender este tipo de lenguajes consiste en ver los programas y aplicaciones expresados a travs de funciones y aplicacin entre funciones. Las caractersticas fundamentales de estos lenguajes se exponen a continuacin: Utilizacin de funciones sobre elementos de primer orden. Utilizacin de funciones polimrficas, es decir, aqullas cuyo tipo devuelto depende del tipo de los argumentos. Utilizacin de funciones de orden superior, es decir, aquellas funciones que aceptan en su lista de argumentos otras funciones.

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Evaluacin perezosa (o lazy), es decir, las expresiones no se evalan hasta que no se necesitan los resultados. Es justamente, lo contrario de la evaluacin eager(ansiosa), donde la evaluacin de los argumentos se realiza antes de aplicar la funcin. La evaluacin perezosa nos proporciona la ventaja de trabajar con listas potencialmente infinitas. Existencia de un sistema de tipos fuerte Uso del Patter Matching: comprobacin de patrones. Vistas las caractersticas fundamentales de los lenguajes funcionales, estos pueden clasificarse en dos tipos: Puros: aquellos en los que slo podemos aplicar funciones. Estas son las nicas estructuras de control. Posee evaluacin perezosa. Impuros: aquellos que poseen evaluacin ansiosa. Ejemplos de lenguajes funcionales: ML CAML Haskell Sheme LISP Lamda Clculo Iswim APL FP Hope Miranda Eden Gofer Erlang Programacin Orientada a Objetos SmallTalk Programacin Orientada a la lgica PROLOG

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

LENGUAJES ESTRUCTURADOS Los lenguajes estructurados incorporan una serie de instrucciones que facilitan la construccin modular de los programas as como correccin de errores y soporte de sistemas. Esto facilita la comprensin del cdigo por cualquier otro programador o analista y hace ms fcil la tarea de probar y depurar los programas. Adems poseen una abundante variedad de instrucciones que facilitan el flujo o secuencia de los procedimientos o pasos que debe seguir el programa para la realizacin de su objetivo. ALGOL ADA C COBOL PASCAL LENGUAJES DE INTELIGENCIA ARTIFICIAL Podemos distinguir tres grandes estilos o subfamilias de los lenguajes de inteligencia artificial. Los tres estilos de programacin son los siguientes: programacin funcional, programacin relacional y programacin por objetos. El lenguaje ms representativo del estilo funcional es el LISP, LOGO por su identificacin con LSIP, cae de lleno dentro de este estilo. El lenguaje ms representativo del estilo relacional PROLOG. El lenguaje ms representativo del estilo de programacin por objetos es el SMALLTALK, pero existen varios dialectos de LISP que permite programar en esta forma.

TRADUCTORES
Los traductores son programas que permiten pasar de un programa fuente a un programa objeto. En los lenguajes de bajo nivel los programas que permiten pasar de un programa fuente a un programa objeto se llaman programas

10

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

ensambladores, mientras en los lenguajes de alto nivel estos programas se denominan compiladores e intrpretes. INTRPRETES Un intrprete es un traductor que toma un programa fuente, lo traduce a un programa objeto instruccin por instruccin, al mismo tiempo que ejecuta el programa. COMPILADORES Los Compiladores son programas que traducen los programas fuentes a programas objetos. El compilador traduce sentencia a sentencia cada una de las instrucciones del programa fuente a cdigo mquina y posteriormente ejecuta el programa.

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, que construyen la tabla de smbolos, se genera un cdigo intermedio al cual

11

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

12

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. En la etapa de optimizacin de cdigo, se busca obtener el cdigo mas corto y rpido posible, utilizando distintos algoritmos de optimizacin.

13

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Etapa de 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

14

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 tenga los operandos permitidos. = / \ id1 + / \ id2 + / \ id3 tipo_ent | 10

Generador de cdigo intermedio una representacin intermedia maquina abstracta. temp1= tipo_ent(10) temp2= id3 * temp1 temp3= id2 + tem2 id1= temp3

Esta etapa se lleva la preposicin a como un programa para una

15

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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;

16

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

char *_base; int _bufsiz; int _flag; int _file; char *_name_to_remove; } FILE; El nuevo cdigo contiene el encabezado o prototipo de la/s funcin/es 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;.

UNIDAD II ELEMENTOS DE LA PROGRAMACIN DE SISTEMAS


CARGADORES

17

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

18

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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.

19

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 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

20

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

21

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

22

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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.

23

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

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.

24

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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.

25

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

SISTEMAS OPERATIVOS
Es un programa que acta como intermedio entre el usuario y el hardware de una PC y su propsito es proporcionar un entorno en el cual el usuario pueda ejecutar sus programas. El objetivo principal de un sistema operativo es, entonces, lograr que el sistema de computacin se use de manera cmoda, y el objetivo secundario es que el hardware del computador se emplee de manera eficiente. Un sistema Operativo es parte importante de casi cualquier sistema de cmputo, el cual cuenta con y componentes bsicos: hardware, Sistemas Operativos, programas de aplicacin y los usuarios. El principal objetivo de un sistema operativo es proporcionar una interfaz entre el equipo y los programas, para esto debe administrar los recursos del sistema, de tal manera que su uso sea lo mas sencillo y eficiente. El hardware (unidad central de proceso (UCP), memoria y dispositivos de entrada y salida (E/S)) proporciona los recursos de computacin bsica bsicos. Los programas de aplicacin (compiladores, sistemas de bases de datos, juegos de vdeo y programas para negocios) definen la forma en que estos recursos se emplean para resolver los problemas de computacin de los usuarios. Puede haber distintos usuarios (personas, mquinas, otros computadores) que intentan resolver problemas diferentes; por consiguiente, es posible que haya diferentes programas de aplicacin. El sistema operativo controla y coordina el uso del hardware entre los diversos programas de aplicacin de los distintos usuarios. Los sistemas operativos son ante todo administradores de recursos; el principal recurso que administran es el hardware del computador: los procesadores, los medios de almacenamiento, los dispositivos de entrada/salida, los dispositivos de comunicacin y los datos. Los sistemas operativos realizan muchas funciones, como proporcionar la interfaz con el usuario, permitir que los usuarios compartan entre s el hardware y los datos, evitar que los usuarios

26

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

interfieran recprocamente, planificar la distribucin de los recursos, facilitar la entrada y salida, recuperarse de los errores, contabilizar el uso de los recursos, facilitar las operaciones en paralelo, organizar los datos para lograr un acceso rpido y seguro, y manejar las comunicaciones en red. No existe una definicin universal aceptada de qu forma parte de un sistema operativo y qu no. Una perspectiva sencilla considera como tal todo lo que enva un vendedor cuando se ordena la adquisicin del "sistema operativo". Sin embargo, los requisitos de memoria y las caractersticas incluidas varan en forma considerable de un sistema a otro. Algunos requieren menos de un megabyte de espacio e incluso carecen de un editor de pantalla, mientras que otros necesitan cientos de megabytes de espacio e incluyen revisores ortogrficos y sistemas de ventanas. Una definicin ms comn es que el sistema operativo es el programa que se ejecuta todo el tiempo en el computador (conocido usualmente como ncleo), siendo programas de aplicacin todos los dems. La segunda definicin es la ms comn y es la que utilizamos en general. Quiz sea ms fcil definir los sistemas operativos por lo que hacen, en vez de hacerlo por lo que son. El objetivo principal de un sistema operativo es la comodidad para el usuario. Un objetivo secundario es la utilizacin eficiente del sistema de computacin. Este propsito tiene una importancia especial en los grandes sistemas multiusuario compartidos; stos suelen ser muy costosos, por lo que es deseable hacerlos lo ms eficientes posible. Tipos de Sistemas Operativos. Una forma de clasificacin de los sistemas operativos se basa en el nmero de usuarios que el sistema puede atender al mismo tiempo. As, tenemos sistemas de una sola tarea o trabajo, los cuales pueden atender solo un trabajo (y por lo tanto un solo usuario) a la vez. Un sistema de multiprogramacin permite que se ejecuten varios trabajos al mismo tiempo. El sistema operativo se encarga de intercambiar la atencin del procesador entre los programas en ejecucin y las funciones de apoyo propias.

27

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Un sistema de multiprocesamiento difiere del sistema de multiprogramacin por el hecho de trabajar con varios procesadores a la vez. Otra forma de clasificar a los sistemas operativos toma en cuente el tipo de acceso que proporcionan al usuario. En este caso, se tienen: sistemas de procesamiento por lotes (batch processing), donde un trabajo se define como una secuencia de instrucciones de control almacenadas en algn dispositivo para que el sistema operativo pueda leer y ejecutar una serie de trabajos, limitando la intervencin del operador solo al montaje de cintas y discos. Por otra parte se tienen los sistemas de tiempo compartido (multiusuario) que proporcionan acceso interactivo o conversacional a varios usuarios, proporcionando a cada uno de ellos pequeos intervalos de tiempo de acuerdo a la cantidad de usuarios presentes y a la prioridad de cada uno de los procesos.

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. Esto lo podemos apreciar desde finales de la dcada de los 50's, cuando con el advenimiento de computadoras comerciales surge tambin la necesidad de programarlas. Se disearon lenguajes como FORTRAN y COBOL que permiten realizar esta tarea de comunicacin al establecer una relacin entre los problemas de los usuarios y lo que las mquinas eran capaces de realizar. Estos primeros lenguajes tambin vinieron acompaados de un nuevo trmino: Compilador. 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

28

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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:

29

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

30

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

UNIDAD III ANLISIS LXICO


EL ANALIZADOR LXICO

31

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

32

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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.

33

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: Si a>b 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 Entonces

34

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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).

35

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

36

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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 Pascal: Token pc-then pc-while pc-write pc-incdec op-rel par-ab par-cer ident lit-ent lit-real Lexemas ejemplo then while write to downto < > ( ) Hola, A77aH, pepe 34, 23442, 1 34.0, 23.4e-5 Descripcin del patrn (t/T)(h/H)(e/E)(n/N) while write to downto < > ( ) Letra seguida de letras y dgitos Dgito no cero seguido de dgitos Dgito no cero seguido de dgitos seguido opcionalmente de punto decimal y dgitos, seguido opcionalmente de 'E' o 'e' y dgitos

37

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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;

38

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 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

39

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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* desde es es es es una una una una expresin expresin expresin expresin regular regular regular regular que que que que denota denota denota denota a los conjuntos R S. al conjunto R. a los conjuntos RS. al conjunto R*, equivale

cero a ms repeticiones del lenguaje R. r+ es una expresin regular que denota al conjunto R+, equivale a una o ms repeticiones del lenguaje R. ri es una expresin regular que denota al conjunto Ri, a s mismo.

40

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

a)

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 ; Posicin Token Valor en memoria ; Delimitador integer P. R. Int : S. Punt. velocidad Id , Separador inicial Id Var P. R. Var

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

41

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

UNIDAD IV 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:

42

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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-Younger-Kasami 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

43

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: 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

44

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 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.

45

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 dificultad para afrontar situaciones en que el error real se produjo antes del punto de deteccin.

46

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

47

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 ms 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: 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 | | <= | |.

48

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 cero, podemos deducir de la definicin que 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 Lenguajes Gramtica Autmata Ejemplo a*

Detector Gramtica Regular deterministico no deterministico finito + Gramtica-lineal Derecha + Gramtica-lineal Izquierda + Gramtica libre de contexto +Gramtica Sensible al contexto + Gramtica norestringida Autmata pushdown no deterministico Autmata LinealVinculada Maquina de Turng

Regulares

Lenguaje libre de contexto Lenguaje sensible al contexto Lenguajes Recursivos Enumerables

ab

abc 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

49

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 1 2 3 Tipo Mquina de de

Recursivamente Mquina Enumerables Turing Sensibles contexto Libres contexto Lenguajes

al Autmata Lineal Acotado de Autmatas de Pila Autmatas

50

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Finitos y Expresiones Regulares Los cuatro tipos de gramticas. Regulares 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

51

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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. 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:

52

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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:

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

53

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: 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.

54

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

55

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

etiquetada con A. Entonces se puede expandir A utilizando la primera alternativa de A para obtener el rbol de la Fig. (b). 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

56

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 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

57

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: <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>.

58

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

59

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

60

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

61

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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$ 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$

62

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 T T F Anlisis Se analizar la cadena siguiente: id + id * id $ 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 $ F id T FT T T *FT F ( E ) E TE E +TE T FT T T + ( E TE E E ) $

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

63

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 ". 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

64

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

65

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

produccin en el orden inverso, y tendremos en la pila "$ E'" "$ E' " y la salida ser la produccin del no terminal " T' ". Paso 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Pila $E $ E' T $ E' T' F $ E' T' Id $ E' T' $ E' $ E' T + $ E' T $ E' T' F $ E' T' Id $ E' T' $ E' T' F * $ E' T' F $ E' T' Id $ E' T' $ E' $ Entrada id + id * id $ id + id * id $ id + id * id $ id + id * id $ + id * id $ + id * id $ + id * id $ id * id $ id * id $ id * id $ * id $ * id $ id $ id $ $ $ $ T E F id T *FT T FT F id T E +TE E TE T FT F id Salida

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

66

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 B d La frase "abbcde" se puede reducir a S por los siguientes pasos: abbcde aAbcde aAde aABe S 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

67

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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).

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:

68

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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]. 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.

69

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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.

70

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 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 E T F + * ( ) id = < = = < < > > > > T F + * = > = > > < < < > > ( ) = > > < < < id

Anlisis Se analizar la cadena siguiente: (x+y)

71

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Paso Pila 0 1 2 3 4 5 6 7 8 $ $( $(x $(E $(E+ $ (E+y $ (E+T $(E

Relaci R Token n < < > = < > > = ( x+y)$ x +y)$ + + y ) ) ) y)$ y)$ )$ $ $ $

$(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 Leftto-Right), la R por 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.

72

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 indica una accin del analizador, y la funcin ir_a, que indica las transiciones entre los estados. Realizacin Gramtica E E + T

73

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

E T T T * F T F F ( E ) F id Algoritmo inicializar la pila al estado cero agregar $ al final de la entrada apuntar al primer smbolo de la entrada repetir begin sea s el estado de la cima de la pila y a el smbolo de entrada actual if accin [s,a] = desplazar # 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

74

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Anlisis 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 id*(id+id) $

Acci S a n 0 id

Como [S,a] = [0,id], tenemos a S5 que es = desplazar, entonces Estado 0 1 2 3 4 5 6 7 id d5 + * Accin ( ) d4 r2 r4 d4 r6 d5 d5 r6 d4 d4 r6 r6 9 3 1 0 $ Aceptar r2 r4 8 2 3 ir_a E T F 1 2 3

d6 r2 d7 r4 r4 d5

8 d6 9 r1 10 r3 11 r5 se mete a (id) y despus a siguiente smbolo, paso 2:

d11 d7 r1 r1 r3 r3 r3 r5 r5 r5 # (5) (el nuevo estado) en la pila, avanzar al

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:

75

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: 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:

76

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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 (1) 0 (2) 0 id 5 (3) 0 F 3 (4) 0 T 2 Entrada id*(id+id)$ *(id+id)$ *(id+id)$ *(id+id)$ Accin S5 R6 R4 S7 S 0 5 3 2 a id * * *

77

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

(5) 0 T 2 * 7 (6) 0 T 2 * 7 ( 4 (7) 0 T 2 * 7 ( 4 id 5 (8) 0 T 2 * 7 ( 4 F 3 (9) 0 T 2 * 7 ( 4 T 2 (10) 0 T 2 * 7 ( 4 E 8 (11) 0 T 2 * 7 ( 4 E 8 + 6

(id+id)$ id+id)$ +id)$ +id)$ +id)$ +id)$ )$

S4 S5 R6 R4 R2 S6 S5 R6 R4 R1 S11 R5 R3 R2

7 4 5 3 2 8 6 5 3 9 8 11 10 2 1

( id + + + + id ) ) ) ) ) $ $ $

(12) 0 T 2 * 7 ( 4 E 8 + 6 id )$ 5 (13) 0 T 2 * 7 ( 4 E 8 + 6 F )$ 3 (14) 0 T 2 * 7 ( 4 E 8 + 6 T )$ 9 (15) 0 T 2 * 7 ( 4 E 8 (16) 0 T 2 * 7 ( 4 E 8 ) 11 (17) 0 T 2 * 7 F 10 (18) 0 T 2 (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> ::= <estado> ::= IF <expr> THEN <estado> ::= <var> := <expr>

78

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

<expr> <var>

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

$ 1 IF 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.

79

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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: $ 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:

80

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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=

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

81

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

<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

82

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Subrutina 2: IF U <> " " then ERROR; i: = i - 1; U = '<var>'. Aqu se hace una reduccin y la pila queda: 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:

83

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

IF <expr>+<var> THEN <var>:= <expr>+<var>+<var> $ <expr> Por lo tanto la matriz quedar: $ IF THEN : + id = 1 3 1 1 3 1 4 1 2 2 2 +<var>

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

U = ' <var> ' := '<expr>+' '<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 THEN : + id

84

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

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

5 0 7 8 4 2

1 0 1 0 0 0

0 9 0 0 4 2

= 6 0 1 0 3 1 6 0 1 0 3 1 0 4 1 2 2 0

if U <> '<var> then ERROR; U := ''; i := i + 1; S (i) = '<var> :=', SIGCOMPLEX. if U<> '<estado>' then ERROR; i := i - 1; U :='<estado>'. if U <> '<var>' and U <> '<expr>' then ERROR; i := i - 1; U:= '<estado>'; if U <> '<var>' and U <> '<expr>' then ERROR; S (i) := 'IF <expr> THEN'; U := ''; SIGCOMPLEX. ERROR; STOP.

7:

8:

9:

0:

85

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

EJEMPLO DE ANLISIS LXICO DEL LENGUAJE DTONE Este es el cdigo en Java del Analizador Lxico. Options { LOOKAHEAD = 3; IGNORE_CASE = true; STATIC = false; } PARSER_BEGIN(dtone3) import java.io.*; import java.lang.*; import java.util.*; import javax.swing.*; public class dtone3{ public FileOutputStream Sint1; public DataOutputStream Sint2; public FileOutputStream Token1; public DataOutputStream Token2; public String ar[]=new String[1024]; public void archSint_crear(String nombre_arch) { try { Sint1 = new FileOutputStream(nombre_arch); Sint2 = new DataOutputStream(Sint1); } catch (IOException Ex) { System.err.println("No se creo el archivo correctamente"); } } public void archSint_cerrar() { try { Sint1.close(); } catch (IOException Ex) { System.err.println("No se cerro corectamente"); } } public void archSint_escribe(String Mensaje) { try { Sint2.writeBytes(Mensaje+"\r"); Sint1.write('\n'); } catch(IOException Ex) { System.err.println("No se escribio correctamente"); }

86

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

} public void archtoken_crear(String nombre_arch) { try { Token1 = new FileOutputStream(nombre_arch); Token2 = new DataOutputStream(Token1); } catch (IOException Ex) { System.err.println("No se creo el archivo correctamente"); } } public void archtoken_cerrar() { try { Token1.close(); } catch (IOException Ex) { System.err.println("No se cerro corectamente"); } } public void archtoken_escribe(String Mensaje) { try { Token2.writeBytes(Mensaje+"\r"); Token1.write('\n'); } catch(IOException Ex) { System.err.println("No se escribio correctamente"); } } public static void main(String args[]) throws ParseException { dtone3 analiza; if(args.length == 0) { System.err.println("Uso del programa: \"java dtone3 archivo.ejm\""); } else { if(args.length == 1) { try { analiza = new dtone3 (new java.io.FileInputStream(args[0])); analiza.archSint_crear("Sint.txt"); analiza.dtone(); analiza.archSint_cerrar(); } catch (java.io.FileNotFoundException e)

87

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

{ System.out.println("No se pudo leer el archivo : " + args[0] + " "); } try { analiza = new dtone3 (new java.io.FileInputStream(args[0])); analiza.archtoken_crear("Lex.txt"); analiza.input(analiza); } catch (java.io.FileNotFoundException e) { System.out.println("No se pudo leer el archivo : " + args[0] + " "); } } else { System.out.println("Formato: java dtone3 nombrearchivo.ejm"); } } } void EscribeSintactico(String mensaje) { archSint_escribe(mensaje); } } PARSER_END(dtone3) SKIP : { "" | "\t" | "\n" | "\r" | "\f" } TOKEN : { <paccess: ("a")("c")("c")("e")("s")("s")> | <pbool: ("b")("o")("o")("l")> | <pbreak: ("b")("r")("e")("a")("k")> | <pbyte: ("b")("y")("t")("e")> | <pcase: ("c")("a")("s")("e")> | <pclass: ("c")("l")("a")("s")("s")> | <pcontinue: ("c")("o")("n")("t")("i")("n")("u")("e")> | <pdefault: ("d")("e")("f")("a")("u")("l")("t")> | <pdelete: ("d")("e")("l")("e")("t")("e")> | <pdo: ("d")("o")> | <pelse: ("e")("l")("s")("e")> | <pexport: ("e")("x")("p")("o")("r")("t")> | <pfalse: ("f")("a")("l")("s")("e")> | <pfor: ("f")("o")("r")> | <pif: ("i")("f")> | <pint8: ("i")("n")("t")("8")>

88

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

| | | | | | | | | | | | | | }

<pint16: ("i")("n")("t")("1")("6")> <pint32: ("i")("n")("t")("3")("2")> <pmodule: ("m")("o")("d")("u")("l")("e")> <pnew: ("n")("e")("w")> <pprivate: ("p")("r")("i")("v")("a")("t")("e")> <preturn: ("r")("e")("t")("u")("r")("n")> <pswitch: ("s")("w")("i")("t")("c")("h")> <ptoken: ("t")("o")("k")("e")("n")> <ptrue: ("t")("r")("u")("e")> <puint8: ("u")("i")("n")("t")("8")> <puint16: ("u")("i")("n")("t")("1")("6")> <puint32: ("u")("i")("n")("t")("3")("2")> <puses: ("u")("s")("e")("s")> <pwhile: ("w")("h")("i")("l")("e")>

TOKEN : { <parenizq: "("> | <parender: ")"> | <llaveizq: "{"> | <llaveder: "}"> | <corizq: "["> | <corder: "]"> | <puncoma: ";"> | <dospuntos: ":"> | <coma: ","> | <punto: "."> | <comillas: "\""> } TOKEN : { <asigna: "="> | <mayor: ">"> | <menor: "<"> | <menigual: "<="> | <mayigual: ">="> | <suma: "+"> | <resta: "-"> | <div: "/"> | <cambioizq: "<<"> | <cambioder: ">>"> | <producto: "*"> | <residuo: "%"> | <inc: "++"> | <dec: "--"> | <nobin: "~"> | <nolog: "!"> | <igual: "=="> | <dif: "!="> | <ybin: "&"> | <obin: "|"> | <xor: "~|"> | <ylog: "&&">

89

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

| <olog: "||"> | <sumasigna: "+="> | <restasigna: "-="> | <prodasigna: "*="> | <divasigna: "/="> | <resasigna: "%="> | <yasigna: "&="> | <oasigna: "|="> | <xorasigna: "~|="> | <camizqasig: "<<="> | <camderasig: ">>="> } TOKEN : { <dig: ["0"-"9"] > | <letra: ["a" - "z","A" - "Z"] > | <entero: (<dig>)+ > | <real: ("-")? <entero> (".") <entero> > | <ident: <letra> (<letra> | <dig> | "_")* > | <cadena: <comillas> (~[ "'" ])* <comillas> > | <c_noval: ("" |"^" | "" | "" | "" | "@" | "$") > | <cad_noval:(<letra> | <dig> | "_")* (<c_noval>)+ (<letra> | <dig> | "_" | <c_noval>)* > } void input(dtone3 analiza) : { String mensaje; } { ( mensaje=Checa() { System.out.println(mensaje); analiza.archtoken_escribe(mensaje); } <EOF>

)+ }

String Checa() : { Token t; } { t=<paccess> { return ( t.image +"\t\t Palabra reservada access"); } | t=<pbool> { return ( t.image +"\t\t Palabra reservada bool");} | t=<pbreak> { return ( t.image +"\t\t Palabra reservada break");} | t=<pbyte>

90

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

{ return ( t.image +"\t\t Palabra reservada byte");} | t=<pcase> { return ( t.image +"\t\t Palabra reservada case");} | t=<pclass> { return ( t.image +"\t\t Palabra reservada class");} | t=<pcontinue> { return ( t.image +"\t\t Palabra reservada continue");} | t=<pdefault> { return ( t.image +"\t\t Palabra reservada default");} | t=<pdelete> { return ( t.image +"\t\t Palabra reservada delete");} | t=<pdo> { return ( t.image +"\t\t Palabra reservada do");} | t=<pelse> { return ( t.image +"\t\t Palabra reservada else");} | t=<pexport> { return ( t.image +"\t\t Palabra reservada export");} | t=<pfalse> { return ( t.image +"\t\t Palabra reservada false");} | t=<pfor> { return ( t.image +"\t\t Palabra reservada for");} | t=<pif> { return ( t.image +"\t\t Palabra reservada if");} | t=<pint8> { return ( t.image +"\t\t Palabra reservada int8");} | t=<pint16> { return ( t.image +"\t\t Palabra reservada int16");} | t=<pint32> { return ( t.image +"\t\t Palabra reservada int32");} | t=<pmodule> { return ( t.image +"\t\t Palabra reservada module");} | t=<pnew> { return ( t.image +"\t\t Palabra reservada new");} | t=<pprivate> { return ( t.image +"\t\t Palabra reservada private");} | t=<preturn> { return ( t.image +"\t\t Palabra reservada return");}

91

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

| t=<pswitch> { return ( t.image +"\t\t Palabra reservada switch");} | t=<ptoken> { return ( t.image +"\t\t Palabra reservada token");} | t=<ptrue> { return ( t.image +"\t\t Palabra reservada true");} | t=<puint8> { return ( t.image +"\t\t Palabra reservada uint8");} | t=<puint16> { return ( t.image +"\t\t Palabra reservada uint16");} | t=<puint32> { return ( t.image +"\t\t Palabra reservada uint32");} | t=<puses> { return ( t.image +"\t\t Palabra reservada uses");} | t=<pwhile> { return ( t.image +"\t\t Palabra reservada while");} | t=<puncoma> { return ( t.image +"\t\t Simbolo ;");} | t=<dospuntos> { return ( t.image +"\t\t Simbolo :");} | t=<coma> { return ( t.image +"\t\t Simbolo ,");} | t=<punto> { return ( t.image +"\t\t Simbolo .");} | t=<parenizq> { return ( t.image +"\t\t Operador (");} | t=<parender> { return ( t.image +"\t\t Operador )");} | t=<corizq> { return ( t.image +"\t\t Operador [");} | t=<corder> { return ( t.image +"\t\t Operador ]");} | t=<llaveizq> { return ( t.image +"\t\t Operador {");} | t=<llaveder> { return ( t.image +"\t\t Operador }");} | t=<asigna> { return ( t.image +"\t\t Operador = ");}

92

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

| t=<mayor> { return ( t.image +"\t\t Operador > ");} | t=<menor> { return ( t.image +"\t\t Operador < ");} | t=<menigual> { return ( t.image +"\t\t Operador <= ");} | t=<mayigual> { return ( t.image +"\t\t Operador >= ");} | t=<suma> { return ( t.image +"\t\t Operador + ");} | t=<resta> { return ( t.image +"\t\t Operador - ");} | t=<div> { return ( t.image +"\t\t Operador / ");} | t=<producto> { return ( t.image +"\t\t Operador * ");} | t=<residuo> { return ( t.image +"\t\t Operador % ");} | t=<cambioizq> { return ( t.image +"\t\t Operador << ");} | t=<cambioder> { return ( t.image +"\t\t Operador >> ");} | t=<inc> { return ( t.image +"\t\t Operador ++ ");} | t=<dec> { return ( t.image +"\t\t Operador -- ");} | t=<nobin> { return ( t.image +"\t\t Operador ~ ");} | t=<nolog> { return ( t.image +"\t\t Operador ! ");} | t=<igual> { return ( t.image +"\t\t Operador == ");} | t=<dif> { return ( t.image +"\t\t Operador != ");} | t=<ybin> { return ( t.image +"\t\t Operador binario & ");} | t=<obin>

93

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

{ return ( t.image +"\t\t Operador binario | ");} | t=<xor> { return ( t.image +"\t\t Operador binario ~| ");} | t=<ylog> { return ( t.image +"\t\t Operador logico && ");} | t=<olog> { return ( t.image +"\t\t Operador logico || ");} | t=<sumasigna> { return ( t.image +"\t\t Operador asignacion += ");} | t=<restasigna> { return ( t.image +"\t\t Operador asignacion -= ");} | t=<prodasigna> { return ( t.image +"\t\t Operador asignacion *= ");} | t=<divasigna> { return ( t.image +"\t\t Operador asignacion /= ");} | t=<resasigna> { return ( t.image +"\t\t Operador asignacion %= ");} | t=<yasigna> { return ( t.image +"\t\t Operador asignacion &= ");} | t=<oasigna> { return ( t.image +"\t\t Operador asignacion |= ");} | t=<xorasigna> { return ( t.image +"\t\t Operador asignacion ~|= ");} | t=<camizqasig> { return ( t.image +"\t\t Operador asignacion <<= ");} | t=<camderasig> { return ( t.image +"\t\t Operador asignacion >>= ");} | t=<dig> { return ( t.image +"\t\t Digito ");} | t=<ident> { return ( t.image +"\t\t Identificador ");} | t=<letra> { return ( t.image +"\t\t Letra ");} | t=<entero> { return ( t.image +"\t\t Numero Entero ");} | t=<real> { return ( t.image +"\t\t Numero real ");}

94

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

| t=<c_noval> { return ( t.image +"\t\t Caracter no valido ");} | t=<cad_noval> { return ( t.image +"\t\t Cadena no valida ");} } EJEMPLO DE ANALISIS SINTCTICO DEL LENGUAJE DTONE Este es el cdigo en Java del Analizador Sintctico. Se describen las gramticas y se da una breve descripcin de cada una de ellas. Esta gramtica corresponde a la estructura general de todo el programa. void dtone() : {} { try{ CABECERA() CUERPO() } catch(ParseException e) {System.out.println("Error en el programa"); } } Esta es la gramtica que corresponde a la cabecera del programa. ste tiene que ser el primer comando en todos los archivos. Identifica el archivo como cdigo del dtone. void CABECERA() : {} {try {VERSION() LIBRERIAS() } catch(ParseException e) { System.out.println("Error en la cabecera"); } } Esta es la gramtica que corresponde a la versin que va en la cabecera. La versin es muy til para identificar la versin del compilador que este cdigo necesita. void VERSION() : {} {try {<pdtone> <dig> <punto> <dig> <punto> <dig> } catch(ParseException e) { System.out.println("Error en la version"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } }

95

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Esta es la gramtica que corresponde a las libreras, lo que se hace es que se listan las libreras que van a ser llamadas para la ejecucin del programa. void LIBRERIAS() : {} {try {(<puses> <comillas> <ident>("/" <ident>)* "/*" <comillas> <puncoma>)+ } catch(ParseException e) { System.out.println("Error en las librerias"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica en la cual se define el cuerpo del programa, en el se van a listar las instrucciones para del programa. void CUERPO() : {} {try {<pmodule> <ident> <llaveizq> DECLARA() (INSTRUC())+ <llaveder> } catch(ParseException e) { System.out.println("Error en el cuerpo"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica para las declaraciones de variables que se van a utilizar en el programa. void DECLARA() : {} {try {(D_VAR() | D_ARR() | D_CONST() | D_FUNCION() )* } catch(ParseException e) { System.out.println("Error en las declaraciones"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica de la declaracin de variables. void D_VAR() : {} {try {(DEC_VAR() | DECINI_VAR()) <puncoma> } catch(ParseException e) {

96

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

System.out.println("Error en las declaracion de variable"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica de la declaracin de variables. void DEC_VAR() : {} {try {TIPO() <ident> } catch(ParseException e) { System.out.println("Error en las declaracion de variable"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corrsponde al tipo de datos con el cual se va a declarar la variable. void TIPO() : {} { (<pint8> | <pint16> | <pint32> | <puint8> | <puint16> | <puint32> | <pbool> | <pbyte>) } Esta gramtica corresponde a la declaracin e inicializacin de variables. void DECINI_VAR() : {} {try {DEC_VAR() <igual> (<entero> | <real> | <cadena>) <puncoma> } catch(ParseException e) { System.out.println("Error en las declaracion de variable"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde a la declaracin de un arreglo. void D_ARR() : {} {try {TIPO() <ident> <corizq> (<entero>)* <corder> <puncoma> } catch(ParseException e) { System.out.println("Error en las declaracion de arreglo");

97

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde a la declaracin de una constante. void D_CONST() : {} {try {<pdefine> <ident> <igual> (<entero>|<real>|<cadena>) <puncoma> } catch(ParseException e) { System.out.println("Error en las declaracion de constante"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde a la declaracin de una funcin. void D_FUNCION() : {} {try {TIPO() <ident> <parenizq> PARAM() <parender> <llaveizq> DECLARA() (INSTRUC())+ < llaveder > } catch(ParseException e) { System.out.println("Error en la declaracion de la funcion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde a la declaracin de parmetros del programa. void PARAM() : {} {try {(DEC_VAR() | D_ARR()) (<coma> (DEC_VAR() | D_ARR() ) )* } catch(ParseException e) { System.out.println("Error en los parametros"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } }

98

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Esta gramtica define las instrucciones que sern dadas para que el programa finalmente cumpla con las ordenes que se le estn dando a travs de dichas instrucciones. void INSTRUC() : {} {try {(ASIGNACION() | CICLO() | LLAM_FUNCION()) } catch(ParseException e) { System.out.println("Error en la instruccion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica que define las asignaciones que podemos hacer en el lenguaje de programacin Dtone. void ASIGNACION() : {} {try {IZQ() <asigna> DER() <puncoma> } catch(ParseException e) { System.out.println("Error en la asignacion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica que define la parte izquierda de las asignaciones que podemos hacer en el lenguaje de programacin Dtone. void IZQ() : {} {try {(<ident> | ARREGLO()) } catch(ParseException e) { System.out.println("Error en la parte izquierda de la asginacion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica define al arreglo que puede ir en la parte izquierda de la asignacin, es decir al arreglo se le va a asignar un valor. void ARREGLO() : {} {try {<ident> <corizq> (<ident>|<entero>) (<coma> (<ident>|<entero>))* <corder>

99

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

} catch(ParseException e) { System.out.println("Error en el arreglo"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica que define la parte derecha de las asignaciones que podemos hacer en el lenguaje de programacin Dtone. void DER() : {} {try {(IZQ() | <cadena> | OPER_ARIT() | <entero> | <real>) } catch(ParseException e) { System.out.println("Error en la parte derecha de la asignacion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde a los operadores aritmticos que pueden ir en la parte derecha de una asignacin. void OPER_ARIT() : {} {try {(<ident> | <entero> | <real> | ARREGLO()) ARITOP() (<ident> | <entero> | <real> | ARREGLO()) } catch(ParseException e) { System.out.println("Error en la operacion"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica define el simbolo del operador aritmtico. void ARITOP() : {} { (<suma> | <resta> | <div> | <producto> | <residuo>) } Esta gramtica define los ciclos que puede contener el cuerpo del programa en el lenguaje Dtone. void CICLO() : {}

100

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

{ (GIF() | GWHILE() | GDO() | GFOR() | GCASE()) }

Esta es la gramtica del IF. Se evala la condicin, si produce una verdad, la verdadera trayectoria se ejecuta, si no la falsa trayectoria (opcional) se ejecuta. void GIF() : {} {try {<pif> <parenizq> OPER_REL() <parender> (INSTRUC())+ } catch(ParseException e) { System.out.println("Error en el IF"); } } Esta es la gramtica de los operadores relacionales que pueden ir dentro de alguna instruccin de control de flujo. void OPER_REL() : {} {try {(<ident> | <entero> | <real> | ARREGLO()) RELOP() (<ident> | <entero> | <real> | ARREGLO()) } catch(ParseException e) { System.out.println("Error en la operacion"); } } Esta es la gramtica de los smbolos de los operadores relacionales que pueden ir dentro de alguna instruccin de control de flujo. void RELOP() : {} { (<mayor> | <menor> | <menigual> | <mayigual> | <igual>) } Esta es la gramtica del ciclo WHILE. En este ciclo se ejecuta el cuerpo si la condicin es verdadera, en caso contrario no. void GWHILE() : {} {try {<pwhile> <parenizq> OPER_REL() <parender> <llaveizq> (INSTRUC())+ <llaveder> } catch(ParseException e) { System.out.println("Error en el WHILE"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } }

101

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

Esta es la gramtica del ciclo DO. En este ciclo, el cuerpo es ejecutado mientras que la condicin sea cierta. El cuerpo del ciclo se ejecuta por lo menos una vez. void GDO() : {} {try {<pdo> <llaveizq> (INSTRUC())+ <llaveder> <pwhile> <parenizq> OPER_REL() <parender> <puncoma> } catch(ParseException e) { System.out.println("Error en el DO"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta es la gramtica del ciclo FOR. El cual tiene una estructura muy parecida a la de C. void GFOR() : {} {try {<pfor> <parenizq> (DECINI_VAR() | ASIGNACION()) <puncoma> OPER_REL() <puncoma> ASIGNACION() <parender> <llaveizq> (INSTRUC())+ <llaveder> } catch(ParseException e) { System.out.println("Error en el FOR"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } Esta gramtica corresponde al case. Esta estructura no requiere declaraciones de ruptura. void GCASE() : {} {try {<pswitch> <parenizq> (INSTRUC())+ <parender> <llaveizq> (<pcase> <entero> <dospuntos> (INSTRUC()) +)+ (<pdefault> <dospuntos> (INSTRUC())+)? <llaveder> } catch(ParseException e) { System.out.println("Error en el CASE"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } } La siguiente gramtica describe la llamada a una funcin en Dtone. void LLAM_FUNCION() : {} {try

102

LIC. MARTHA MARTINEZ MORENO

MANUAL DE PROGRAMACIN DE SISTEMAS I

{<ident> <parenizq> (<ident> | <entero> | <cadena> | <real>)* <parender> <puncoma> } catch(ParseException e) { System.out.println("Error en la llamada"); Token t; do{ t = getNextToken();} while(t.kind != puncoma & t.kind != EOF); } }

103

LIC. MARTHA MARTINEZ MORENO

Você também pode gostar