Documentos de Académico
Documentos de Profesional
Documentos de Cultura
CAPITULO 1.
Introducción a la programación de sistemas
1.3 Lenguajes
Existe una variedad de clasificación de los lenguajes, pero tomando en cuenta las
necesidades contemporáneas, lo más importante es distinguir entre los llamados
lenguajes naturales o vernáculos y los lenguajes artificiales.
1.4.1 Ensambladores
1.4.2 Compiladores
Proceso de Compilación.
El proceso de compilación realiza primero un análisis del programa fuente para
producir la sintaxis del programa objeto. Para ello utiliza diversas tablas.
Para realizar estas funciones las estructuras deben obedecer a reglas muy rígidas,
puesto que la ambigüedad no podría ser dilucidada por la máquina. De ahí la
importancia de los lenguajes formales y de los autómatas en relación con los
lenguajes evolucionados y los compiladores, pues las tareas esenciales del
compilador son la evaluación semántica (o traducción propiamente dicha).
Entre las tablas utilizadas, se halla la tabla de bucles empleada para la estructura
en lazo y para las variables de control.
El explorador (scanner) o analizador lexicográfico tiene como misión indagar
sobre los caracteres del programa fuente y generar los símbolos del programa
para pasarlos a los analizadores sintáctico y semántico.
El programa fuente se representa internamente de muy diferentes formas: árbol,
lista de cuartetos (operador, operador, operador, resultado) o en notación polaca.
Por último, se realizara la generación del código, que es la traducción del
programa fuente interno a lenguaje de máquina o a un lenguaje intermedio.
Clasificación de Compiladores
El programa compilador traduce las instrucciones en un lenguaje de alto nivel a
instrucciones que la computadora puede interpretar y ejecutar. Para cada lenguaje
de programación se requiere un compilador separado. El compilador traduce todo
el programa antes de ejecutarlo. Los compiladores son, pues, programas de
traducción, insertados en la memoria por el sistema operativo para convertir
programas de cómputo en pulsaciones electrónicas ejecutables (lenguaje de
máquina). Los compiladores pueden ser de:
Una sola pasada: examina el código fuente una vez, generando el código o
programa objeto.
Pasadas múltiples: requieren pasos intermedios para producir un código en
otro lenguaje, y una pasada final para producir y optimizar el código
producido durante los pasos anteriores.
Optimación: lee un código fuente, lo analiza y descubre errores potenciales
sin ejecutar el programa.
Compiladores incrementales: generan un código objeto instrucción por
instrucción (en vez de hacerlo para todo el programa) cuando el usuario
teclea cada orden individual. El otro tipo de compiladores requiere que
todos los enunciados o instrucciones se compilen conjuntamente.
Ensamblador: el lenguaje fuente es lenguaje ensamblador y posee una
estructura sencilla.
Compilador cruzado: se genera código en lenguaje objeto para una
máquina diferente de la que se está utilizando para compilar. Es
perfectamente normal construir un compilador de Pascal que genere código
Análisis Léxico.
El análisis lexicográfico, también conocido como rastreo o en ocasiones rastreo y
filtrado, agrupa secuencias de caracteres desde el programa fuente de entrada en
unidades llamadas componentes léxicas o tokens. Así, el rastreo puede
considerarse un mapeo.
En la fase de análisis léxico se leen los caracteres del programa fuente y se
agrupan en cadenas que representan los componentes léxicos. Cada componente
léxico es una secuencia lógicamente coherente de caracteres relativa a un
identificador, una palabra reservada, un operador o un carácter de puntuación.
A la secuencia de caracteres que representa un componente léxico se le llama
lexema (o con su nombre en inglés token). En el caso de los identificadores
creados por el programador no solo se genera un componente léxico, sino que se
genera otro lexema en la tabla de símbolos.
Análisis Sintáctico.
En esta fase, los componentes léxicos se agrupan en frases gramaticales que el
compilador utiliza para sintetizar la salida. La estructura reconocida por el análisis
sintáctico se describe en forma semejante a un árbol y es conocido como árbol
sintáctico, árbol gramatical o árbol de estructura.
Análisis Semántico.
Esta fase determina el significado (semántica) el programa mediante la creación
de tabla de símbolos, verificando cuales de las variables utilizadas han sido
definidas (lenguajes como Pascal requieren esto) y una infinidad de otras tareas
anteriores a la generación de código. Dos de las tareas principales en la fase del
análisis semántico son (1) la verificación estática del programa y (2) la generación
de una representación Intermedia (RI).
La fase de análisis semántico se intenta detectar instrucciones que tengan la
estructura sintáctica correcta, pero que no tengan significado para la operación
implicada.
La generación estática completa el análisis iniciado por el analizador gramatical y
efectúa actividades como la afirmación de que una variable con valor de carácter
no haya sido asignada a una variable declarada con valor entero. Esto se conoce
como verificación de tipos. La verificación estática de tipos varía con el lenguaje
que está siendo compilado.
Optimización de Código.
En esta fase se trata de mejorar el código intermedio, de modo que resulte un
código de máquina más rápido de ejecutar.
Generación de Código.
Esta constituye la fase final de un compilador. En ella se genera el código objeto
que por lo general consiste en código en lenguaje máquina (código relocalizable) o
código en lenguaje ensamblador.
Manejador de errores.
En cada fase del proceso de compilación es posibles encontrar errores. Es
conveniente que el tratamiento de los errores se haga de manera centralizada a
través de un manejador de errores. De esta forma podrán controlarse más
eficientemente los errores encontrados en cada una de las fases de la compilación
de un programa.
1.4.3 Interpretes
Los programas interpretados suelen ser más lentos que los compilados, pero los
intérpretes son más flexibles como entornos de programación y depuración.
Comparando su actuación con la de un ser humano, un compilador equivale a un
traductor profesional que, a partir de un texto, prepara otro independiente traducido
a otra lengua, mientras que un intérprete corresponde al intérprete humano, que
traduce de viva voz las palabras que oye, sin dejar constancia por escrito.
En la actualidad el entorno más común de uso de los intérpretes informáticos es
Internet, debido a la posibilidad que éstos tienen de ejecutarse
independientemente de la plataforma.
PHP, Javascript, ASP (hasta la versión 3) y HTML son ejemplos de lenguajes
interpretados.
Figura 1.
El usuario (esto es, el escritor del compilador) proporciona una descripción del
lenguaje que se va a traducir. Esta descripción puede consistir en un conjunto de
reglas léxicas para la definición de los componentes léxicos y una gramática para
el lenguaje fuente. Algunos compiladores de compiladores manejan esta
información para generar directamente un analizador de léxico y uno sintáctico.
Otros crean tablas para ser utilizadas por rutinas de análisis léxico estándar
manejado por tabla y por rutinas de análisis sintáctico, proporcionadas por el
compilador de compiladores.
Además de la descripción del lenguaje fuente, el usuario proporciona un conjunto
de rutinas semánticas o de generación de código. A menudo existe una rutina
para cada regla de la gramática. El analizador sintáctico llama a esta rutina cada
vez que reconoce la construcción del lenguaje descrita por la regla asociada. Sin
embargo, algunos compiladores de compiladores pueden analizar sintácticamente
una sección más grande del programa antes de llamar a una rutina semántica. En
este caso, puede pasarse una forma interna de las proposiciones que se han
analizado, como sucedería con una porción del árbol sintáctico, a la rutina
semántica. Este último enfoque se usa mucho cuando se efectúa la optimación de
código. Los compiladores de compiladores suelen proporcionar lenguajes
especiales, notaciones, estructuras de datos y otras posibilidades similares, que
pueden emplearse en la escritura de rutinas semánticas.
La principal ventaja de hacer uso de un compilador de compiladores es, por
supuesto, la facilidad de construir y probar un compilador. Sin embargo, la
cantidad de trabajo requerido por el usuario varía considerablemente de un
compilador de compiladores a otro, dependiendo del grado de flexibilidad
proporcionado. Los compiladores generados de esta forma tienden a necesitar
más memoria y compilan los programas con más lentitud que los compiladores
escritos a mano. Sin embargo, el código objeto generado por el compilador puede
ser realmente mejor cuando se usa un compilador de compiladores. A causa de la
construcción automática de analizadores de léxicos y sintácticos, y a las
herramientas especiales que se proporcionan para la escritura de rutinas
semánticas, el escritor del compilador se libera de muchos detalles mecánicos de
la construcción del compilador, por lo que puede centrar más la atención en una
buena generación y optimación de código.
Con el fin de aumenta la velocidad de producción de los compiladores y reducir el
personal que intervenga en ellos, se han desarrollado lenguajes de alto nivel
llamados compilador de compiladores.
Los primeros lenguajes de este tipo aparecieron en 1958 y suelen estructurarse en
sublenguajes específicos para cada parte del proceso de compilación.