sábado, 20 de noviembre de 2010

UNIDAD 1: DEFINICIONES BÁSICAS

EN ESTA UNIDAD SE DAN A CONOCER LOS CONCEPTOS QUE SON NECESARIOS PARA PODER ADENTRARNOS EN MATERIA...



TEMARIO:
INTRODUCCION
LENGUAJES DE PROGRAMACION
PROCESADORES DE LENGUAJE
FASES DE UN COMPILADOR
JERARQUIAS DE CHOMSKY
FORMAS DE BACKUS NAUR

INTRODUCCION


En el año de 1946 se desarrolló el primer ordenador digital. En un principio, estas máquinas ejecutaban instrucciones consistentes en códigos numéricos que señalan a los circuitos de la máquina los estados correspondientes a cada operación. Esta expresión mediante códigos numéricos se llamó Lenguaje Máquina, interpretado por un secuenciador cableado o por un microprograma. Pero los códigos numéricos de las máquinas son engorrosos. Pronto los primeros usuarios de estos ordenadores descubrieron la ventaja de escribir sus programas mediante claves más fáciles de recordar que esos códigos numéricos; al final, todas esas claves juntas se traducían manualmente a Lenguaje Máquina. Estas claves constituyen los llamados lenguajes ensambladores, que se generalizaron en cuanto se dio el paso decisivo de hacer que las propias máquinas realizaran el proceso mecánico de la traducción. A este trabajo se le llama ensamblar el programa.
Los trabajos de investigación se orientaron entonces hacia la creación de un lenguaje que expresara las distintas acciones a realizar de una manera lo más sencilla posible para el hombre. Es por eso que en el año de en 1950, John Backus dirigió una investigación en I.B.M. en un lenguaje algebraico. En 1954 se empezó a desarrollar un lenguaje que permitía escribir fórmulas matemáticas de manera traducible por un ordenador. Le llamaron FORTRAN (FORmulae TRANslator). Fue el primer lenguaje considerado de alto nivel. Se introdujo en 1957 para el uso de la computadora IBM modelo704. Permitía una programación más cómoda y breve que lo existente hasta ese momento, lo que suponía un considerable ahorro de trabajo. Surgió así por primera vez el concepto de un traductor, como un programa que traducía un lenguaje a otro lenguaje.
La tarea de realizar un compilador no fue fácil. El primer compilador de FORTRAN tardó 18 años-persona en realizarse y era muy sencillo. Esta corriente estuvo muy influida por los trabajos sobre gramáticas de contexto libre publicados por Chomsky dentro de su estudio de lenguajes naturales. Con estas ideas surgió un grupo europeo encabezado por el profesor F.L.Bauer . Este grupo definió un lenguaje de usos múltiples independiente de una realización concreta sobre una máquina. Pidieron colaboración a la asociación americana A.C.M. (Association for Computing Machinery) y se formó un comité en el que participó J. Backus que colaboraba en esta investigación. De esa unión surgió un informe definiendo un International Algebraic Language (I.A.L.), publicado en Zurich en 1958. Posteriormente este lenguaje se llamó ALGOL 58 (ALGOritmic Language). En 1969, el lenguaje fue revisado y llevó a una nueva versión que se llamó ALGOL 60.
En el ALGOL aparecen por primera vez muchos de los conceptos de los nuevos lenguajes
algorítmicos:
• Definición de la sintaxis en notación BNF (Backus-Naur Form).
• Formato libre.
• Declaración explícita de tipo para todos los identificadores.
• Estructuras iterativas más generales.
• Recursividad.
• Paso de parámetros por valor y por nombre.
• Estructura de bloques, lo que determina la visibilidad de los identificadores.
En 1958, Strong y otros proponían una solución al problema de que un compilador fuera utilizable por varias máquinas objeto. Para ello se dividía por primera vez el compilador en dos fases, designadas como el "front end" y el "back end". La primera fase (front end) es la encargada de analizar el programa fuente y la segunda fase (back end) es la encargada de generar código para la máquina objeto. El puente de unión entre las dos fases era un lenguaje intermedio que se designó con el nombre de UNCOL (UNiversal Computer Oriented Language
Ya en estos años se van poniendo las bases para la división de tareas en un compilador. Así, en 1959 Rabin y Scott proponen el empleo de autómatas deterministas y no deterministas para el reconocimiento lexicográfico de los lenguajes. Rápidamente se aprecia que la construcción de analizadores léxicos a partir de expresiones regulares es muy útil en la implementación de los compiladores.
En 1968, Johnson apunta diversas soluciones. En 1975, con la aparición de LEX surge el concepto de un generador automático de analizadores léxicos a partir de expresiones regulares, basado en el sistema operativo UNIX.A partir de los trabajos de Chomsky ya citados, se produce una sistematización de la sintaxis de los lenguajes de programación, y con ello un desarrollo de diversos métodos de análisis sintáctico.

Con la aparición de la notación BNF - desarrollada en primer lugar por Backus en 1960 cuando trabajaba en un borrador del ALGOL 60, modificada en 1963 por Naur y formalizada por Knuth en 1964 - se tiene una guía para el desarrollo del análisis sintáctico. Los diversos métodos de parsers ascendentes y descendentes se desarrollan durante la década de los 60. En 1959, Sheridan describe un método de parsing de FORTRAN que introducía paréntesis adicionales alrededor de los operandos para ser capaz de analizar las expresiones. Más adelante, Floyd introduce la técnica de la precedencia de operador y el uso de las funciones de precedencia. A mitad de la década de los 60, Knuth define las gramáticas LR y describe la construcción de una tabla canónica de parser LR. Por otra parte, el uso por primera vez de un parsing descendente recursivo tuvo lugar en el año 1961. En el año 1968 se estudian y definen las gramáticas LL así como los parsers predictivos..
En los primeros años de la década de los 70, se describen los métodos SLR y LALR de parser LR. Debido a su sencillez y a su capacidad de análisis para una gran variedad de lenguajes, la técnica de parsing LR va a ser la elegida para los generadores automáticos de parsers. A mediados de los 70, Johnson crea el generador de analizadores sintácticos YACC para funcionar bajo un entorno UNIX .
Junto al análisis sintáctico, también se fue desarrollando el análisis semántico.
En los primeros lenguajes (FORTRAN y ALGOL 60) los tipos posibles de los datos eran muy simples, y la comprobación de tipos era muy sencilla. No se permitía la coerción de tipos, pues ésta era una cuestión difícil y era más fácil no permitirlo. Con la aparición del ALGOL 68 se permitía que las expresiones de tipo fueran construidas sistemáticamente. Más tarde, de ahí surgió la equivalencia de tipos por nombre y estructural. El manejo de la memoria como una implementación tipo pila se usó por primera vez en 1958 en el primer proyecto de LISP. La inclusión en el ALGOL 60 de procedimientos recursivos potenció el uso de la pila como una forma cómoda de manejo de la memoria. Dijkstra introdujo posteriormente el uso del display para acceso a variables no locales en un lenguaje de bloques.

La técnica de la optimización apareció desde el desarrollo del primer compilador de FORTRAN. Backus comenta cómo durante el desarrollo del FORTRAN se tenía el miedo de que el programa resultante de la compilación fuera más lento que si se hubiera escrito a mano. Para evitar esto, se introdujeron algunas optimizaciones en el cálculo de los índices dentro de un bucle. Pronto se sistematizan y se recoge la división de optimizaciones independientes de la máquina y dependientes de la máquina. Entre las primeras están la propagación de valores , el arreglo de expresiones, la eliminación de redundancias, etc.
Entre las segundas se podría encontrar la localización de registros, el uso de instrucciones propias de la máquina y el reordenamiento de código. A partir de 1970 comienza el estudio sistemático de las técnicas del análisis de flujo de datos. Su repercusión ha sido enorme en las técnicas de optimización global de un programa. En la actualidad, el proceso de la compilación ya está muy asentado. Un compilador es una herramienta bien conocida, dividida en diversas fases.
De todas formas, y en contra de lo que quizá pueda pensarse, todavía se están llevando a cabo varias vías de investigación en este fascinante campo de la compilación. Por una parte, se están mejorando las diversas herramientas disponibles.

LENGUAJES DE PROGRAMACION


Un lenguaje de programación es una construcción mental del ser humano para expresar programas. Está constituido por un grupo de reglas gramaticales, un grupo de símbolos utilizables, un grupo de términos con sentido único y una regla principal que resume las demás. Para que ésta construcción mental sea operable en un computador debe existir otro programa que controle la validez o no de lo escrito. A éste se le llama traductor.
Los lenguajes pueden ser de alto o bajo nivel. En los de bajo nivel las instrucciones son simples y cercanas al funcionamiento de la máquina, como por ejemplo el código máquina y el ensamblador. En los lenguajes de alto nivel hay un alto grado de abstracción y el lenguaje es más próximo a los humanos, como por ejemplo Léxico, PASCAL, Cobol o Java. La programación de los sistemas se hace a través de los lenguajes de programación, que posibilitan la comunicación de órdenes al ordenador o sistema.

Lenguaje de programación

Los lenguajes de programación son herramientas y una notación formal para describir algoritmos o funciones que serán ejecutadas por un ordenador que nos permiten crear programas y software. Entre ellos tenemos Delphi, Visual Basic, Pascal, Java entre otros más.

Un lenguaje de programación es una técnica estándar de comunicación que permite expresar las instrucciones que han de ser ejecutadas en una computadora. Consiste en un conjunto de reglas sintácticas y semánticas que definen un lenguaje informático.

Clasificación de los lenguajes de programación

Existen diferentes clases o tipos de lenguajes de programación:

Según su grado de independencia de la máquina
1) Lenguaje máquina: es el lenguaje de programación que entiende directamente la computadora o máquina.
- Forma más baja de un lenguaje de programación.
- Lenguaje de bajo nivel.
- Secuencias de 0 y 1’s, cada instrucción se representa por un código numérico y las direcciones igual.
- Es la notación que entiende directamente la PC.
- Las instrucciones y la estructura están ligadas directamente a la arquitectura de la PC.

2) Lenguaje ensamblador: fue el primer lenguaje de programación que trato de sustituir el lenguaje máquina por otro mucho más parecido al de los seres humanos.
- Es la versión simbólica del lenguaje máquina (nemónicos).
- Cada código de operación se indica por un código simbólico (ADD MUL DIV MOD).
- Las asignaciones de memoria se dan con nombres simbólicos (PAGO; NOMBRE).

3) Lenguaje de medio nivel
4) - Tiene algunas características de los lenguajes de bajo nivel: posibilidad de acceso directo a posiciones de memoria e indicaciones para que ciertas variables se almacenen en los registros del procesador.
- Presentan la posibilidad del manejo de estructuras de control y estructuras de datos de los lenguajes de alto nivel.
- Ejemplos de estos lenguajes: C y FORTH.
5) Lenguaje de alto nivel: Este tipo de lenguajes de programación son independientes de la máquina, lo podemos usar en cualquier computador con muy pocas modificaciones o sin ellas, son muy similares al lenguaje humano, pero precisan de un programa interprete o compilador que traduzca este lenguaje de programación de alto nivel a uno de bajo nivel como el lenguaje de máquina que la computadora pueda entender.

- Presentan características superiores a los lenguajes de medio nivel, aunque no tienen algunas posibilidades de acceso directo al sistema.
- Facilitan la estructura de programas con estructuras de datos complejas, utilización de bloques y procedimientos o subrutinas.
- Los lenguajes orientados a objetos pertenecen a esta clasificación y permiten definir tipos de datos abstractos que agrupan datos y métodos.

6) Lenguaje orientados a problemas concretos
- Se utilizan para la resolución de problemas en un campo específico.
- Comúnmente se conocen como “aplicaciones”.

Según la forma de sus instrucciones

1) Lenguajes imperativos o procedimentales
- Usan la instrucción o sentencia de asignación como construcción básica en la estructura de los programas.
- También se conocen como “lenguajes orientados a instrucciones”.
- Uso intensivo de variables para referenciar posiciones de memoria.
- La estructura de los programas está basada en instrucciones.
- Ejemplos de estos lenguajes: Pascal, C, C++, Ada, Fortran, Cobol.
2) Lenguajes declarativos
Son lenguajes de muy alto nivel cuya notación es muy próxima al problema del algoritmo que resuelven.
Ejemplos de estos lenguajes: LISP, APL, PROLOG.
3) Lenguajes concurrentes
Permiten la ejecución simultánea (paralela) de dos o varias tareas.
Ejemplos de estos lenguajes: Ada, Concurrent C, Aarhus, Concurrent Prolog.
Ejemplos de estos lenguajes: LISP, APL, PROLOG.
4) Lenguajes orientados a objetos
Soportan directamente tipos abstractos de datos y clases. Lenguajes basados en objetos, añaden mecanismos para soportar la herencia.

Ventajas de los lenguajes de alto nivel sobre los lenguajes de bajo nivel
 Diseño modular de programas.
 Facilitan la estructura de los programas.
 Mayor capacidad de creación de estructuras de datos.
 Son más fáciles de aprender, requieren pocos conocimientos de hardware, y están cerrados a ciertas zonas de la máquina.
 Soporte para la programación orientada a objetos.
 Los programadores se liberan de ocupaciones rutinarias con referencia a instrucciones simbólicas o numéricas, asignaciones de memoria, etc.
 Ofrecen gran variedad de estructuras de control.
 Los programas se depuran más fácilmente que los escritos en lenguaje máquina o ensamblador.
 Permiten trabajar en modo gráfico.
 El programador no necesita conocer la forma en que se colocan los datos en memoria.

PROCESADORES DE LENGUAJE


Un procesador de lenguaje es el nombre genérico que reciben las aplicaciones cuya entrada es un lenguaje (entrada no trivial).

Procesadores de lenguaje
Nombre genérico que reciben todas las aplicaciones informáticas en las cuales uno de los datos fundamentales de entrada es un lenguaje. Proporciona herramientas para ayudar al programador a escribir programas informáticos y a usar diferentes lenguajes de programación de forma práctica.
Que incluyen:

• Traductores: Programa que procesa un texto fuente y genera un texto objeto. Está escrito en un lenguaje de implementación. Se representa por la “Notación T”

Donde:
L. F. = Lenguaje origen que transforma el traductor.
L. O. = Lenguaje a que se traduce el lenguaje fuente.
L. I. = Lenguaje en que está escrito el traductor.

• Ensamblador:Si el lenguaje fuente es el lenguaje ensamblador y el lenguaje objeto es el lenguaje máquina, entonces el traductor se llama Ensamblador. Los ensambladores son traductores sencillos.

• Compilador:Traductor que transforma textos fuente de lenguaje de alto nivel a lenguaje de bajo nivel.
Tiempo de Compilación. Tiempo que se necesita para traducir un lenguaje de alto nivel a lenguaje de bajo nivel.
Tiempo de ejecución. Tiempo que tarda en ejecutarse un programa objeto.

• Montadores de enlace o enlazador (linker):Se produce cuando el lenguaje fuente permite una fragmentación de los programas en trozos, denominados de distintas formas según el lenguaje de programación empleado (módulos, units, librerías, procedimientos, funciones, subrutinas, etc.). Dichas partes pueden compilarse por separado, produciéndose los códigos objeto de cada una de estas partes.

• Cargadores: El cargador se encarga de colocar el fichero ejecutable en memoria; asignando el espacio necesario al programa en memoria y pasando el control a la primera de las instrucciones a ejecutar, comenzando a continuación la fase de ejecución
• Intérpretes: Son programas que simplemente ejecutan las instrucciones que encuentran en el texto fuente. Se da en tiempo de ejecución. Basic, LOGO, Prolog, son lenguajes interpretados.

• Decompiladores: Los decompiladores realizan la tarea inversa a los compiladores, es decir, son un caso particular de los traductores en los cuales el programa fuente es un lenguaje de bajo nivel y el lenguaje objeto es un lenguaje de nivel superior.

• Desensambladores: Un caso particular de los decompiladores son los desensambladores que traducen de código máquina a ensamblador. Son más fáciles, por la correspondencia directa entre las instrucciones de ensamblador y código máquina.

• Depuradores: Los depuradores son herramientas que permiten encontrar y corregir los errores de los programas (bugs). Suelen ir ligados a los compiladores de forma que el programador pueda comprobar y visualizar la correcta ejecución de un programa.

• Analizadores de rendimiento (profilers):Los analizadores de rendimiento son herramientas que permiten examinar el comportamiento de los programas en tiempo de ejecución, permitiendo comprobar qué zonas de código trabajan eficientemente y cuáles deberían ser revisadas por su bajo rendimiento.

• Optimizadores de código: Pueden ser herramientas independientes o estar incluidas en los compiladores e invocarse por medio de opciones de compilación, siendo ésta última forma como se suelen encontrar en la mayor parte de los compiladores comerciales.
• Compresores: Los compresores de archivos son una herramienta habitual de uso en el campo de la informática. Un caso particular son los compresores de ficheros ejecutables, que reducen el tamaño de los ejecutables.
• Preprocesadores: Los preprocesadores son un caso particular de traductor en el cual se traduce un lenguaje de alto nivel a “otro”, cuando el primero no puede pasar a lenguaje máquina directamente. El preprocesador realiza las sustituciones, pero no hace ningún tipo de análisis del contexto donde las realiza, esta es la principal diferencia entre un preprocesador y otros tipos de procesador de lenguaje. En otras palabras, los preprocesadores procesan un texto fuente modificándolo en cierta forma previamente a la compilación.
• Formateadores: Pueden ser de muchos tipos y con diferentes fines, desde los dedicados a formatear textos, ecuaciones o programas. Los formateadores de programas resaltan su sintaxis o su estructura, para lo cual es necesario conocer la sintaxis del lenguaje a formatear.
• Editores: Los editores de lenguajes de programación con sintaxis resaltada por medio de colores o tipos de letra permiten llamar la atención del programador en el momento mismo que está escribiendo el programa, sin necesidad de compilar, dado que llevan incorporada la sintaxis del lenguaje.

FASES DE UN COMPILADOR



Compilador
Son programas o herramientas encargadas de compilar. Un compilador toma un texto (código fuente) escrito en un lenguaje de alto nivel y lo traduce a un lenguaje comprensible por las computadoras (código objeto).

Ejemplos de compiladores
- Borland C++ Compiler 5.5
- Microsoft QuickBasic 7.1
- Borland Turbo Assembler
- Borland Turbo C++ 3.0
- Borland Turbo C++
- Borland Turbo Debugger 5.5
- Borland Turbo Pascal 7
- Apteryx Lisp 1.0
- Object Ada 7.1 Special Edition
- Macromedia Director MX 9.0
- Pacific C MS-DOS Compiler
- CA Clipper 5.3
- XBASE++ Compilador Windows para CA-Clipper


Clasificación de los compiladores

1) Compilador cruzado: Genera un código ejecutable en un ordenador distinto de aquel en que se realiza la compilación.
2) Compilador de montaje y ejecución: Se fragmenta el programa fuente en módulos que se compilan por separado, y una vez compilados se unen mediante un enlazador para formar un módulo ejecutable.
3) Compilador en una pasada: Examina el código fuente una sola vez, generando el código objeto.
4) Compilador de pasadas múltiples: Requiere varias lecturas del programa fuente para producir y optimizar el código objeto.
5) Compilador de optimización: Lee el código fuente, lo analiza, optimiza y descubre errores potenciales sin ejecutar el programa.
6) Compilador incremental: Compila el programa fuente, en caso de detectar errores al volver a compilar el programa corregido, solo compila las modificaciones que se han hecho respecto al primero.
7) Ensamblador: El lenguaje fuente es el lenguaje ensamblador.
8) Autocompilador: Es el compilador que está escrito en el mismo lenguaje a compilar, básicamente nos sirve para hacer ampliaciones al lenguaje, mejorar el código generado, etc.
9) Metacompilador: “Compilador de compiladores”. Obtiene como entrada la definición de un lenguaje y como salida el compilador para dicho lenguaje.


Proceso de compilación
Un compilador opera en fases, cada una de las cuales transforma el programa fuente de una representación en otra, hasta llegar al programa objeto.

FASES DEL PROCESO DE COMPILACIÓN

1. Análisis lineal: También llamado análisis léxico o exploración. En esta etapa la cadena de caracteres que constituye el programa fuente se lee de izquierda a derecha (de arriba hacia abajo) y se agrupa en componentes léxicos que son secuencias de caracteres que tienen un significado colectivo.
NOTA: Los espacios en blanco y comentarios se eliminan durante el análisis léxico.

2. Análisis jerárquico: También llamado análisis sintáctico. En esta etapa los caracteres o componentes léxicos se agrupan jerárquicamente en colecciones anidadas con un significado colectivo.
La representación gráfica del programa fuente se hace mediante un árbol de análisis sintáctico (jerarquías).

3. Análisis semántico: En esta etapa se revisa el programa fuente para tratar de encontrar errores semánticos y se reúne la información de los tipos para la fase posterior de generación de código.
Utiliza la estructura jerárquica determinada en la fase de análisis sintáctico para identificar los operadores y operandos, expresiones y proposiciones.

4. Generación de código intermedio: Algunos compiladores generan una representación intermedia explícita del programa fuente. A esta representación intermedia se le considera “un programa” para una máquina abstracta. El código intermedio debe cumplir con dos propiedades importantes: ser fácil de producir y fácil de traducir al programa objeto.

5. Optimización de código: Trata de mejorar el código intermedio de modo que resulte un código máquina más fácil de ejecutar. Hay mucha variación en la cantidad de optimización de código que ejecutan los compiladores. Un compilador de optimización realiza mucha optimización, ocupando gran parte del tiempo de compilación en esta tarea

6. Generación de código: Fase final de un compilador. Por lo general, consiste en código máquina o ensamblador. Las posiciones de memoria se seleccionan para cada una de las variables usadas por el programa. Después, cada una de las instrucciones intermedias se traducen a una secuencia de instrucciones de máquina que ejecutan la misma tarea.

Otras funciones del compilador:

Administrador de la Tabla de Símbolos
Una función esencial del compilador es registrar los identificadores utilizados en el programa fuente y reunir la información sobre los atributos de cada identificador.
Información que proporcionan los atributos: memoria asignada, tipo, ámbito (locales, globales).
Para procedimientos o funciones: número y tipo de argumentos, método para pasar argumentos, tipo de dato que devuelve.

Manejador de Errores
Cada fase del compilador puede encontrar errores. Después de detectar un error, cada fase debe tratar de alguna forma ese error para poder continuar la compilación, permitiendo la detección de más errores en el programa fuente.
El análisis sintáctico y semántico manejan la mayoría de errores detectables por el compilador.
El análisis léxico detecta errores donde los caracteres restantes de la entrada no forman ningún componente léxico del lenguaje.
El análisis sintáctico detecta los errores donde la cadena de componentes léxicos violan las reglas de la estructura.
El análisis semántico el compilador intenta detectar construcciones que tengan estructura sintáctica correcta pero que no tengan significado para la operación implicada. Por ejemplo, cuando se intenta sumar dos identificadores, donde uno corresponde al nombre de un arreglo y otro al nombre de una función.

Agrupamiento de las fases de compilación
Las fases del proceso de compilación se agrupan en una etapa inicial y una etapa final.
Etapa inicial
Comprende aquellas fases que dependen principalmente del lenguaje fuente y son en gran parte independientes de la máquina objeto.
- Análisis léxico
- Análisis sintáctico
- Análisis semántico
- Generación de código intermedio
Etapa final
Comprende aquellas fases del compilador que dependen de la máquina objeto. No dependen del lenguaje fuente, solo del lenguaje intermedio.
- Optimización de código
- Generación de código

JERARQUIAS DE CHOMSKY



En los años 50 Noam Chomsky (1928) realizó grandes avances en la concepción de un modelo matemático de las gramáticas en conexión con los lenguajes naturales.
Los metalenguajes son herramientas para la descripción formal de los lenguajes, facilitando no sólo la comprensión del lenguaje, sino también el desarrollo del compilador correspondiente. Ejemplos: las expresiones regulares que describen los componentes léxicos del lenguaje; las notaciones BNF, EBNF y los diagramas sintácticos que describen la sintaxis del lenguaje.

En lingüística la jerarquía de Chomsky es una clasificación jerárquica de distintos tipos de gramáticas formales que generan lenguajes formales. Esta jerarquía fue descrita por Noam Chomsky en 1956.


FORMAS DE BACKUS NAUR



John Backus es un informático estadounidense, ganador del Premio Turing en 1977 por sus trabajos en sistemas de programación de alto nivel, en especial por su trabajo con FORTRAN.
John Backus participó en la creación del primer lenguaje de alto nivel (FORTRAN), y posteriormente participó a principios de los años 60 en el desarrollo del lenguaje ALGOL que utilizó por primera vez la forma BNF.
La notación BNF o gramática independiente de contexto permite describir la sintaxis de las construcciones de los lenguajes de programación, utilizando los siguientes metasímbolos:
< > Encierra conceptos definidos o por definir (se utiliza para los no terminales en una gramática).
: : = Para definir o indicar equivalencia
| Separa las distintas alternativas
“ “ Indica que el símbolo entre comillas es un carácter que forma parte de la sintaxis del lenguaje.
( ) Para agrupaciones
Por ejemplo, para definir un identificador (nombre que se utiliza para identificar una variable) en BNF:
::= | |
::= a | b | c | d | e | . . . | z
::= 0 | 1 | 2 | 3 | 4 | . . . | 9
en este caso, a,b,c,d,e,...,z y 0,1,2,3,...,9 son terminales y el resto no terminales.
Leer más...

UNIDAD 2: ANÁLISIS LÉXICO

ENTRANDO EN MATERIA, EN ESTA UNIDAD SE HABLA ACERCA DE LO QUE ES EL ANÁLISIS LÉXICO, LO QUE SON LOS LEXEMAS, UN PATRON,EL MANEJO DEL BUFFERS DE ENTRADA...


FUNCIÓN DEL ANÁLISIS LÉXICO-GRÁFICO
LEXEMAS, PATRONES Y TOKENS
MANEJO DE BUFFERS DE ENTRADA
ESPECIFICACIÓN DE LOS COMPONENTES LÉXICOS
RECONOCIMIENTO DE COMPONENTES LÉXICOS

FUNCIÓN DEL ANÁLISIS LÉXICO-GRÁFICO


El analizador lexicográfico, o explorador, es la parte del compilador que lee el programa fuente, carácter a carácter, y construye a partir de éste unas entidades primarias llamadas tokens. Es decir, el analizador lexicográfico transforma el programa fuente en tiras de tokens.
Función principal del analizador léxico
Leer los caracteres de entrada y elaborar como salida una secuencia de componentes léxicos que utiliza el analizador sintáctico para hacer el análisis.

Funciones secundarias.
• Eliminar del programa fuente comentarios y espacios en blanco (caracteres de espacio en blanco, caracteres TAB, caracteres de nueva línea).

• Relacionar los mensajes de error con el lenguaje fuente.

LEXEMAS, PATRONES Y TOKENS


Componente léxico (token): Son las unidades lógicas que genera el analizador léxico. Es el conjunto de cadenas de entrada que produce como salida el mismo componente léxico. Cada token es una secuencia de caracteres que representa una unidad de información en el programa fuente.

Los componentes léxicos más comunes son los siguientes:
 palabras clave o reservadas
 operadores aritméticos
 operadores relacionales
 operadores lógicos
 operador de asignación
 identificadores
 constantes
 cadenas
 literales
 signos de puntuación
 librerías

Lexema: Representan cadenas de caracteres en el programa fuente que se pueden tratar juntos como una unidad léxica. Un lexema es una secuencia de caracteres en el programa fuente con la que concuerda el patrón para un componente léxico.

Patrón: Regla que describe el conjunto de lexemas que pueden representar a un determinado componente léxico en los programas fuente.

Atributos de los componentes léxicos: El analizador léxico recoge información sobre los componentes léxicos en sus atributos asociados. Los componentes léxicos influyen en las decisiones del análisis sintáctico y los atributos en la traducción de los componentes léxicos.

MANEJO DE BUFFERS DE ENTRADA


Buffer: Área del almacenamiento primario destinada a contener datos durante transferencia de entrada salida. Durante la entrada los datos son cargados en el buffer, al terminar la transferencia ya se puede trabajar con ellos.

Técnica de “Pareja de buffers”
En la técnica de pareja de buffers se utiliza un buffer dividido en dos mitades de N caracteres cada uno:

Donde:
N  número de caracteres en un bloque de disco
eof  marca el final del archivo fuente

Al principio, los dos apuntadores apuntan al primer carácter del próximo lexema que hay que encontrar:
1. El APUNTADOR DELANTERO examina hacia delante hasta encontrar una concordancia con un patrón. Una vez determinado el siguiente lexema, el apuntador delantero se coloca en el carácter de su extremo derecho.
2. El APUNTADOR DE LEXEMA se queda al inicio del lexema y lo procesa.
Después de haber procesado el lexema, ambos apuntadores se colocan en el carácter situado inmediatamente después del lexema.

Técnica de “Centinelas”
Si se utiliza la pareja de buffers, cada vez que se mueva el apuntador delantero se debe comprobar si se ha salido de una mitad del buffer, si así ocurriera se deberá cargar la segunda mitad. Es decir, para hacer avanzar el apuntador se realizan dos pruebas.
Se pueden reducir estas dos pruebas a una si se amplía cada mitad del buffer para admitir un carácter centinela (carácter especial que no puede ser parte del programa fuente – eof) al final.

ESPECIFICACIÓN DE LOS COMPONENTES LÉXICOS


Expresiones regulares
Notación o representación para especificar patrones para un componente léxico. Cada patrón concuerda con una serie de cadenas, de modo que las expresiones regulares servirán como nombres para conjuntos de cadenas.

Cadenas y lenguajes
Alfabeto o clase de carácter: Denota cualquier conjunto finito de símbolos (letras o caracteres).
Conjunto {0,1} alfabeto binario
a, b, c, d, e, ... , z alfabeto
Código ASCII, EBCDIC alfabetos del computador
Cadena (frase o palabra): Es una secuencia finita de símbolos tomadas de un alfabeto.
Lenguaje: Se refiere a cualquier conjunto de cadenas de un alfabeto fijo.

También se puede extender el operador de “exponenciación” a los lenguajes definiendo L° como { }

Sea L el conjunto {A, B, C, D, ...,Z, a, b, c, d,...,z} y D el conjunto {0, 1, 2, ..., 9}. Algunos ejemplos de nuevos lenguajes creados a partir de L y D:
1. LUD es el conjunto de letras y dígitos.
2. LD es el conjunto de cadenas que consta de una letra seguida de un dígito.
3. L4 es el conjunto de todas las cadenas de cuatro letras.
4. L* es el conjunto de todas las cadenas de letras, incluyendo la cadena vacía ( ).
5. L(LUD)* es el conjunto de todas las cadenas de letras y dígitos que comienzan con una letra.
6. D+ es el conjunto de todas las cadenas de uno o más dígitos.

Las expresiones regulares se utilizan para describir los componentes léxicos de un lenguaje o tokens. Las expresiones regulares utilizan varios tipos de operadores para definir los componentes léxicos:
• Paréntesis. Para agrupar símbolos
• Operación concatenación. Se permite la concatenación de cadenas.
• Operación alternativa. Se representa por |, y permite la elección entre dos o más alternativas.

Componentes léxicos:

a) Identificador: (Letra seguida de letras y dígitos). Se puede definir a partir de dos símbolos: letra y dígito.
letra (letra|dígito)*

b) Constante entera
(sin signo) digito+
(con signo) (+|-) digito+

c) Constante de punto flotante sin exponente
(+|-) digito+.digito+

Abreviaturas en la notación

1. Uno o más casos de. +

2. Cero o un caso. ?

Conjuntos no regulares
Aquellos lenguajes que no se pueden describir con ninguna expresión regular.

RECONOCIMIENTO DE COMPONENTES LÉXICOS


Consideremos el siguiente formato gramatical:
Prop  if expr prop
| if expr prop else prop
| €

expr  termino op_rel termino
| termino

termino  id | num

*Donde if, else, opr_rel, id, num, generan conjuntos de cadenas dadas por la siguiente definición regular:


If  if
else  else
op_rel < | <= | == | >= | > | < >
id  letra (letra|digito)*
num  digitos fraccion_optativa exponente_optativo
letra  a|b|c|d| ... |z|A|B|C|...|Z
digito  0|1|2|3|...|9
digitos  digito digito*
fraccion_optativa  .digitos|€
exponente_optativo  (E(+|-|€) digitos)|€

* El analizador léxico reconoce las palabras clave del lenguaje (if, else)
* op_rel, id, num, los representa por su expresión regular.

Leer más...

UNIDAD 3: ANÁLISIS SINTÁCTICO

EN ESTA UNIDAD SE HABLA ACERCA DE LA FUNCION QUE REALIZA EL ANALIZADOR SINTÁCTICO, ASI COMO TAMBIEN LO QUE SON LAS GRAMATICAS Y SU ESTRUCTURA...


FUNCION DEL ANÁLISIS SINTÁCTICO
GRAMÁTICAS INDEPENDIENTES DE CONTEXTO
ESCRITURA DE UNA GRAMÁTICA
ANÁLISIS SINTÁCTICO DESCENDENTE
ANÁLISIS SINTÁCTICO ASCENDENTE
ANÁLISIS SINTÁCTICO POR PRECEDENCIA DE OPERADORES
ANALIZADORES SINTÁCTICOS IZQUIERDA-DERECHA
USO DE GRAMÁTICAS AMBIGUAS

FUNCION DEL ANALISIS SINTACTICO


El analizador sintáctico obtiene una cadena de componentes léxicos del analizador léxico, y comprueba si la cadena puede ser generada por la gramática del programa fuente.

Tipos generales de analizadores sintácticos para gramáticas:
a) Análisis sintáctico descendente. Construye árboles de análisis sintáctico desde arriba (raíz) hacia abajo (hojas). El análisis se realiza de lo general a lo particular.
b) Análisis sintáctico ascendente. Construyen árboles de análisis sintáctico comenzando en las hojas y suben hacia la raíz. El análisis se realiza de lo particular a lo general.
En ambos casos, se examina la entrada al analizador léxico de izquierda a derecha, un símbolo a la vez.

GRAMATICAS INDEPENDIENTES DE CONTEXTO


Una gramática describe de forma natural la estructura jerárquica de muchas construcciones de los lenguajes de programación. Las gramáticas libres de contexto permiten describir la mayoría de los lenguajes de programación, de hecho, la síntaxis de la mayoría de lenguajes de programación está definida mediante gramáticas libres de contexto. Por otro lado, estas gramáticas son suficientemente simples como para permitir el diseño de eficientes algoritmos de análisis sintáctico que, para una cadena de caracteres dada determinen como puede ser generada desde la gramática
Consta de:
• TERMINALES. Símbolos básicos con que se forman las cadenas. Para un lenguaje de programación, cada palabra clave/reservada es un terminal.

• NO TERMINALES. Son variables sintácticas que denotan conjuntos de cadenas (identificadotes o variables). Los no terminales definen conjuntos de cadenas que ayudan a definir el lenguaje generado por la gramática. Imponen una estructura jerárquica sobre el lenguaje que es útil tanto para el análisis sintáctico como para la traducción.

• UN SÍMBOLO INICIAL. En una gramática, es un no terminal que representa un conjunto de cadenas.

• PRODUCCIONES. Especifican cómo se pueden combinar los terminales y no terminales para formar cadenas. Cada producción consta de un No terminal (símbolo inicial), seguido por una flecha o símbolo de asignación, seguida por una cadena de no terminales y terminales.

ESCRITURA DE UNA GRAMATICA


Las gramáticas describen la mayoría de las sintaxis de los lenguajes de programación.Toda construcción que se pueda describir mediante una expresión regular también se puede describir por medio de una gramática.
Por ejemplo, para la expresión regular (a|b)* abb
Y la gramática: A0 → a A0 | b A0| b A1
A1 → b A2
A2 → bA3
A3 → є

ANALISIS SINTACTICO DESCENDENTE


Se considera un intento de encontrar una derivación por la izquierda para una cadena de entrada.También se puede considerar como un intento de construir un árbol de análisis sintáctico para la entrada comenzando desde la raíz y creando nodos del árbol en orden previo.

ANALISIS SINTACTICO ASCENDENTE


El análisis sintáctico ascendente intenta construir un árbol para la cadena de entrada que comienza por las hojas (el fondo) y avanza hacia la raíz (la cima).

ANÁLISIS SINTÁCTICO POR PRECEDENCIA DE OPERADORES


Para una pequeña clase de gramáticas se puede construir con facilidad a mano eficientes analizadores sintácticos ascendentes.Estas gramáticas, por precedencia de operadores, tienen la propiedad de que ningún lado derecho de la producción es є ni tiene 2 terminales adyacentes.
Una gramática con esta última propiedad de denomina gramática de operadores.

ANALIZADORES SINTÁCTICOS IZQUIERDA-DERECHA


Es una técnica eficiente de análisis sintáctico ascendente que se puede utilizar para analizar una amplia clase de gramáticas independientes de contexto, denominada Análisis sintáctico LR(k)
L es por el examen de la entrada de izquierda a derecha (left to right)
R por construir una derivación por la derecha (right most derivation) en orden inverso.
K por el número de símbolos de entrada de examen por anticipado utilizados para tomar decisiones del análisis sintáctico. Cuando se omite, se asume que k es 1.
Este análisis es atractivo por varias razones:
• Reconocen prácticamente todas las construcciones de los lenguajes de programación para los que se pueden escribir gramáticas independientes del contexto.
• Puede detectar un error sintáctico tan pronto como sea posible hacerlo en un examen de izquierda a derecha de la entrada.

USO DE GRAMÁTICAS AMBIGUAS


Gramática ambigua es aquella que produce más de un árbol de análisis sintáctico para alguna frase, es decir, una gramática ambigua es la que produce más de una derivación por la izquierda o por la derecha para la misma frase.Algunos tipos de gramáticas ambiguas son útiles en la especificación e implementación de lenguajes. Se utiliza para el aislamiento de construcciones sintácticas habituales para optimación en casos especiales.
Una Sentencia es ambigua si hay más de una derivación distinta. Si una sentencia es ambigua, el árbol de análisis sintáctico no es único; podemos crear más de un árbol de análisis sintáctico para la misma sentencia.Con una gramática ambigua se pueden especificar las construcciones de casos especiales añadiendo cuidadosamente nuevas producciones a la gramática. Las construcciones ambiguas se deben usar raramente y de una manera estrictamente controlada, pues de lo contrario no se puede reconocer con seguridad el lenguaje que reconoce el analizador.

Leer más...

UNIDAD 4: HERRAMIENTAS PARA GENERAR COMPILADORES

ESTA UNIDAD TRATA SOBRE LAS DIFERENTES HERRAMIENTAS CON LAS QUE SE CUENTA HOY EN DIA PARA PODER CREAR NUESTRO PROPIO COMPILADOR, CONOCIENDO CADA UNA DE LAS HERRAMIENTAS QUE A CONTINUCACION SE DESCRIBEN...



HERRAMIENTAS TRADICIONALES
HERRAMIENTAS DE NUEVA GENERACION
OTRAS HERRAMIENTAS
KIT PARA LA CONSTRUCCION DE COMPILADORES

HERRAMIENTAS TRADICIONALES


- Lex/Yacc: Sirven, respectivamente, para generar analizadores lexicográficos y analizadores sintácticos para su aprovechamiento como partes de los compiladores de los lenguajes de programación; estos usos de Lex y Yacc no son los únicos, aunque sí son los que aquí se consi¬deran principalmente.
Para entender cabalmente el funcionamiento de los generadores de analizadores, hay que co¬nocer la teoría de compiladores relacionada con las tareas de análisis de lenguajes.

Cuando se emplea el término Lex, se mencionan dos posibles significados:
a) una notación para especificar las características lexicográficas de un lenguaje de programación,
b) un traductor de especificaciones lexicográficas.

- Pclex: Permite mostrar cómo, utilizando expresiones regulares, se puede combinar la especificación
de patrones con acciones, por ejemplo, haciendo entradas de una tabla de símbolos cuya ejecución se pueda pedir a un analizador léxico.
- Flex: Es un marco de trabajo de código abierto gratuito y altamente productivo para la creación de aplicaciones web expresivas que se implantan coherentemente en exploradores, ordenadores de sobremesa y sistemas operativos


HERRAMIENTAS DE NUEVA GENERACION


ANTLR:(ANother Tool for Language Recognition – otra herramienta para reconocimiento de lenguajes) es una herramienta creada principalmente por Terence Parr, que opera sobre lenguajes, proporcionando un marco para construir reconocedores (parsers), intérpretes, compiladores y traductores de lenguajes a partir de las descripciones gramaticales de los mismos (conteniendo acciones semánticas a realizarse en varios lenguajes de programación).
- Se considera el lex/yacc del nuevo milenio.
- Genera árboles sintácticos descendentes .
- Escrito íntegramente en JAVA.
- Genera código en JAVA o C++.
JAVACC: (Java Compiler Compiler) es un generador de analizadores sintácticos de código abierto para el lenguaje de programación Java. JavaCC es similar a Yacc en que genera un parser para una gramática presentada en notación BNF, con la diferencia de que la salida es en código Java. A diferencia de Yacc, JavaCC genera analizadores descendentes (top-down), lo que lo limita a la clase de gramáticas LL(K) (en particular, la recursión desde izquierda no se puede usar).
- Inicialmente se llamo JACK.
- Similar al ANTLR.
- Analizador ascendente.

OTRAS HERRAMIENTAS


BYACC/JAVA
- Extensión de YACC para generar código JAVA en vez de C/C++.
- Fichero de especificaciones igual que YACC
- Código y declaraciones de lenguaje escritos en JAVA.
COCO/JAVA
- Generados de compiladores que a partir de la descripción del lenguaje mediante una gramática LL genera un analizador sintáctico y un analizador léxico para dicho lenguaje.
CUP
- Versión LEX/YACC para JAVA (su forma de trabajo es análoga).
JACCIE
- JAVA BASED COMPILER.-Compiler in an Interactive Environment.
- Herramienta educativa que se puede utilizar para visualizar las técnicas de compilación.
- Dos principales componentes: un generador de analizadores léxicos y una variedad de generadores de generadores sintácticos.
JELL
- Es un generador de analizadores sintácticos que genera analizadores descendentes a partir de gramáticas LL.

KIT PARA LA CONSTRUCCION DE COMPILADORES


COKTAIL
Conjunto de herramientas para construir compiladores
- REXgenerador de analizadores léxicos.
- LALRgenerador de analizadores sintácticos.
- ELLgenerador de analizadores sintácticos.
- ASTgenerador de árboles sintácticos.
- AGpermite procesar gramáticas atribuidas.

ELI
- Combina una variedad de herramientas estándar para implementar potentes estrategias en la construcción de compiladores.
- Se pueden generar automáticamente implementaciones de lenguajes completos a partir de las especificaciones de la aplicación.
- Contiene librerías de especificaciones reusables.
PCCT
- Escrito inicialmente en C++ para generar compiladores en C++.
- Portado a JAVA y llamado ANTLR.XX
- Consta de 3 herramientas:
• ANTLRgenerador de analizadores de sintácticos
• DLGgenerador de analizadores léxicos
• SORCERERgenerador de árboles sintácticos

Leer más...

UNIDAD 5: ANÁLISIS SEMÁNTICO

EN ESTA UNIDAD SE MUESTRAN LAS REGLAS SEMÁNTICAS, CUAL ES LA FUNCIÓN DEL ANÁLISIS SEMÁNTICO ASI COMO LAS REGLAS Y LA COMPATIBILIDAD DE TIPOS...



TEMARIO:
FUNCIÓN DEL ANÁLISIS SEMÁNTICO
REGLAS SEMÁNTICAS
COMPATIBILIDAD DE TIPOS
SISTEMAS DE TIPOS
COMPROBACIÓN ESTÁTICA Y DINÁMICA DE TIPOS
COMPROBACIÓN DE TIPOS EN EXPRESIONES, SENTENCIAS Y FUNCIONES
CONVERSIÓNES DE TIPOS

FUNCION DEL ANÁLISIS SEMÁNTICO


La tarea del compilador requiere la extracción del contenido semántico incluido en las distintas sentencias del programa. Es por esto que se hace necesario dotar al compilador de una serie de rutinas auxiliares que permitan captar todo aquello que no se ha expresado mediante la sintaxis del lenguaje y todo aquello que hace descender a nuestro lenguaje de programación de las alturas de una máquina abstracta hasta el nivel de un computador real.
El análisis semántico completa las dos fases anteriores de análisis lexicográfico y sintáctico incorporando ciertas comprobaciones que no pueden asimilarse al mero reconocimiento de una cadena dentro de un lenguaje.
La fase de análisis semántico revisa el programa fuente para tratar de encontrar errores semánticos y reúne la información sobre los tipos para la fase posterior de generación de código. Un componente importante del análisis semántico es la Verificación de Tipos. Aquí, el compilador verifica si cada operador tiene operandos permitidos por la especificación del lenguaje fuente.

REGLAS SEMÁNTICAS


Las reglas semánticas vienen dadas en función de los atributos de los demás símbolos que componen la regla.
La evaluación de las reglas semánticas puede generar código, guardar información en una tabla de símbolos, emitir mensajes de error o realizar otras actividades. La traducción de la cadena de componentes léxicos es el resultado obtenido al evaluar las reglas semánticas.La evaluación de las reglas semánticas define los valores de los atributos en los nodos del árbol de análisis sintáctico para la cadena de entrada.

COMPATIBILIDAD DE TIPOS


Un compilador debe comprobar si el programa fuente sigue tanto las convenciones sintácticas como las semánticas del lenguaje fuente. Esta comprobación, llamada comprobación estática, garantiza la detección y comunicación de algunas clases de errores de programación.
Los ejemplos de comprobación estática incluyen:
1. Comprobaciones de tipos: Un compilador debe informar de un error si se aplica un operador a un operando incompatible.
2. Comprobaciones del flujo de control: Las proposiciones que hacen que el flujo del control abandone una construcción deben tener algún lugar a dónde transferir el flujo de control
3. Comprobaciones relacionadas con nombres: En ocasiones, el mismo nombre debe aparecer dos o más veces en un mismo bloque de instrucciones, el compilador debe comprobar que se utilice el mismo nombre en ambos sitios.

SISTEMAS DE TIPOS


El diseño de un comprobador de tipos para un lenguaje se basa en información acerca de las construcciones sintácticas del lenguaje, la noción de tipos y las reglas para asignar tipos a la construcciones de lenguaje.

Expresiones de tipos
El tipo de una construcción de un lenguaje se denotará mediante una “expresión de tipo”. De manera informal, una expresión de tipo es, o bien un tipo básico o se forma aplicando un operador llamado constructor de tipos a otras expresiones de tipos.
Cada lenguaje de programación requerirá unas expresiones de tipos adecuadas a sus características.
Expresiones de tipos más comunes:
• Tipos simples: Son expresiones de tipos los tipos simples del lenguaje, y algunos tipos especiales:
 integer
 real
 char
 boolean
 void
 error

• Constructores de tipos: Permiten formar tipos complejos a partir de otros más simples. La semántica de cada lenguaje tiene asociada unos constructores de tipos propios. En general, en los lenguajes de programación se definen los siguientes constructores:
 Matrices: Si T es una expresión de tipos, entonces array(R,T) es también una expresión de tipos que representa a una matriz de rango R de elementos de tipo T.
 Productos: Sea T1 y T2 expresiones de tipos, T1 x T2 es una expresión de tipos que representa al producto cartesiano de los tipos T1 y T2. A fin de simplificar consideraremos que el constructor u operador de tipos x es asociativo por la izquierda.
 Registros: Sea un registro formado por los campos u1, u2 ... uN, siendo cada uno de ellos de los tipos T1,T2 ... TN.
 Punteros: Si T es una expresión de tipos, entonces pointer(T) es una expresión de tipos que representa a un puntero a una posición de memoria ocupada por un dato de tipo T.
 Funciones: Sean T1,T2 ... TN, las expresiones de tipos asociadas a los segmentos de código correspondientes a los argumentos de una función, y sea T el tipo devuelto por la función. Las expresiones de tipo pueden contener variables cuyos valores son expresiones de tipos.

COMPROBACIÓN ESTÁTICA Y DINÁMICA DE TIPOS


Se dice que la comprobación realizada por un compilador es estática, mientras que la comprobación hecha al ejecutar el programa objeto se denomina dinámica. En principio, cualquier verificación se puede realizar dinámicamente, si el código objeto carga el tipo de un elemento con el valor de dicho elemento.

Recuperación de errores
Como la comprobación de tipos tiene la capacidad de descubrir errores en los programas, es importante que un comprobador de tipos haga algo razonable cuando se descubre un error. Como mínimo, el compilador debe informar de la naturaleza y la posición del error. Es mejor que el comprobador de tipos se recupere de los errores, para que pueda comprobar el resto de la entrada. Como el manejo de errores afecta a las reglas de comprobación de tipos, tiene que diseñarse como parte del sistema de tipos desde el principio; las reglas tienen que servir para tratar los errores.

COMPROBACIÓN DE TIPOS EN EXPRESIONES, SENTENCIAS Y FUNCIONES


A partir de reglas semánticas se desarrolla la comprobación de tipos para expresiones, sentencias y funciones. El comprobador de tipos es un esquema de traducción que sintetiza el tipo de cada expresión a partir de los tipos de las subexpresiones. El comprobador de tipos puede manejar matrices, apuntadores, proposiciones y funciones.

CONVERSIONES DE TIPOS


Considérense expresiones como x + i donde x es de tipo real e i es de tipo entero. Como pa representación de enteros y reales es distinta dentro de un computador, y se utilizan instrucciones de máquina distintas para las operaciones sobre enteros y reales, puede que el compilador tenga que convertir primero uno de los operandos de + para garantizar que ambos operandos sean del mismo tipo cuando tenga lugar la suma.
La definición del lenguaje especifica las conversiones necesarias. Cuando un entero se asigna a un real, o viceversa, la conversión es al tipo del lado izquierdo de la asignación. En expresiones, la transformación más común es la de convertir el entero en un número real y después realizar una operación real con el par de operandos reales obtenidos. Se puede utilizar el comprobador de tipos en un compilador para insertar estas operaciones de conversión en la representación intermedia del programa fuente.

Coerciones
Se dice que la conversión de un tipo a otro es implícita si el compilador la va a realizar automáticamente. Las conversiones de tipo implícitas, también llamadas coerciones, se limitan en muchos lenguajes a situaciones donde en principio no se pierde ninguna información; por ejemplo, un entero se puede transformar en un real pero no al contrario.
Se dice que la conversión es explícita si el programador debe escribir algo para motivar la conversión. Para un comprobador de tipos, las conversiones explícitas parecen iguales que las aplicaciones de función, así que no presentan problemas nuevos.
La conversión implícita de constantes se puede realizar generalmente en el momento de la compilación, mejorando a menudo el tiempo de ejecución del programa objeto.

Sobrecarga de funciones y operadores
Un símbolo sobrecargado es el que tiene distintos significados dependiendo de su contexto. La sobrecarga se resuelve cuando se determina un significado único para un caso de un símbolo sobrecargado. La resolución de la sobrecarga a menudo aparece referida como identificación de operadores porque determina la operación que denota un símbolo de operador.
Funciones polimórficas
Un procedimiento normal permite que las proposiciones de su cuerpo se ejecuten con argumentos de tipos fijos; cada vez que se llama un procedimiento polimórfico, las proposiciones de su cuerpo pueden ejecutarse con argumentos de tipos distintos. El término “polimórfico” también se aplica a cualquier parte de código que pueda ejecutarse con argumentos de tipos distintos, de modo que se puede hablar de funciones, así como de operadores polimórficos.

Leer más...