TECNOLÓGICO NACIONAL DE MÉXICO INSTITUTO TECNOLOGICO DE ACAPULCO ACAPULCO
“Educación Tecnológica con compromiso social”
Ingeniería En Sistemas Computaiona!es Carrera Lengua"es # aut$matas II Asignatura Actividades de aprendizaje Unidad 1. Análisis semántico Competencia especíica a desarrollar !eporte de la manipulación de la ta"la de conversión de sím"olos # de direcciones $roesor% &ilvestre 'edolla &olano. (ntegrantes del e)uipo * Alumnos% +imenez ,onzalez Alam Emmanuel 2idalgo &ánc3ez Teresita 'e 'erenice Aranci"ia ,arcía 5ngel Andr6s Andr6s +imenez 7eal 8iguel Angel
1-/-0* 11/-144 1-/-01 1-/-09
Acapulco: ,uerrero: -/ de diciem"re del /-14
Conteni&o (ntroducción..........................................................................................................2 0
(;T!<=UCC(>;...................................................................................................3 =E&A!!<77<......................................................................................................3 T($<& =E E!!; A ;(BE7 =E !A&E ...............................................................7 !E,7A& =E $!<=UCC(>; A=(C(<;A7E& A=(C(<;A7E& $A!A E7 C<;T!<7 =E E!!; ,7<'A7..................................................................................8 T!ATA8(E;T< E!!; =E T($<&............................................................................8 A&$ECT<& ,E;E!A7E&................................................................................8 E&$EC((CAC(>; =E U; C<8$!<'A=; =E E!!
9
8anipular la ta"la de conversión de sím"olos # de direcciones. ..................................22 C<;C7U&(>;%....................................................................................................29 ......................................................... ........................................ ................................................. ............................. 30 'i"liograía.....................................
Intro&ui$n El proceso de la compilación se desglosa en dos partes% la parte )ue depende solo del lenguaje uente @etapa inicial o rontend # la parte )ue depende solo del lenguaje o"jeto @etapa inal o "acFend. 1
7a etapa inicial traduce un programa uente a una representación intermedia s partir de la cual la etapa inal genera el código o"jeto. =e esta orma: los detalles )ue tienen )ue ver con las características del lenguaje o"jeto @código ensam"lador: código ma)uina a"soluto o relocaliza"le:...: la ar)uitectura de la ma)uina @nGmero de registros: modos de direccionamiento: tamaHo de los tipos de datos: memoria cac3e:...: el entorno de ejecución @estructura de registros # memoria de la má)uina donde se va a ejecutar el programa... # el sistema operativo se englo"an en la etapa inal # se aíslan del resto. El código intermedio es un código a"stracto independiente de la má)uina para la )ue se generará el código o"jeto. El código intermedio 3a de cumplir dos re)uisitos importantes% ser ácil de producir a partir del análisis sintáctico: # ser ácil de traducir al lenguaje o"jeto. Con una representación intermedia "ien deinida: un compilador para el lenguaje i # la ma)uina j puede ser construido com"inando el rontend para el lenguaje i con el "acFend de la ma)uina j. =e esta manera se pueden construir mIn compiladores escri"iendo Gnicamente m rontends # n "acFende.
'()*eporte &e !a &etei$n # reuperai$n &e errores sem+ntios INT*ODUCCIÓN 7os errores encontrados en las distintas ases de análisis se envían a un módulo denominado manejo de errores. En el caso más sencillo puede ser un su"programa al )ue se le invoca enviándole el código de error: # )ue se encarga de escri"ir un mensaje con el error correspondiente: # el nGmero de línea donde se 3a producido: así como de cortar el proceso de traducción. &i se desea construir un tratamiento de errores más completo: por ejemplo detectando todos los errores del programa uente: el módulo se complica dado )ue los analizadores de"en proseguir su tra"ajo con alta de datos. <"jetivos • • •
(normar con claridad: eJactitud !ecuperación rápida recuperación no es corrección 2
• •
;o de"e retrasar el procesamiento de programas sin errores ;o generar errores en cascada @ej. eliminar identiicador
Acciones posi"les • • • •
=etectar errores (normar de los errores !ecuperar de los errores Corregir errores
DESA**OLLO A continuación se muestra un ragmento de código de un m6todo de la clase Errores escrito en CKK: para el tratamiento de errores sintácticos. En el caso )ue se presenta cada vez )ue se encuentra un error el compilador se detiene: # inaliza el proceso.
Una de las unciones más importantes de un compilador es su respuesta a los errores en un programa uente. 7os errores pueden ser detectados durante casi cual)uier ase de la compilación. Estos errores estáticos @o de tiempo de compilación de"en ser notiicados por un compilador: # es importante )ue el compilador sea capaz de generar mensajes de error signiicativos # reanudar la compilación despu6s de cada error. Cada ase de un compilador necesitará una clase ligeramente dierente de manejo de errores. D: por lo tanto: un manejador de errores de"e contener operaciones dierentes: cada una apropiada para una ase # situación especíica. Es recomenda"le estudiar las t6cnicas de manejo de errores por cada ase. Una deinición de lenguaje por lo general re)uerirá no solamente )ue los errores estáticos sean detectados por un compilador: sino tam"i6n ciertos errores de ejecución. Esto re)uiere )ue un compilador genere código eJtra: el cual realizará prue"as de ejecución apropiadas para garantizar )ue todos esos 3
errores provocarán un evento apropiado durante la ejecución. El más simple de tales eventos será detener la ejecución del programa. &in em"argo: a menudo esto no es adecuado: # una deinición de lenguaje puede re)uerir la presencia de mecanismos para el manejo de eJcepciones. Lstos pueden complicar sustancialmente la administración de un sistema de ejecución: especialmente si un programa puede continuar ejecutándose desde el punto donde ocurrió el error.
Ejemplo BA! c3 % C2A!M @I Un identiicador no se puede utilizar si I ent% (;TE,E!M @I previamente no se 3a deinido. I ... c3 %N ent K 1M @I En $ascal no es válido: en C sí. I • • •
Análisis l6Jicos% =evuelve la secuencia de toFens% id asig id suma nGmero ptocoma Análisis &intáctico%
TIPOS DE E**O*ES Tipos de errores )ue suelen ocurrir @dependiendo de la ase% 76Jicos% ;o concuerda con ninguna E!. Ejemplo% escri"ir mal una pala"ra &intácticos% 7a estructura )ue se 3a seguido no es correcta. Ejemplo% eJpresión con par6ntesis no emparejados. &emánticos% 7a estructura está "ien pero 3a# errores de signiicado Ejemplo% operador # operando incompati"les. 7ógicos% 7os comete el programador Ejemplo% una llamada ininitamente recursiva •
•
•
•
4
Algunos errores se pueden detectar en compilación otros solo en ejecución. El tratamiento de errores es una parte importante )ue se suele descuidar.
T*ATAMIENTO DE LOS E**O*ES LEXICOS Un traductor de"e adoptar alguna estrategia para detectar: inormar # recuperarse para seguir analizando 3asta el inal. 7as respuestas ante el error pueden ser% (nacepta"les% $rovocadas por allos del traductor: entrada en lazos ininitos: producir resultados erróneos: # detectar sólo el primer error # detenerse. Acepta"les% Evitarla avalanc3a de errores @mala recuperación #: aun)ue más complejo: inormar # reparar el error de orma automática. 7a conducta de un Analizador de 76Jico es el de un Autómata inito o “scanner”. =etección del error% El analizador de 76Jico detecta un error cuando no eJiste transición desde el estado )ue se encuentra con el sím"olo de la entrada. El sím"olo en la entrada no es el esperado. •
•
•
7os errores l6Jicos se detectan cuando el analizador l6Jico intenta reconocer componentes l6Jicos # la cadena de caracteres de la entrada no encaja con ningGn patrón. &on situaciones en las )ue usa un carácter invalido @O:P:Q:R:...: )ue no pertenece al voca"ulario del lenguaje de programación: al escri"ir mal un identiicador: pala"ra reservada u operador. Errores l6Jicos típicos son% ;om"re ilegales de identiicadores% un nom"re contiene caracteres inválidos. ;Gmeros incorrectos% Un numero contiene caracteres inválidos o no está ormado correctamente: por ejemplo :1S en vez de .1S o -..1S. Errores de ortograía en pala"ras reservadas% caracteres omitidos: adicionales o cam"iados de sitio: por ejemplo la pala"ra 3ile en vez de 3ile. in de arc3ivo% se detecta un in de arc3ivo a la mitad de un componente l6Jico. • •
•
•
7os errores l6Jicos se de"en a descuidos del programador. En general: la recuperación de errores l6Jicos es sencilla # siempre se traduce en la generación de un error de sintaJis )ue será detectado más tarde por el analizador sintáctico cuando el analizador l6Jico devuelve un componente l6Jico )ue el analizador sintáctico no espera en esa posición. 7os m6todos de recuperación de errores l6Jicos se "asan "ien en saltarse caracteres en la entrada 3asta )ue un patrón se 3a podido reconocerM o "ien usar otros m6todos más soisticados )ue inclu#en la inserción: "orrado: sustitución de un carácter en la entrada o intercam"io de dos caracteres consecutivos. Una "uena estrategia para la recuperación de errores l6Jicos% Universidad ;acional del &anta Curso% Teoría de Compiladores &i en el momento de detectar el error #a 3emos pasado por algGn estado inal ejecutamos la acción correspondiente al Gltimo estado inal visitado con el leJema ormado 3asta )ue salimos de 6lM el resto de caracteres leídos se devuelven al lujo de entrada # se vuelve al estado inicialM •
&i no 3emos pasado por ningGn estado inal: advertimos )ue el carácter encontrado no se espera"a: lo eliminamos # proseguimos con el análisis. T*ATAMIENTO DE LOS E**O*ES SINTACTICOS •
5
T*ATAMIENTO DE E**O*ES SINT,CTICOS 8uc3os errores de naturaleza sintáctica !ecuperación% Al producirse un error el compilador de"e ser capaz de inormar del error # seguir compilando. @(deal El manejo de errores de sintaJis es el más complicado desde el punto de vista de la creación de compiladores. ;os interesa )ue cuando el compilador encuentre un error: se recupere # siga "uscando errores. $or lo tanto el manejador de errores de un analizador sintáctico de"e tener como o"jetivos% • • •
(ndicar los errores de orma clara # precisa. Aclarar el tipo de error # su localización. !ecuperarse del error: para poder seguir eJaminando la entrada. ;o ralentizar signiicativamente la compilación.
Un "uen compilador de"e 3acerse siempre teniendo tam"i6n en mente los errores )ue se pueden producirM con ello se consigue% • •
&impliicar la estructura del compilador. 8ejorar la respuesta ante los errores.
Tenemos varias estrategias para corregir errores: una vez detectados% (,;; A ;(BE7 =E !A&E (ntenta recuperar el error una vez descu"ierto. En el caso anterior: por ejemplo: podría 3a"er sido lo suicientemente inteligente como para insertar el toFen MV. 2a# )ue tener cuidado con este m6todo: pues puede dar lugar a recuperaciones ininitas. !E,7A& =E $!<=UCC(>; A=(C(<;A7E& $A!A E7 C<;T!<7 =E E!!; ,7<'A7 =ada una secuencia completa de toFens a ser reconocida: si 3a# algGn error por el )ue no se puede reconocer: consiste en encontrar la secuencia completa más
6
$arecida )ue sí se pueda reconocer. Es decir: el analizador sintáctico le pide toda la secuencia de toFens al l6Jico: # lo )ue 3ace es devolver lo más parecido a la cadena de entrada pero sin errores: así como el ár"ol )ue lo reconoce.
T*ATAMIENTO E**O*ES SEM,NTICOS C<8$!<'AC(>; =E T($<& A&$ECT<& ,E;E!A7E& Un lenguaje con compro"ación uerte de tipos es capaz de garantizar )ue los programas se pueden ejecutar sin errores de tipo: por lo )ue los errores de tipo se detectarán siempre en tiempo de compilación. Como mínimo: ante un error: un compro"ador de tipos de"e inormar de la naturaleza # posición del error # recuperarse para continuar con la compro"ación del resto del programa a analizar. Beamos algunas de las operaciones a tener en cuenta en una compro"ación de tipos% Conversión de tipos% A veces es necesario transormar el tipo de una eJpresión para utilizar correctamente un operador o para pasar de orma adecuada un parámetro a una unción. Coerción% Es una conversión de tipos )ue realiza de orma implícita el propio compilador. &i es el programador el )ue realiza la conversión se tratará entonces de una conversión eJplícita. &o"recarga de operadores% 7a so"recarga se resuelve determinando el tipo de cada una de las eJpresiones intervinientes en la so"recarga. unciones polimóricas% &on a)uellas )ue tra"ajan con argumentos cu#o tipo puede cam"iaren distintas llamadas a la unción. •
•
•
•
E&$EC((CAC(>; =E U; C<8$!<'A=; =E E!!
Compro"aciones de tipos% operadores aplicados a operados incompati"les: asignación de tipos incompati"les: llamadas a unciones con tipos no adecuados: etc. Compro"aciones de lujo de control% las sentencias )ue 3acen )ue el lujo de control a"andone una construcción de"e tener algGn lugar a donde transmitir el control. $or ejemplo% Un"reaF de"e estar dentro de una proposición 3ile: or o sitc3 en C. Compro"aciones de unicidad% situaciones en las )ue solo se puede deinir un o"jeto una vez eJactamente. $or ejemplo% Un identiicador: las eti)uetas case den tro de un sitc3. 7
&olo nos 3emos centrado en las compro"aciones de tipo. 7as otras son cierto modo rutinarias # se pueden realizar ácilmente insertando acciones intercaladas en el código para realizarlas: por eje. Cuando se introduce un identiicador en la Ta"la de &ím"olos.
8
e$presion returns %&trin' tpe( ) *+E,- root.sm!ol &m!olsmta!le%*+E,-.te$t( t -()Cua&ro sin$ptio &on&e se &esri.e e! mane"o &e tipos eninst=asi' !as e/presiones # e! uso &e ) literal tpeliteral.tpe opera&ores >init entos contenidos en instrucciones de nuestro len'ua;e tam!i
a /orma que el de los identifcadores a que el mecanismo que #emos utiliado para re'istrar su tipo durante
Llamadas a función Externa
e$presion returns %&trin' tpe( ) *+E,- i/smta!le.ontainse*+E,-.te$t root.sm!ol &m!olsmta!le%*+E,-.te$t( tpero
0()Lista &e !as reg!as para !a on1ersi$n &e tipos 2asting3 en e/presiones on tres e"emp!os por a&a reg!a
9 cillo aún que en el caso de los literales a que nos !asaremos directamente en el tipo almacenado en la ta!la
Una declaración de operador de conversión introduce una conversión deinida por el usuario )ue aumenta las conversiones implícitas # eJplícitas predeinidas. Una declaración de operador de conversión )ue inclu#e la pala"ra clave implicit deine una conversión implícita deinida por el usuario. 7as conversiones implícitas pueden ocurrir en distintas situaciones: inclu#endo las invocaciones de miem"ros de unción: las eJpresiones de conversión # las asignaciones.
Una declaración de operador de conversión )ue inclu#e la pala"ra clave eJplicit deine una conversión eJplícita deinida por el usuario. 7as conversiones eJplícitas pueden ocurrir en las eJpresiones de conversión.
Un operador de conversión convierte de un tipo origen: indicado por el tipo del parámetro del operador de conversión: a un tipo destino: indicado por el tipo del valor devuelto del operador de conversión. Una clase o estructura puede declarar una conversión de un tipo origen & a un tipo destino T si se cumple Identicadores todo lo siguiente% Z
& # T son tipos dierentes
Z
& o T es el tipo de clase o estructura en el )ue tiene lugar la declaración del operador.
Z
;i & ni T son de tipo o"ject ni un tipodeinteraz.
Z
T no es una clase "ase de &: # & tampoco lo es de T.
=e la segunda regla se deriva )ue un operador de conversión de"e convertir a o del tipo de la clase o estructura en la )ue se declara el operador. $or ejemplo: es posi"le )ue un tipo de clase o de estructura C deina una conversión de C a int # de int a C: pero no de int a "ool. ;o es posi"le volver a deinir una conversión predeinida. $or lo tanto: no está permitido utilizar operadores de conversión para convertir de o a o"ject por)ue #a eJisten conversiones implícitas # eJplícitas entre o"ject # el resto de tipos. Además: ni el tipo de origen ni el de destino de una conversión puede ser un tipo "ase del otro: por)ue entonces #a eJistiría una conversión. 7as conversiones deinidas por el usuario no pueden convertir de o a tiposdeinteraz. Esta restricción impide: en particular: )ue se produzcan transormaciones deinidas por el usuario cuando se convierte a un tipodeinteraz: # asegura )ue una conversión a un tipodeinteraz se ejecute correctamente sólo si el o"jeto )ue se está convirtiendo implementa realmente el tipodeinteraz especiicado. 7a irma de un operador de conversión está ormado por el tipo de origen # el tipo de destino @6sta es la Gnica orma de miem"ro en la )ue el tipo de valor devuelto participa en la irma. 7a clasiicación implicit o eJplicit de un operador de conversión no orma parte de la irma del operador. $or lo tanto: una clase o una estructura no puede declarar a la vez operadores de conversión implicit # eJplicit con los mismos tipos de origen # destino.
10
e$presion returns %&trin' tpe( ) literal tpeliteral.tpe l iteral returns %&trin' HHHtpe( >init tpeII
En general: las conversiones implícitas deinidas por el usuario de"en diseHarse para )ue nunca produzcan eJcepciones ni pierdan inormación. &i una conversión deinida por el usuario puede dar lugar a eJcepciones @por ejemplo: de"ido a )ue el argumento de origen está uera del intervalo o a p6rdida de inormación @como descartar los "its de ma#or orden: dic3a conversión de"ería deinirse como eJplícita. En el ejemplo
usingstemM pu"licstruct =igit [ "#te valueM pu"lic =igit@"#te value [ i @value \ - ]] value R 0 t3ro ne ArgumentEJception@M t3is.value N valueM ^ pu"lic static implicit operator "#te@=igit d [ returnd.valueM ^ pu"lic static eJplicit operator =igit@"#te " [ return ne =igit@"M ^ mo consultar el tipo de to@en deAuelto por el analiador sintáctico asi'nar directamente un tipo u otro en la ^
11 Literales
7a conversión de =igit a "#te es implícita por)ue nunca produce eJcepciones o pierde inormación: pero la conversión de "#te a =igites eJplícita #a )ue =igit sólo puede representar un su"conjunto de los posi"les valores de un "#te. Conversiones implícitas 7a ma#oría de las conversiones: como la asignación de un valor a una varia"le: se producen automáticamente. El tipo de datos de la varia"le determina el tipo de datos de destino de la conversión de eJpresión. En el ejemplo siguiente se muestra una conversión de datos implícita entre un valor int: un valor &tring # un valor dou"le. vari % intM var d % dou"leM var s % &tringM i N 4M s N iM __ `idening% t3e int value 4 coverted to t3e &tring Q4Q. d N iM __ `idening% t3e int value 4 coverted to t3e dou"le 4. s N dM __ `idening% t3e dou"le value 4 coverted to t3e &tring Q4Q. i N dM __ ;arroing% t3e dou"le value 4 coverted to t3e int 4.
. n 8 i N sM __ ;arroing% t3e &tring value iQ4Q coverted to t3e int 4. s e r pQ4Q coverted to t3e dou"le 4. d N sM __ ;arroing% t3e &tring value $ e a n u e Cuando se compila este código: d pueden aparecer advertencias en tiempo de compilación s de )ue las conversiones de restricción o pueden producir errores o ser mu# lentas. p i t
para inormar
$uede ocurrir )ue las conversiones e de restricción implícitas no uncionen si la conversión re)uiere una d p6rdida de inormación. $or ejemplo: o las siguientes líneas no uncionarán% var i % intM . l var % loatM o
! r ás % &tringM var l e d N o .1SM d o i N n M __ !untime u s s N aQappleQM e t s < á r a n ' i s
e u q e # c o l u c l á c l E
error. T3e num"er .1S cannot "e represented it3 an int.
12
n 8 i s i N e sM __ !untime error. T3e string QappleQ cannot "e converted to an int. r p $ e a n u e d o uizás te 3a#as preguntado )u6 pasa cuando escri"imos eJpresiones num6ricas p i t operandos son del mismo tipo. $or ejemplo% s l E
en las )ue no todos los
e r oc3ar nM d a r int a: ": c: dM e p oloat r: s: tM e d... o s ua N 1-M l e " N 1--M s er N 1---M n o i sc N a K "M e r ps N r K aM $ e sd N r K "M a l nd N n K a K rM e st N r K a s K cM o p i t
...
e d oEn estos casos: cuando los operandos de cada operación "inaria asociados a un operador son de distinto ; etipo: el compilador los convierte a un tipo comGn. EJisten reglas )ue rigen estas conversiones: # aun)ue npueden cam"iar ligeramente de un compilador a otro: en general serán más o menos así% a J
1. Cual)uier tipo entero pe)ueHo como c3ar o s3ort es convertido a int o unsignedint. En este punto cual)uier pareja de operandos será int @con o sin signo: long: longlong:dou"le: loat o longdou"le. /.
&i un operando es de tipo longdou"le: el otro se convertirá a longdou"le.
.
&i un operando es de tipo dou"le: el otro se convertirá a dou"le.
S.
&i un operando es de tipo loat: el otro se convertirá a loat.
4.
&i un operando es de tipo unsignedlonglong: el otro se convertirá a unsignedlonglong.
9.
&i un operando es de tipo longlong: el otro se convertirá a longlong.
*.
&i un operando es de tipo unsignedlong: el otro se convertirá a unsignedlong. 13
.
&i un operando es de tipo long: el otro se convertirá a long.
0.
&i un operando es de tipo unsignedint: el otro se convertirá a unsignedint.
1-.
7legados a este punto am"os operandos son int.
Beamos a3ora el ejemplo% c N a K "M caso 1-: am"as son int. s N r K aM caso S: a se convierte a loat. d N r K "M caso S: " se convierte a loat. d N n K a K rM caso 1: n se convierte a int: la operación resultante corresponde al caso S: el resultado @nKa se convierte a loat. t N r K a s K cM caso S: a se convierte a loat: caso S @rKa # s son loat: caso S: c se convierte a loat. Tam"i6n se aplica conversión de tipos en las asignaciones: cuando la varia"le receptora es de distinto tipo )ue el resultado de la eJpresión de la derec3a. En el caso de las asignaciones: cuando la conversión no implica p6rdida de precisión: se aplican las mismas reglas )ue para los operandos: estas conversiones se conocen tam"i6n como promoción de tipos. Cuando 3a# p6rdida de precisión: las conversiones se conocen como democión de tipos. El compilador normalmente emite un aviso o arning: cuando se 3ace una democión implícita: es decir cuando 3a# una democión automática. En el caso de los ejemplos # S: es eso precisamente lo )ue ocurre: #a )ue estamos asignando eJpresiones de tipo loat a varia"les de tipo int.
C<;BE!&(<;E& A '<<7 En CKK podemos 3a"lar de otro tipo de conversión de tipo implícita: )ue se realiza cuando se usa cual)uier eJpresión entera en una condición: # más generalmente: cuando se usa cual)uier eJpresión donde se espera una eJpresión "ooleana. El dominio del tipo "ool es mu# limitado: #a )ue sólo puede tomar dos valores% true # alse. $or convenio se considera )ue el valor cero es alse: # cual)uier otro valor entero es true. $or lo tanto: 3a# una conversión implícita entre cual)uier entero # el tipo "ool: # si aHadimos esta regla a las eJplicadas antes: cual)uier valor dou"le: longdou"le: loat o cual)uiera de los enteros: inclusoc3ar: se puede convertir a "ool. Esto nos permite usar condiciones a"reviadas en sentencias i: or: 3ile o do..3ile: cuando el valor a comparar es cero.
14
$or ejemplo: las siguientes eJpresiones "ooleanas son e)uivalentes% - NN J e)uivale a bJ. - bN J e)uivale a J. En el primer caso: usamos el operador NN para comparar el valor de J con cero: pero al aplicar el operador b directamente a J o"ligamos al compilador a reinterpretar su valor como un "ool: de modo )ue si J vale - el valor es alse: # balse es true. =e orma sim6trica: si J es distinto de cero: se interpretará como true: # btrue es alse. El resultado es el mismo )ue usando la eJpresión - NN J. En el segundo caso pasa algo análogo. A3ora usamos el operador bN para comparar el valor de J tam"i6n con cero: pero a3ora interpretamos directamente J como "ool: de modo )ue si J vale - el valor es alse: # si J es distinto de cero: se interpretará como true. El resultado es el mismo )ue usando la eJpresión - bN J. ;o está claro cuál de las dos opciones es más eicaz: a la 3ora de compilar el programa. $ro"a"lemente: la segunda re)uiera menos instrucciones del procesador: #a )ue eJisten instrucciones de ensam"lador especíicas para comparar un entero con cero. =el otro modo estaremos comparando con un valor literal: # salvo )ue el compilador optimice este código: generalmente se re)uerirán más instrucciones de este modo. AHadir )ue los ejemplos anteriores uncionan aun)ue el tipo de J no sea un entero. &i se trata de un valor en coma lotante se realizará una conversión implícita a entero antes de evaluar la eJpresión.
Conversiones eJplícitas $ara convertir eJplícitamente una eJpresión a un tipo de datos concreto: utilice el identiicador de tipo de datos seguido de la eJpresión )ue se va a convertir entre par6ntesis. 7as conversiones eJplícitas re)uieren más escritura )ue las implícitas: pero proporcionan más seguridad con respecto a los resultados. Además: las conversiones eJplícitas pueden controlar conversiones con p6rdida de inormación. En el ejemplo siguiente se muestra una conversión de datos eJplícita entre un valor int: un valor &tring # un valor dou"le. vari % intM var d % dou"leM var s % &tringM i N 4M s N &tring@iM __ `idening% t3e int value 4 coverted to t3e &tring Q4Q. d N dou"le@iM __ `idening% t3e int value 4 coverted to t3e dou"le 4. 15
s N &tring@dM __ `idening% t3e dou"le value 4 coverted to t3e &tring Q4Q. i N int@dM
__ ;arroing% t3e dou"le value 4 coverted to t3e int 4.
i N int@sM
__ ;arroing% t3e &tring value Q4Q coverted to t3e int 4.
d N dou"le@sM __ ;arroing% t3e &tring value Q4Q coverted to t3e dou"le 4. 7as conversiones de restricción eJplícitas suelen uncionar correctamente: aun)ue la conversión re)uiera una p6rdida de inormación. 7a conversión eJplícita no se puede utilizar para convertir tipos de datos incompati"les. $or ejemplo: no se pueden convertir datos =ate a datos !egEJp: # viceversa. Además: algunos valores no se pueden convertir por)ue no eJiste ningGn valor razona"le al )ue se puedan convertir. $or ejemplo: se genera un error si se intenta convertir eJplícitamente el valor ;a; de tipo dou"le a un valor decimal. Esto es así por)ue no 3a# un valor decimal natural )ue se pueda identiicar con ;a;. En este ejemplo: se convierte un nGmero )ue tiene una parte decimal # una cadena en nGmeros enteros% vari % intM var d % dou"leM var s % &tringM d N .1SM i N int@dM print@iM s N QappleQM i N int@sM print@iM El resultado es% El comportamiento de la conversión eJplícita depende del tipo de datos originales # del tipo de datos de destino.
En CKK 3a# varios tipos dierentes de casting: pero de momento veremos sólo el )ue eJiste tam"i6n en C. Un casting tiene una de las siguientes sintaJis%
16
@\nom"re de tipoR\eJpresiónR \nom"re de tipoR@\eJpresiónR Esta Gltima es conocida como notación uncional: #a )ue tiene la orma de una llamada a unción. En el ejemplo anterior: las líneas # S )uedarían% d N @int@r K "M d N @int@n K a K rM < "ien% d N int@r K "M d N int@n K a K rM 2acer un casting indica )ue sa"emos )ue el resultado de estas operaciones no es un int: )ue la varia"le receptora sí lo es: # )ue lo )ue 3acemos lo estamos 3aciendo a propósito. Beremos más adelante: cuando 3a"lemos de punteros: más situaciones donde tam"i6n es o"ligatorio el uso de casting.
4()Ta.!a &on&e se &esri.e !as aiones sem+ntias a !a estrutura &e !a gram+tia El análisis semántico se realiza despu6s del sintáctico # es más diícil de ormalizar )ue 6ste. &e trata de determinar el tipo de los resultados intermedios: compro"ar )ue los argumentos )ue tiene un operador pertenecen al conjunto de los operadores posi"les: # si son compati"les entre sí: es decir: compro"ará )ue el signiicado de lo )ue se va le#endo es válido. El análisis semántico utiliza como entrada el ár"ol sintáctico detectado para compro"ar restricciones de tipo # otras limitaciones semánticas # preparar la generación de código. 7a salida “teórica” de la ase de análisis semántico sería un ár"ol semántico. Consiste en un ár"ol sintáctico en el )ue cada una de sus ramas 3a ad)uirido el signiicado )ue de"e tener. En el caso de los operadores polimóricos @un Gnico sím"olo con varios signiicados: el análisis semántico determina cuál es el aplica"le. $or ejemplo: consideremos la siguiente sentencia de asignación% A %N ' K C. En $ascal: el signo “K” sirve para sumar enteros # reales: concatenar cadenas de caracteres # unir conjuntos. El análisis semántico de"e compro"ar )ue ' # C sean de un tipo comGn o compati"le # )ue se
17
les pueda aplicar dic3o operador. &i ' # C son enteros o reales los sumará: si son cadenas las concatenará # si son conjuntos calculará su unión. =ependiendo del tipo de sentencias: las acciones semánticas pueden agruparse en% Acción semántica &entencias de =eclaración
=escripción Completar la sección de tipos de la Ta"la de &ím"olos.
&entencias “ejecuta"les”
!ealizar compro"aciones de tipos entre los operandos implicados.
unciones # procedimientos
Compro"ar el nGmero: orden # tipo de los parámetros actuales en cada llamada a una unción o procedimiento. Compro"ar si un identiicador 3a sido declarado antes de utilizarlo.
(dentiicación de varia"les Eti)uetas Constantes Conversiones # e)uivalencias de tipo
Compro"ar si 3a# eti)uetas repetidas # validación. Compro"ar )ue no se utilicen en la parte iz)uierda de una asignación. Beriicación.
&o"recarga de operadores # unciones =etectar # solventar.
18
5()*eporte &e !a manipu!ai$n &e !a ta.!a &e on1ersi$n &e sím.o!os # &e &ireiones
Intro&ui$n
7a ta"la de sím"olos es una componente necesaria de un compilador. Al declarar un identiicador @normalmente una sola vez: este es insertado en la ta"la. Cada vez )ue se utilice el identiicador se realizara una "Gs)ueda en la ta"la para o"tener la inormación asociada @el valor. Algunos pro"lemas asociados son% 'Gs)ueda: dada la clave de un elemento: encontrar su valor. (nserción: dado un par clavevalor: aHadir un elemento nuevo a la ta"la. Cam"io de valor: 'uscar el elemento # cam"iar su valor. 'orrado: eliminar un elemento de la ta"la. En este reporte en glo"al el uncionamiento de la ta"la de sím"olos # las direcciones así como los m6todos # unos ejemplos en el lenguaje C.
Manipu!ar !a ta.!a &e on1ersi$n &e sím.o!os # &e &ireiones( Una ta"la de sím"olos es una estructura de datos )ue contiene una entrada para cada identiicador encontrado en el programa uente: se crea durante la ase de análisis l6Jico a trav6s de los componentes l6Jicos: pero en el proceso de análisis sintáctico suren algunas modiicaciones. Con el o"jeto de )ue el compilador pueda llevar un control de la inormación so"re el ám"ito # el enlace de los nom"res de datos )ue intervienen en el programa uente. 19
7os campos de cada entrada en la ta"la de sím"olos corresponden a los atri"utos de cada identiicador. @Tipo: valor: dirección: parámetros: etc.. =urante la compilación de un programa: cada vez )ue se encuentra un identiicador en la ta"la de sím"olos: se puede realizar lo siguiente% • • •
7a ta"la puede ser consultada para ver si es necesario dar de alta el nuevo identiicador. En la ta"la se puede completar los atri"utos altantes de un identiicador #a eJistente. &e puede recuperar los atri"utos de un identiicador #a eJistente en la ta"la de sím"olos.
Un mecanismo de ta"la de sím"olos de"e permitir aHadir nuevas entradas # encontrar las entradas eJistentes de un analizador l6Jico eiciente. 7os dos mecanismos para ta"las de sím"olos presentados a continuación son listas lineales # ta"las de dispersión. Cada uno de estos mecanismos se evalGa "asándose en el tiempo necesario para aHadir n entradas # realizar e consultas. Una lista 7ineal es lo más ácil de implantar: pero su rendimiento es po"re cuando e # n se vuelven más grandes. 7as ta"las de dispersión proporcionan un ma#or rendimiento con esuerzo algo ma#or de programación # gasto de espacio. Am"os mecanismos pueden adaptarse rápidamente para uncionar las reglas del anidamiento más cercano. Un compilador de"e ser capaz de aumentar dinámicamente la ta"la de sim"olos durante la complicación. &i la ta"la de sím"olos tiene tamaHo ijo al escri"ir el compilador: entonces el tamaHo de"e ser lo suicientemente grande como para almacenar cual)uier programa uente. Es mu# pro"a"le )ue dic3o tamaHo sea demasiado grande para la ma#oría de los programas e inadecuación para algunos. $ara mantener uniormes los registros de la ta"la de sím"olos: es conveniente guardar una parte de la inormación de un nom"re uera de la entrada de la ta"la: almacenado en el registro solo un apuntador a esta inormación: para 3acer reerencia a 6l.
A&ministrai$n &e !a Ta.!a &e Sím.o!os( Cada entrada de la ta"la de sím"olos corresponde a la declaración de un nom"re. El ormato de las entradas no tiene )ue ser uniorme por)ue la inormación de un nom"re depende del uso de dic3o nom"re. Cada entrada se puede implantar como un registro )ue conste de una secuencia de pala"ras consecutivas de memoria. ;o toda la inormación se introduce en la ta"la de sím"olos.
20
7as pala"ras clave se introducen: al inicio. El analizador l6Jico "usca secuencias de letras # dígitos en la ta"la de sím"olos para determinar si se 3a encontrado una pala"ra clave o un nom"re.
Una ta"la de sím"olos separada en dos partes: utilizando una parte como apuntador a dic3a ta"la para 3acer reerencia a los nom"res almacenados en ella. 7as pala"ras clave de"en estar en la ta"la de sím"olos antes de )ue comience el análisis l6Jico. &i el analizador l6Jico reconoce las pala"ras clave: entonces no necesitan aparecer en la ta"la de sím"olos. &i el lenguaje no convierte en pala"ras reservadas entonces es indispensa"le )ue las pala"ras clave se introduzcan en la ta"la de sím"olos advirtiendo su posi"le uso como pala"ras clave. 7a entrada misma de la ta"la de sím"olos puede esta"lecerse cuando se aclara el papel de un nom"re: # se llenan los valores de los atri"utos cuando se dispone de la inormación. En algunos casos: el analizador l6Jico puede iniciar la entrada en cuanto aparezca un nom"re en los datos de entrada.
Operaiones on !a Ta.!a &e Sím.o!os( En general en la Ta"la de sím"olos @T& a partir de a3ora se realizan dos operaciones% la inserción # la "Gs)ueda. En C la operación de inserción se realiza cuando se procesa una declaración. 2a# dos posi"ilidades% )ue la T& est6 ordenada @o sea: nom"res de varia"les por orden ala"6tico o )ue no est6 ordenada. &i está ordenada: entonces la operación de inserción llama a un procedimiento de "Gs)ueda para encontrar el lugar donde colocar los atri"utos del identiicador a insertar: por lo )ue en este caso la inserción lleva tanto tiempo como la "Gs)ueda. En cam"io: si no está ordenada la T&: la inserción se simpliica muc3o aun)ue se complica la "Gs)ueda: pues de"e eJaminar toda la ta"la. En la "Gs)ueda: se detectan los identiicadores )ue no 3a#an sido declarados previamente: emitiendo un mensaje de error. •
ejemplo en lenguaje C% Undeined sím"olo J: si es una varia"le )ue desea usarse pero no se declaró. 21
En la inserción: se detectan identiicadores )ue #a 3an sido declarados previamente: emitiendo un mensaje de error •
ejemplo en C% multipledeclarationor J si J #a esta"a en T&.
Un nom"re puede indicar varios o"jetos distintos: )uizás incluso en el mismo "lo)ueo o procedimiento. $or ejemplo: las declaraciones en C. (nt JM &truct J @ loat #: zMM Utilizan J como entero # como eti)ueta de una estructura con dos campos. En am"os casos: el analizador l6Jico solo puede devolver al analizador sintáctico el nom"re solo @o un apuntador al leJema )ue orma dic3o nom"re: en lugar de un apuntador a la entrada en la ta"la de sím"olos. Analizador &intáctico@$arser &intaJis% El orden correcto de las pala"ras Ej. $rograma uente% S%N IJ 9S-M AnaleJ% ;U8 A&(,; $
El Analizador semántico. &emántica% &igniicado de las rases. Estando una rase del programa uente #a analizada sintácticamente @QparseadaQ pasa al analizador semántico para veriicar la intención del programador con esa rase% Q$asó por el parser # no presentó erroresQ. Ejemplo% 22
"#te "M int vM &tring sM__Error semántico " N S---M __out o range s N 9---M __incompati"le t#pes o QT#pe mismatc3Q vN 1/M __ out o range
&e crea el registro en la ta"la de sím"olos cuando se descu"re el papel sintáctico )ue desempeHa este nom"re. $ara las declaraciones de la eJpresión se crearían dos entradas en la ta"la de sím"olos para JM una con J como entero # otra como estructura. 7os atri"utos de un nom"re se introducen en respuesta a las declaraciones: )ue pueden ser implícitas. 7as eti)uetas son identiicadores seguidos de dos puntos: asi )ue una acción asociada con el reconocimiento de dic3o identiicador puede ser introducir este 3ec3o en la ta"la de sím"olos. 7a sintaJis de las declaraciones de los procedimientos especiica )ue algunos identiicadores son parámetros ormales.
23
6()Propuesta &e pro#eto 7ina! &e pretende diseHar un sotare )ue sea capaz de analizar los errores tanto l6Jicos como sintácticos de un lenguaje de programación en especíico: o si mismo tam"i6n tomar en cuenta la creación de un ala"eto para diseHar dic3o sotare. 7a implementación de este dic3o sotare será diseHado en el lenguaje de programación cKK: así tam"i6n se tomara en cuenta el ala"eto del mismo compilador # de un lenguaje lógico: el cual su nom"re es prolog. Un compilador es un programa inormático: )ue se encarga de traducir el código uente de una aplicación )ue este en desarrollo: es decir convierte un programa 3ec3o en lenguaje de programación de alto nivel a un lenguaje de má)uina: el cual es conocido como de "ajo nivel: de tal orma )ue sea más entendi"le # muc3o más ácil de procesar en el e)uipo en el )ue se está ejecutando. =e igual manera un traductor es el )ue toma como entrada un teJto escrito # da como salida otro teJto en un lenguaje llamado o"jeto. Un compilador está "asado en distintos "lo)ues los cuales se muestran en la siguiente imagen%
24
Un compilador está ormado por dos procesos análisis # síntesis. 1. Análisis% El cual se trata de la escritura correcta del código uente. Esta a su vez comprende varias ases% Y Análisis l6Jico% esta ase es la encargada de leer el código uente # separarlo en lotes para poder ser leído por el análisis sintáctico. Y Análisis sintáctico% esta ase evalGa los lotes de código con el in de )ue este cumpla con los re)uerimientos deinidos por el compilador. Y Análisis semántico% en esta ase se "usca esta"lecer )ue el código uente cumpla con la semántica solicitada por el compilador: es decir )ue el código este correctamente escrito para poder ser interpretado. /. &íntesis% =espu6s del proceso de análisis se procede a generar grupos de los componentes )ue conorman el programa: para generar una salida. Y ,eneración de código intermedio% este código se genera con el in de mejorar el uso de la memoria con el in de optimizar código uente. Y
CONCLUSIÓN% Es muc3o más diícil introducir m6todos ormales para la recuperación de errores semánticos )ue para la recuperación de errores sintácticos: #a )ue a menudo la recuperación de errores semánticos es ad 3oc. ;o o"stante: puede re)uerirse )ue: por lo menos: el error semántico sea inormado al programador: )ue se le ignore # )ue: por tanto: se suprimirá la generación de código. 25
&in em"argo: la ma#oría de los errores semánticos pueden ser detectados mediante la revisión de la ta"la de sím"olos: suponiendo un tipo )ue se "ase en el conteJto donde ocurra o un tipo universal )ue permita al identiicador ser un operando de cual)uier operador del lenguaje. Al 3acerlo: evitamos la producción de un mensaje de error cada vez )ue se use la varia"le no deinida. &i el tipo de un operando no concuerda con los re)uisitos de tipo del operador: tam"i6n es conveniente reemplazar el operando con una varia"le icticia de tipo universal.
8i.!iogra7ía Cidecame. @s... Errores de compilacion. <"tenido de 3ttp%__cidecame.uae3.edu.mJ_lcc_mapa_$!
26