lunes, 8 de mayo de 2017

Diferencia entre Atributos Heredados y Sintetizados

Atributos Sintetizados
Los atributos sintetizados se utilizan ampliamente.
Si una definición dirigida por sintaxis tiene únicamente atributos sintetizados se dice que es S-atribuida.
El árbol de análisis sintáctico de una gramática S-atribuida puede decorarse mediante un recorrido en post orden.
Atributos Heredados
Sirven para expresar la dependencia que hay entre una construcción del lenguaje de programación y su contexto.
Siempre es posible reescribir una definición dirigida por sintaxis para que sea S-atribuida.

En ocasiones es más natural utilizar atributos heredados

Herencia

La Herencia es específica de la programación orientada a objetos, donde una clase nueva se crea a partir de una clase existente. La clase existente se denomina superclase. La clase derivada de la superclase se denomina la subclase. 
En la Herencia la subclase (la nueva clase creada) contiene los atributos y métodos de la clase primaria. La principal ventaja de la herencia es la capacidad para definir atributos y métodos nuevos para la subclase, que luego se aplican a los atributos y métodos heredados.
Esta particularidad permite crear una estructura jerárquica de clases cada vez más especializada.

¿En qué consiste?
Existen dos clases, a las que llamaremos padre (superclase o clase base) e hija (subclase o clase derivada) Al igual que las herencias en la vida real, la clase hija pasa a tener lo que tiene la clase padre Atributos Métodos Un objeto de la clase hija es también un objeto de la clase padre
¿En qué consiste?
 En la clase hija se definen las diferencias respecto de la clase padre
¿Para qué se usa?

Para extender la funcionalidad de la clase padre Para especializar el comportamiento de la clase padre

lunes, 3 de abril de 2017

Analizador Lexico y Sintactico

Analizador Léxico

CODIGO
package examen_3;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.*;
import java.lang.*;
import javax.swing.JOptionPane;
public class Examen_3 {
    public static void main (String[] args)throws IOException {
        BufferedReader a= new BufferedReader(new InputStreamReader(System.in));
        String lector;
        int cont_pal=0;
        String cadena;
        try{
            FileReader fr = new FileReader("C:\\Users\\Carmona Yañez\\Documents\\NetBeansProjects\\examen_3\\Examen3.txt");
            BufferedReader br = new BufferedReader(fr);
            lector = JOptionPane.showInputDialog("QUE PALABRA DESEAS BUSCAR: ");
            
            while ((cadena=br.readLine())!=null){
                String arreglo[] = cadena.split(" ");
                
                for (int i=0; i<arreglo.length;i++){
                    if(arreglo[i].equals(lector)){
                    cont_pal++;    
                    }
                } 
            }
            JOptionPane.showMessageDialog(null," "+cont_pal+" veces se repite la palabra: "+lector);
        }catch (Exception ex){
        }
    }
}

Compilamos el programa de Java, y al ejecutarlo se abre el siguiente recuadro, el cual nos pide que introduzcamos en el área de texto

Al dar click en Aceptar el programa lo que hace es buscar la palabra en el documento de texto llamado Examen3, y este nos dice cuantas veces se repite la palabra dentro del texto

Puede diferenciar entre mayúsculas y minúsculas

Y también distingue palabras alfanuméricas

Analizador Sintáctico
CÓDIGO
package lenguaje_formal;
import java.lang.*;
import java.io.*;
import javax.swing.JOptionPane;
public class Lenguaje_formal {
    public static void main(String[] args)throws IOException {
BufferedReader a = new BufferedReader (new InputStreamReader(System.in));
    String b = "chin";
    String c = "chon" ;
    String d = "chan";
    String e = ";";
    String tipov;
    String signo;
    String leer = "leer";
    String Leer;
    String imprime = "imprime";
    String Imprime;
    JOptionPane.showMessageDialog(null,"LENGUAJE DE PROGRAMACION FORMAL\n\n\n"
            + "Palabra reservada para valores enteros 'chin'"
            + "\n\nPalabra reservada para valores de cadena 'chon'"
            + "\n\nPalabra reservada para valores decimales 'chan'");
    tipov = JOptionPane.showInputDialog("");
    if(b.equals(tipov)){
        String palabra;
        palabra = JOptionPane.showInputDialog(null,tipov+" ");
        signo = JOptionPane.showInputDialog(null,tipov+" "+palabra);
        if(e.equals(signo)){
        Leer= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e);
            if(leer.equals(Leer)){
            String x;
            x = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer);
            signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x);            
                if(e.equals(signo)){
                Imprime= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo);
                    if(imprime.equals(Imprime)){
                    palabra = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime);
                    signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra);
                        if(e.equals(signo)){
                        JOptionPane.showMessageDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra+""+signo+"\n\n"+x);
                        }
                    }
                }                
            }
        }
    }
    
    
    if (c.equals(tipov)){
        String palabra;
        palabra = JOptionPane.showInputDialog(null,tipov+" ");
        signo = JOptionPane.showInputDialog(null,tipov+" "+palabra);
        if(e.equals(signo)){
        Leer= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e);
            if(leer.equals(Leer)){
            String x;
            x = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer);
            signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x);            
                if(e.equals(signo)){
                Imprime= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo);
                    if(imprime.equals(Imprime)){
                    palabra = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime);
                    signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra);
                        if(e.equals(signo)){
                        JOptionPane.showMessageDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra+""+signo+"\n\n"+x);
                        }
                    }
                }                
            }
        }
    }
    
    
    if(d.equals(tipov)){
    String palabra;
        palabra = JOptionPane.showInputDialog(null,tipov+" ");
        signo = JOptionPane.showInputDialog(null,tipov+" "+palabra);
        if(e.equals(signo)){
        Leer= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e);
            if(leer.equals(Leer)){
            double x;
            x =  Double.parseDouble(JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer));
            signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x);            
                if(e.equals(signo)){
                Imprime= JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo);
                    if(imprime.equals(Imprime)){
                    palabra = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime);
                    signo = JOptionPane.showInputDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra);
                        if(e.equals(signo)){
                        JOptionPane.showMessageDialog(null,tipov+" "+palabra+""+e+"\n"+leer+" "+x+""+signo+"\n"+Imprime+" "+palabra+""+signo+"\n\n"+x);
                        }
                    }
                }                
            }
        }    
    }  
  }
}

al compilar el programa nos aparece el siguiente recuadro que nos muestra la sintaxis de las palabras reservadas de este lenguaje de programación

Introducimos la palbra reservada chin la cual pertenece a valores enteros

Damos aceptar y en seguida introducimos el nombre de una variable

Escribimos punto y coma para continuar, a continuación escribimos leer para que reconozca algun valor numerico y lo relacione a la variable val1

Damos en continuar y agregamos el valor (en este caso 23), hacemos click en Aceptar y escribimos punto y coma

Para imprimir todo en pantalla, escribimos la palabra imprime, damos aceptar escribimos el nombre de la variable (val1)

Tecleamos punto y coma y al dar Aceptar se imprimirá el numero de la variable que se guardo

martes, 28 de marzo de 2017

Construcción de analizadores sintácticos

Analizadores sintácticos
Concepto
Es la fase del analizador que se encarga de chequear el texto de entrada en base a una gramática dada. Y en caso de que el programa de entrada sea válido, suministra el árbol sintáctico que lo reconoce. En teoría, se supone que la salida del analizador sintáctico es alguna representación del árbol sintáctico que reconoce la secuencia de tokens suministrada por el analizador 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 en Castellano, determinando quien es el sujeto, predicado, el verbo y los complementos. El análisis sintáctico agrupa a los tokens en clases sintácticas (denominadas no terminales en la definición de la gramática), tales como expresiones, procedimientos, etc. El analizador sintáctico o parser obtiene un árbol sintáctico (u otra estructura equivalente) en la cual las hojas son los tokens, y cualquier nodo que no sea una hoja, representa un tipo de clase sintáctica (operaciones).

Características
• Lee componentes léxicos (tokens)
• Comprueba que el orden de estos corresponde a la sintaxis predeterminada
• Genera errores en caso de que el flujo de tokens no responda a la sintaxis
• Genera árboles de análisis sintáctico
• Se suele conocer como “Parser”
• El análisis sintáctico desarrolla el esqueleto de toda la fase de análisis
• Utiliza el analizador léxico como una rutina dentro del análisis sintáctico ( getNextToken() )
• Integra el análisis semántico como un conjunto de rutinas a ejecutar durante la comprobación de la sintaxis
• Aunque el objetivo teórico es construir un árbol de análisis sintáctico, este raramente se construye como tal, sino que las rutinas semánticas integradas van generando el árbol de sintaxis abstracta.
• El análisis sintáctico se especifica mediante una gramática libre de contexto
• El análisis sintáctico se implementa mediante un autómata de pila

Ventajas
Ventajas de los analizadores sintácticos LR Los analizadores sintácticos son construidos por tablas, similar a los analizadores sintácticos LL no recursivos. El análisis sintáctico LR es atractivo por varias razones:
Pueden construirse analizadores sintácticos LR para reconocer prácticamente todas las construcciones de lenguajes de programación para las cuales puedan escribirse gramáticas libres de contexto.
El método de análisis sintáctico LR es el método de análisis sintáctico de desplazamiento reducción sin rastreo hacia atrás más general que se conoce a la fecha.
Un AS LR puede detectar un error sintáctico tan pronto como sea posible en una exploración de izquierda a derecha en la entrada.

La clase de gramáticas que pueden analizarse mediante los métodos LR es un superconjunto propio de la clase de gramáticas que pueden analizarse con métodos predictivos o LL.

Desventajas
Su principal desventaja es que es demasiado trabajo construir un analizador sintáctico LR en forma manual para una gramática común de un lenguaje de programación. 

Aplicabilidad
Analizador de oraciones
Ayuda a mejorar la estructura y redacción de oraciones
Complemento y apoyo para la enseñanza de partes de una oración
Completo análisis de las relaciones sintácticas que se establecen entre los pares de palabras que la componen: su tipo de relación de dependencia, qué palabra es nuclear y cuál dependiente, su categoría gramatical y su posición en la frase.

*Que son las gramáticas ambiguas
Es un gramática libre del contexto para la que existe una cadena que puede tener más de una derivación a la izquierda, mientras una gramática no ambigua es una Gramática libre del contexto para la que cada cadena válida tiene una única derivación a la izquierda. Muchos lenguajes admiten tanto gramáticas ambiguas como no ambiguas, mientras otros lenguajes admiten solo gramáticas ambiguas. Cualquier lenguaje no vacío admite una gramática ambigua al tomar una gramática no ambigua e introducir una regla duplicada (el único lenguaje sin gramáticas ambiguas es el lenguaje vacío). Un lenguaje que solo admite gramáticas ambiguas se conoce como un Lenguaje Inherentemente Ambiguo, y existen lenguajes libres del contexto inherentemente ambiguos. Las gramáticas libres del contexto deterministas son siempre no-ambiguas, y son una subclase importante de GLCs no-ambiguas; existen GLCs no-deterministas y no-ambiguas simultáneamente.


*Eliminación de recursión izquierda en las gramáticas, arboles de sintaxis





lunes, 20 de febrero de 2017

Analizador Léxico, Sintáctico y Semántico

Los ordenadores son una mezcla equilibrada de Software y Hardware
Los compiladores son programas de computadora que traducen de un lenguaje a otro un lenguaje escrito en lenguaje fuente y produce un programa equivalente escrito en lenguaje objeto
Un compilador se compone internamente de varias etapas o faces que realizan operaciones lógicas y estas son:

Analizador léxico
Lee la secuencia de caracteres de izquierda a derecha del programa fuente y agrupa la secuencia de caracteres en unidades con significado propio (componentes léxicos o tokens)
Las palabras clave identificadores, operadores, constantes numéricas, signos de puntuación como separadores de sentencia, llaves, parestesias, etcétera. son diversas clasificaciones de componentes léxicos.

Actividad:
Dos conceptos de analizador léxico, ejemplo y representación de sus componentes.

Análisis léxico (Scanner)
Scanner tiene las funciones de leer el programa fuente como un archivo de caracteres y dividirlo en tokens. Los tokens son las palabras reservadas de un lenguaje, secuencia de caracteres que representa una unidad de información en el programa fuente. En cada caso un token representa un cierto patrón de caracteres que el analizador léxico reconoce, o ajusta desde el inicio de los caracteres de entrada. De tal manera es necesario generar un mecanismo computacional que nos permita identificar el patrón de transición entre los caracteres de entrada, generando tokens, que posteriormente serán clasificados. Este mecanismo es posible crearlo a partir de un tipo especifico de maquina de estados llamado autómata finito. 

Ejemplos:



Representación de un Analizador léxico
Los componentes léxicos se representan:
1.       Palabras reservadas: if, while, do, …
2.       Identificadores: variables, funciones, tipos definidos por el usuario, etiquetas, …
3.       Operadores: =, >, <, >=, <=, +, *, …
4.       Símbolos especiales: ;, ( ), { }, …
5.       Constantes numéricas. literales que representan valores enteros y flotantes.

6.       Constantes de carácter: literales que representan cadenas de caracteres. 

¿Qué es un analizador léxico?
Se encarga de buscar los componentes léxicos o palabras que componen el programa fuente, según unas reglas o patrones. La entrada del analizador léxico podemos definirla como una secuencia de caracteres.
El analizador léxico tiene que dividir la secuencia de caracteres en palabras con significado propio y después convertirlo a una secuencia de terminales desde el punto de vista del analizador sintáctico, que es la entrada del analizador sintáctico. El analizador léxico reconoce las palabras en función de una gramática regular de manera que sus NO TERMINALES se convierten en los elementos de entrada de fases posteriores.

Ejemplos:

Representación de sus componentes



Análisis sintáctico 
determina si la secuencia de componentes léxicos sigue la sintaxis del lenguaje y obtiene la estructura jerárquica del programa en forma de árbol, donde los nodos son las construcciones de alto nivel del lenguaje.
Se determina las relaciones estructurales entre los componentes léxicos esto es semejante a realizar el análisis gramatical sobre una fase en el lenguaje natural. La estructura sintáctica se define mediante las gramáticas independientes del contexto

Actividad:
Dos conceptos de analizador sintáctico, ejemplo y representación de sus componentes.


¿Qué es el analizador sintáctico?
Es la fase del analizador que se encarga de chequear el texto de entrada en base a una gramática dada. Y en caso de que el programa de entrada sea válido, suministra el árbol sintáctico que lo reconoce. En teoría, se supone que la salida del analizador sintáctico es alguna representación del árbol sintáctico que reconoce la secuencia de tokens suministrada por el analizador léxico. En la práctica, el analizador sintáctico también hace:
• Acceder a la tabla de símbolos (para hacer parte del trabajo del analizador semántico).
• Chequeo de tipos (del analizador semántico).
• Generar código intermedio.

• Generar errores cuando se producen. En definitiva, realiza casi todas las operaciones de la compilación. Este método de trabajo da lugar a los métodos de compilación dirigidos por sintaxis.


Representación de sus componentes


Análisis Semántico
El análisis semántico dota de un significado coherente a lo que hemos hecho en el análisis sintáctico.
El chequeo semántico se encarga de que los tipos que intervienen en las expresiones sean compatibles o que los parámetros reales de una función sean coherentes con los parámetros formales

Funciones principales
Identificar cada tipo de instrucción y sus componentes
Completar la Tabla de Símbolos
Realizar distintas comprobaciones y validaciones:
Comprobaciones de tipos.
Comprobaciones del flujo de control.
Comprobaciones de unicidad.

Comprobaciones de emparejamiento.

Actividad:
Concepto de analizador semántico, ejemplo y representación de sus componentes.

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

Ejemplo

Representación de sus componentes
.

miércoles, 8 de febrero de 2017

Tarea

Diseño compilador
El compilador traduce el código escrito en un idioma a otro idioma si cambiar el sentido del programa. También está previsto que un compilador debe hacer el código de destino, eficaz y optimizado en términos de tiempo y espacio, debe ser capaz de ejecutar una traducción básica detectar errores, recuperarse de errores.
Un compilador debe incluir un analizador léxico una definición de sintaxis y un analizador semántico que puede ser el front end, así como la generación de código y optimización de la misma.

Crear un programa que se declare como variables c1 c1 c3… cn (según mi nombre es el numero de variables) imprimir el nombre concatenado

Codigo
#include <iostream>
using namespace std;
int main() {
string  d="D",a="a",n="n",i="i",e="e",l="l";
cout << "Hola: "<<d+a+n+i+e+l <<endl;
system ("PAUSE");

}



Tarea
Preguntar al usuario cuantos caracteres son de su nombre e imprimir

#include <iostream>
using namespace std;

int nc,i,j,op;
char a[20];
int main (){
cout << "Ingresa el numero de caracteres: ";
cin >>nc;
for (i=1;i<nc+1;i++){
cout<< "ingresa el valor: ["<<i<<"]: ";
cin >>a[i];
}
cout <<"Cuantos caracteres deseas imprimir: ";
cin>> op;
for (j=i;j<op+1;j++){
cout<<a[j];
}

cout <<"Hola "<<a<<endl;
system ("PAUSE");

}

Compiladores en Linux (C/C++)

Instalar un compilador y crear un programa en Linux

Para esta práctica se instalara un compilador de C y C++ en alguna distribución de Linux

Después de hacer varias investigar sobre las distribuciones más estables para instalar compiladores se tiene como opciones Ubuntu 16, Fedora 25, y Lubuntu 14 (parecida a Ubuntu, tiene el gestor LXDE, idela para equipos antiguos con recursos limitados, muy ligero pero contiene todos los ficheros y paquetes actuales)
Además se instalara CodeBlocks o CodeLite que son los compiladores de C y C++ para distribuciones de Linux

Ubuntu 16

No se obtuvo éxito para poder instalar correctamente alguno de los dos programas

Fedora 25
Se logro instalar CodeBlocks en esta distribución de Linux


Abrimos el programa

Nos muestra esta mensaje de alerta indicandos que hubo un error durante la instalación del compilador

Aunque nos permite crear el archivo y pareciera ser que se puede ejecutar el programa nos es así, ya que no se tiene habilitado el panel de ejecución o compilación

Se investigo en diversas fuentes, paginas de internet, foros, libros, vídeos tutoriales y debido a que se esta utilizando una maquina virtual no permite la instalación de algún fichero que requiere el programa


Lubuntu 14
Para esta distribucion de Linux se lograron instalar los dos programas como se muestra a continuación:

Primero con CodeLite, el programa se instalo desde el Centro de Instalación de Software 

Al igual que como ocurrió con Fedora 25 no se pudo crear ningún proyecto ya que no se obtuvo la instalación completa, falto algún fichero le cual la maquina virtual no permitió instalar


Luego de investigar en distintos foros y paginas de internet, se encontró el post de una persona la cual argumentaba tenia un problema similar al momento de usar una maquina virtual en su ordenador, afortunadamente compartió los comandos que se deben de ingresar en la terminal.

Es necesario añadir los siguientes repositorios y ficheros para que el programa trabaje correctamente 
sudo apt-add-repository ppa:pasgui/ppa 

sudo apt-get update && sudo apt-get install codeblocks codeblocks-contrib 



A continuación necesitaremos instalar el compilador
sudo apt-get install build-essential 



gcc y g++:También puede optar por instalar los compiladores para C/C++ de forma individual o combinada: 
C: 
sudo apt-get install gcc 



C++: 
sudo apt-get install g++ 



Ambos: 
sudo apt-get install gcc g++ 


Para instalar la documentación necesaria para el desarrollo de aplicaciones C/C++ hacemos lo siguiente: 
sudo apt-add-repository ppa:p12/ppa 
sudo apt-get update && sudo apt-get install devhelp cppreference-doc-en 


Para finalizar abrimos el programa

Creamos un nuevo proyecto (debe seleccionarse la opción "Console Application")

Seleccionamos el tipo de lenguaje a emplear

Asignamos el nombre al proyecto

En esta parte de la creación del proyecto se deja tal cual no se tiene que modificar alguno de los formularios

Nuestro proyecto aparecerá del lado izquierdo del programa expandimos todas las pestañas y abrimos el archivo main.cpp que es donde programaremos

Una vez creado el programa lo compilamos y ejecutamos

  
Se pudo haber utilizado solo la terminal de alguna de las distribuciones de Linux, instalar solo el fichero de gcc o g++ los cuales nos permiten compilar en los leguajes C y C++, pero en realidad el programar, compilar y ejecutar todo desde terminal no hubiese aportado mucho a la práctica

martes, 7 de febrero de 2017

Unidad 1

Unidad 1 Arquitectura de los Compiladores e Intérpretes

Unidad de competencia: determina la estructura general de los compiladores e intérpretes con base en la funcionalidad de sus etapas y faces

Definición de compiladores e intérpretes
Concepto:
Compilador
Un traductor es cualquier programa que toma un texto escrito en un lenguaje y da como salida en otro lenguaje, Los compiladores son programas de computadora que traducen de un lenguaje a otro. Un compilador toma como su entrada un programa escrito en lenguaje fuente y produce un programa equivalente escrito en lenguaje objeto.

Interpretes
Ejecutan las instrucciones del programa según se vallan presentando. Necesitan menos memoria, pero son más lentos que los compiladores (LISP, Prolog). Históricamente, se pusieron de moda en los primeros años porque los recursos de memoria eran escasos. Permiten añadir código dinámicamente durante la ejecución.

Características:
Compiladores
Se compila una vez, se ejecuta n-veces
En bucles, la compilación genera código equivalente al bucle pero un intérprete se traduce tantas veces una línea como veces se repite el bucle
El compilador tiene una visión global del programa, por lo que la información de mensajes de errores es más detallada.
Front End: parte que analiza el código fuente, comprueba su validez, genera el árbol de derivación y rellena los valores de la tabla de símbolos. Parte que suele ser independiente de la plataforma o sistema operativo para el que funcionará.
Back End: parte en donde se genera el código máquina exclusivo para una plataforma a partir de lo analizado en el front end.

Interprete
Un intérprete necesita menos memoria que un compilador

Permite una mayor interactividad con el código en tiempo de desarrollo. Son más sencillos de implementar. Lo cual facilita el estudio de la corrección del intérprete y proporciona nuevas líneas de investigación como la generación automática de intérpretes a partir de las especificaciones semánticas del lenguaje. Proporcionan una mayor flexibilidad que permite modificar y ampliar características del lenguaje fuente. No es necesario contener en memoria todo el código fuente. Esto permite su utilización en sistemas de poca memoria o en entornos de red, en los que se puede obtener el código fuente a medida que se necesita [Plezbert 97]. Facilitan la meta-programación. Un programa puede manipular su propio código fuente a medida que se ejecuta. Esto facilita la implementación de sistemas de aprendizaje automatizado y reflectividad [Aït Kaci 91]. Aumentan la portabilidad del lenguaje: Para que el lenguaje interpretado funcione en otra máquina sólo es necesario que su intérprete funcione en dicha máquina.

Aplicabilidad:


Ejemplos:




Arquitectura de los compiladores e intérpretes
Concepto:
Un compilador contiene varios modulos que transforman, refinan y envıan información. Toda la informacion debe pasar por todos los modulos
Hay dos opciones:
1. Procesar la informacion en partes pequenas (compilador estrecho)
2. Procesar todo el programa (compilador amplio)

Características:
Se leen “pocos” tokens del programa y se producen pocos bytes de codigo (de ser posible
Se desecha casi toda la informacion acerca de los tokens leıdos
Requiere poca memoria (no depende del tamano del programa) pero es m´as lento
Casi todos los compiladores “reales” son de este tipo con componentes amplias (un compilador de C, puede procesar por rutina)
Puede requerir varias pasadas (lecturas del programa fuente) para compilar.
Se aplica cada modulo secuencialmente a todo el programa
Requiere una cantidad de memoria proporcional al tamano del programa

Aplicabilidad:
Se aplica cada modulo secuencialmente a todo el programa
Son mas “sencillos” desde un punto de vista teorico, educativo y de diseño

Ejemplos:




Máquinas virtuales
Concepto:
En informática una máquina virtual es un software que emula a un ordenador y puede ejecutar programas como si fuese un ordenador real. Este software en un principio fue definido como "un duplicado eficiente y aislado de una máquina física". La acepción del término actualmente incluye a máquinas virtuales que no tienen ninguna equivalencia directa con ningún hardware real.

Características:
Una característica esencial de las máquinas virtuales es que los procesos que ejecutan están limitados por los recursos y abstracciones proporcionados por ellas. Estos procesos no pueden escaparse del computador o máquina virtual

Aplicabilidad:
Uno de los usos domésticos más extendidos de las máquinas virtuales es ejecutar sistemas operativos para "probarlos". De esta forma podemos ejecutar un sistema operativo que queramos probar (Linux, por ejemplo) desde nuestro sistema operativo habitual (Windows por ejemplo) sin necesidad de instalarlo directamente en nuestro ordenador y sin miedo a que se desconfigure el sistema operativo primario.

Ejemplos:
VMware Software propietario, muy maduro


Virtual PC Software propietario, algunas versiones son freeware