miércoles, 1 de junio de 2016

Introducción y Conclusiones


DOCENTE:

ING. Marvin Osmaro Parada

ALUMNO:

José Francisco García Martínez

MATERIA:

Compiladores e Interpretres




Datos personales

Nombre: José Francisco García Martínez

Edad: 20
Sexo: Masculino

Estudios: Universitarios

Universidad: Universidad Gerardo Barrios de Usulután

Carrera: Ing. En Sistemas y Redes Informáticas

Ciclo actualmente cursando: Ciclo 7

Materias actualmente cursando: Compiladores e Interpretes, Administración de Redes de Computadoras, Gestión de Proyectos Informáticos, Auditoria de Sistemas Informáticos, Diseño y Arquitectura de Computador.

¿Qué espero de la materia?

Adquirir las competencias necesarias de la materia.
Adquirir los conocimientos suficientes acerca de los compiladores e interpretes.
Anexar todos estos conocimientos a mi ambito profesional.
Aprobar la materia con excelentes notas y muchos conocimentos de ella.

Introducción

La materia de Compiladores e Intérpretes presenta una introducción al software cuya función única es compilar programas fuentes en un determinado lenguaje, y producir programas ejecutables, la asignatura cubre los fundamentos conceptuales, el principio de funcionamiento, la estructura básica; así también presenta un estudio de aspectos, léxicos, sintácticos y semánticos propios de un compilador. 


Conclusiones personales de la materia

Durante el transcurso de la materia he aprendido sobre términos no antes conocidos por mi, como lo son Traductores, Compilador, Interprete, Tipos de Análisis que tiene el compilador, así como también acerca de un poco al final sobre el lenguaje ensamblador.

Aprendí a través de las diferentes practicas como realizar la fase de análisis léxico, sintáctico y semántico en modo consola en el lenguaje C++, donde una de las competencias a adquirir en el proyecto final es realizar todas esas fases en el mismo lenguaje pero con una interfaz gráfica.

Como estudiante de la carrera Ing. En Sistemas y Redes Informáticas, el cursar la materia compiladores e interpretes ha sido de mucha importancia y ha aportado conocimientos que se que como estudiante de está área me serán de mucha utilidad en mi carrera profesional. 

Clase 10 - Generación de Código Intermedio

Generación de Código Intermedio

INDEPENDENCIA DE LA MÁQUINA 
Según el modelo de arquitectura de un compilador en el que éste se divide en frontend y backend, la etapa inicial traduce el programa fuente a una representación intermedia a partir de la cual la etapa final genera el código objeto, ya sea en forma de código máquina o ensamblador.

La construcción del lenguaje objeto en la etapa final, facilita la reutilización del frontend para crear otros compiladores del mismo lenguaje pero que generan código para otras plataformas.


¿A QUÉ LE LLAMAMOS CÓDIGO INTERMEDIO?

Es una simplificación de los lenguajes de alto nivel en la que se elimina las estructuras y las declaraciones y con sentencias cercanas al ensamblador.


¿PARA QUE LO UTILIZAMOS? 

El código intermedio se utiliza en un compilador por las siguientes razones: 
1. Es mas fácil hacer la conversión en dos fases. 
2. Independiza el analizador sintáctico del resto del compilador. 

Es mas sencillo aplicar la optimización sobre instrucciones independientes del hardware que sobre instrucciones dependientes.

¿A QUÉ LE LLAMAMOS LENGUAJE INTERMEDIO?

Los lenguajes intermedios son representaciones abstractas de un leguaje fuente. Algunas representaciones obsoletas o en desuso son los árboles sintácticos. Actualmente se utilizan como código intermedio las cuádruplas.



Lenguaje Ensamblador.


El término ensamblador (del inglés assembler) se refiere a un tipo de programa informático que se encarga de traducir un fichero fuente escrito en un lenguaje ensamblador, a un fichero objeto que contiene código máquina, ejecutable directamente por la máquina para la que se ha generado. 

El propósito para el que se crearon este tipo de aplicaciones es la de facilitar la escritura de programas, ya que escribir directamente en código binario, que es el único código entendible por la computadora, es en la práctica imposible. 

La evolución de los lenguajes de programación a partir del lenguaje ensamblador originó también la evolución de este programa ensamblador hacia lo que se conoce como programa compilador.

Historia.

El primer compilador fue escrito por Grace Hopper, en 1952 para el lenguaje de programación A-0. 

En 1950 John Backus dirigió una investigación en IBM sobre 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 de alto nivel y se introdujo en 1957 para el uso de la computadora IBM modelo 704.

El primer compilador de FORTRAN tardó 18 años persona en realizarse y era muy sencillo.

El primer compilador autocontenido, es decir, capaz de compilar su propio código fuente fue el creado para Lisp por Hart y Levin en el MIT en 1962. Desde 1970 se ha convertido en una práctica común escribir el compilador en el mismo lenguaje que este compila, aunque Pascal y C han sido alternativas muy usadas.
Crear un compilador autocontenido genera un problema llamado bootstrapping, es decir el primer compilador creado para un lenguaje tiene que o bien ser compilado por un compilador escrito en otro lenguaje o bien compilado al ejecutar el compilador en un intérprete.

Componentes.

Los elementos básicos del lenguaje ensamblador son:
  • Etiquetas: es una palabra utilizada para designar alguna línea o sección del programa, se pueden utilizar para saltar de una parte hacia esa etiqueta.
  • Instrucciones: son las operaciones  que realiza el microcontrolador, así que estas ya están definidas para cada familia de  PIC.
  • Operandos: Son los elementos que emplea la instrucción que se está ejecutando. Usualmente los operandos son los registros, las variables o las constantes.
  • Directivas: son similares a las instrucciones, pero a diferencia de  estas las directivas son propias del lenguaje ensamblador e independientes del microcontrolador que se utilice. 
  • Comentarios: on las palabras, frases y oraciones que se pueden escribir en el código para hacer el programa más claro y legible, o solo para recordar. 

Software editores.

Un programador escribe el programa origen en  lenguaje ensamblador utilizando cualquier editor de textos o procesador de palabras que sea capaz de  producir una salida de texto en ASCII. Una vez que el código origen ha sido escrito, el archivo origen es  ensamblado mediante su procesamiento a través de algún ensamblador.

Software reglas de programación.

Para la programación se utiliza una cierta tabulación que se debe respetar, además utilizar una tabulación adecuada hace los programas más claros y le gibles. 

Software TASM Y TLINK

El Turbo Assembler (TASM) un paquete ensamblador principalmente destinado a la plataforma del IBM PC y sus compatibles. 

El enlazador o linkador LINK permite convertir el código objeto generado por TASM en archivo ejecutable de tipo EXE*. 

*Empleando el ML de MASM 6.X se obtiene directamente el fichero EXE ya que invoca automáticamente al linkador.



Clase 9 - Análisis Semantico

Análisis Semántico.



¿Que es la semántica?

Se refiere a los aspectos del significado, sentido o interpretación del significado de un determinado elemento, símbolo, palabra, expresión o representación formal.


Se trata de determinar el tipo de los resultados intermedios, comprobar que los argumentos que tiene un operador pertenecen al conjunto de los operadores posibles, y si son compatibles entre sí, etc. En definitiva, comprobará que el significado de lo que se va leyendo es válido.

El análisis semántico se realiza posteriormente al sintáctico y mucho más difícil de formalizar que éste.

La salida “teórica” de la fase de análisis semántico sería un árbol semántico.

¿Que es un árbol semántico?

Es una estructura jerárquica en la cual se registran las operaciones que implica u operan dentro del programa fuente. 

En cada una de las ramas del  árbol semántico se registra el valor o significado que este debe tener, y el análisis semántico se encarga de terminar cual de los valores registrados en las ramas es aplicable.

Tabla de símbolos en esta fase.

Un compilador necesita guardar y usar la información de los objetos que se va encontrando en el texto fuente, como variables, etiquetas, declaraciones de tipos, etc.

Esta información se almacena en una estructura de datos interna conocida como tabla de símbolos.

El compilador debe desarrollar una serie de funciones relativas a la manipulación de esta tabla como consultar un elemento en ella, y consultar la información relacionada con un símbolo, etc.

Como se tiene que acceder mucho a la tabla de símbolos los accesos deben ser lo más rápidos posible para que la compilación sea eficiente.

Sistemas de tipo: Es el conjunto de reglas que determinan el criterio para asignar expresiones de tipo a las diferentes partes del código fuente.

*Tipo básico: entero, carácter, real, lógico
*Nombres de tipo
*Constructores de tipo: estructuras, uniones, objetos
*Apuntadores: referencias a tipos ◦ Funciones a=suma();

Chequeos de tipos (y otros)

Un compilador debe realizar una serie de chequeos estáticos, como chequeos de tipos:
Consistencia: unicidad, existencia, no-ciclicidad, ...
Equivalencia y compatibilidad de tipos
Inferencia de tipos (en valores)
Sobrecarga de funciones y operadores

Comprobaciones Semánticas Tipos

Comprobaciones Estáticas.
Las comprobaciones sintácticas y semánticas.
Comprobaciones Dinámicas.
Realizadas en tiempo de ejecución. 

Comprobaciones Semánticas 

*De Tipo.
Verificación del tipo de los operando en las expresiones.

*De Flujo de Control.
 Verifica los puntos del programa de salida y entrada del control.

*De Unicidad.
 Verifica la presencia de símbolos de forma única. (ejemplo: declarar un símbolo una sólo vez).

*Relación de Nombres.
 Un mismo nombre puede aparecer más de una vez.

Clase 8 - Ejemplo de Analizador Lexixo-Sintantico

EJEMPLO DE ANALIZADOR LEXICO-SINTACTICO MINI-DEV

El analizador sintáctico (ASN) comprueba que el orden en que el analizador léxico le va entregando los tokens es válido. Si esto es así significará que la sucesión de símbolos que representan dichos tokens puede ser generada por la gramática correspondiente al lenguaje del código fuente.

La forma más habitual de representar la sintaxis de un programa es el árbol de análisis sintáctico, y lo que hacen los analizadores sintácticos es construir una derivación por la izquierda o por la derecha del programa fuente, que en realidad son dos recorridos determinados del árbol de análisis sintáctico. 


PROTOTIPO DE UN ANALIZADOR LEXICO


Analizador Léxico (Lexico.h)







Analizador Sintáctico (Sintactico.h)









Programa Principal (Lexico.cpp)



Programa Principal (Sintactico.cpp)


Clase 7 - Analisis Sintactico

Análisis Sintáctico


Analisis Sintactico: Determina  la  sintaxis,  o  estructura  de  un programa. Es un análisis a nivel de sentencias, y es mucho más complejo que el análisis léxico.
Su función es tomar  el  programa  fuente  en  forma  de  tokens,  que  recibe  del analizador  léxico,  y  determinar  la  estructura  de  las sentencias del programa.
Este proceso es similar a determinar la estructura de una frase

Análisis Sintáctico – Proceso
       
Código fuente
Analizador léxico o rasterador
Tokens
Analizador Sintáctico
Árbol sintáctico
Analizador Semántico
Árbol con anotaciones
Optimizador de código fuente
Código intermedio
 Generador de código
Código objetivo
Optimizador de código objetivo
Código Objetivo


La tarea del AS es determinar la estructura sintáctica  de  un  programa  a  partir  de  los tokens producidos por el AL.
En  resumen  una  función  que  toma  como entrada la secuencia de tokens y salida el AS.

Secuencia de tokens <> árbol sintáctico

El árbol se define como estructura de datos dinámica,  nodos,  atributos,  campos  del atributo.

Manejo  de  errores,  no  solo  mostrar mensaje  sino recuperarse (inferir  código corregido)  y  continuar  el  análisis,  para encontrar tantos errores como sea posible.

Al proceso de reconocer la estructura del lenguaje fuente se conoce  con  el  nombre  de  análisis  sintáctico  (parsing). 

Hay distintas clases de analizadores o reconocedores sintácticos, pero  en  general  se  clasifican  en  2  grandes  grupos: 
A.S. Ascendentes y A.S. Descendentes.


Tipos de Análisis Sintácticos

Análisis descendente:
Partimos de la raíz del árbol (donde estará situado el símbolo inicial de la gramática) y se van aplicando reglas por la izquierda de forma que se obtiene una derivación por la izquierda de la cadena de entrada.
Para decidir qué regla  aplicar, se lee un token de la entrada.

Análisis ascendente:
Partiendo de la cadena de entrada, se construye el árbol de análisis sintáctico empezando por las hojas (donde están los tokens) y se van creando nodos intermedios hasta llegar a la raíz (hasta el símbolo inicial), construyendo así el árbol de abajo a arriba.
El recorrido del árbol se hará desde las hojas hasta la raíz.

Función principal

Comprueba  que  el orden en que el analizador léxico le va entregando los tokens es  válido.  Si  esto  es  así  significará  que  la  sucesión  de símbolos que representan dichos tokens puede ser generada por la gramática correspondiente al lenguaje del código fuente.


Clase 6 - Analisis Lexico

Análisis Lexixo y Diagramas de Transición

Fases de un compilador:


Analisis Lexico: Está constituido por todas las palabras y símbolos que lo componen. Para un lenguaje de programación la definición también es válida.

Lo constituyen todos los elementos individuales del lenguaje, denominados frecuentemente en inglés tokens.

Token

Así son tokens: las palabras reservadas del lenguaje, los símbolos que denotan los distintos tipos de operadores, identificadores (de variables, de funciones, de procedimientos, de tipos, etc.), separadores de sentencias y otros.

Token 
◦ Elemento léxico del lenguaje 
◦ Símbolo No Terminal de las fases siguientes 

Patrón 
◦ Expresión regular que define el lenguaje 
◦ Letra (Letra | Digito)

Lexema 
◦ Secuencia de caracteres que concuerda con un patrón 
◦ Numero, caracter. 

Atributos 
◦ Estructura de datos de cada token para almacenarse en la TS 
◦ Depende del tipo de token ◦ [ID, Lexema, Tipo, Valor, línea]

Un programa fuente es una serie de símbolos que representan las construcciones del lenguaje tales como variables, etiquetas, palabras reservadas, constantes, operadores, entre otros. 
El programa fuente se trata inicialmente con el analizador léxico.

Pasos del Análisis Lexico:

Identificar la colección de tokens 
Estructurar la colección de tokens
Describir el lenguaje como expresiones regulares

Ejemplo:




El análisis léxico es un análisis a nivel de caracteres, su misión es reconocer los componentes léxicos o tokens, enviando al analizador sintáctico.

Funciones:
Tratar con la tabla de símbolos 
Generar tokens bajo demanda del analizador sintáctico
Manejar el fichero fuente
Ignorar comentarios 
Contabilizar posición de tokens
Preprocesar macros, constantes, includes…



Clase 5 - Test

A continuación se presenta un pequeño test acerca de los compiladores e interpretes, contestar de acuerdo a los conocimientos adquiridos.