sábado, enero 14, 2006

Codigo Fuente
Si deseas el codigo fuente manda tu correo a: Lrch_Fox3@yahoo.com ó Lrch_Fox2003@hotmail.com, para poder compartirte el archivo del codigo fuente desde www.web-a-file.com.

domingo, diciembre 04, 2005

Código Intermedio

Código Intermedio

Para generar el código intermedio se cuenta con una clase que simula una tabla (la tabla es guardada en memoria). La tabla esta estructurada con los siguientes elementos: Operador, Argumento1, Argumento2 y Resultado (cada elemento es del tipo ArrayList), al recorrer la gramática en la tabla se van almacenando información (esta información es manejada de acuerdo a los estándares del programador) que después será utilizada para generar el código Mips,
X=2+5
Oper: “:=#” -- Arg1:”2” -- Arg2:”” -- Resol:”$t0”
Oper: “:=#” -- Arg1:”5” -- Arg2:”” -- Resol:”$t1”
Oper: “operplus” -- Arg1:”$t0” -- Arg2:”$t1” -- Resol:”$t2”

Hasta el momento el código intermedio funciona para realizar traducciones de Código Mips para sumas, multiplicaciones, divisiones, restas, leer entero, escribir string, escribir entero, asignaciones, llamar funciones o procedimientos, pasar parámetros, detectar si existen arreglos (entero o char).

Preguntas sobre el proyecto de compiladores

1 pregunta:
program ejemplo();
     var x,y : integer;
     function suma(n,m:integer):integer;
          begin     
         x := 5; //Asigno 5 a x
               suma:=n+m
          end;
begin
     y:=suma(5,5);
     writeint( x )  // debería imprimir 5
     writeint( y )  // debería imprimir 10
end.

Cómo hago para guardar el valor 5 en la variable x, la cual es global.
En MIPS x esta representada como:
x: .word 0 ( el valor de x es 0, pero yo quiero saber como guardar el valor 5 cuando se le asigna a x, y ya el valor de x no seria 0 sino que 5. Esto debería pasar también con la variable y (debería almacenar la suma – 10)

2 pregunta:
Con la instrucción readchar, como hacer para leer el carácter.

#---------- Leer número ----------
addi $v0, $zero, 5
syscall
add $s0, $v0, $zero # $s0 almacena el numero

#---------- ¿Leer char? ----------

3 pregunta:
Con la instrucción writechar, como hacer para escribir el carácter.

#---------- Escribir número ----------
addi $v0, $zero, 1
add $a0, $zero, $t0
syscall

#---------- ¿Escribir char? ----------

domingo, noviembre 27, 2005

Operador Ellipsis

Operador Ellipsis

#include <cstdlib>
#include <iostream>
#include <stdarg.h>
using namespace std;

int sumavar(int , ... );
int main(int argc, char *argv[]) {
     cout<<"La suma es: "<<sumavar(9,1,2,3,4,5,6,7,8,9)<<endl;
    system("PAUSE");
    return 0;
}
int sumavar(int size, ...) {
     va_list ap;    
     int *tmp = 0,r=0;
     va_start(ap, size);
     for (int i=0; i<size;i++){
           tmp = va_arg(ap, int *);
           r=r+(int)tmp;  
     }
    va_end(ap);    
    return r;
}

Nota: el primer parámetro que se manda es la cantidad de parámetros variables que serán sumados, ya que si no envía este parámetro empieza a obtener datos basuras del stack que maneja C/C++, este stack es manejado mediante la librería “stdarg.h”

Convenciones de llamada de las arquitecturas MIPS e Intel
Invocación C
Esta opción indica al compilador utilizar la secuencia de llamada estándar C para funciones, es decir: Generar guiones de subrayado -guiones bajos-; distinguir mayúsculas de minúsculas (no transformar minúsculas en mayúsculas); pasar parámetros de derecha a izquierda.
Las funciones que utilizan esta convención de llamada pueden aceptar una lista variable de parámetros (su número no tiene que ser fijo) y utilizan la pila para el paso de argumentos.  La función que realiza la llamada es la encargada de limpiar la pila, lo que provoca que el código de este tipo de ejecutables sean ligeramente mayores que en el resto de las convenciones, en las que es la función invocada la que limpia la pila.
Invocación Pascal
Esta opción indica al compilador utilizar la secuencia de llamada de Pascal para las funciones (no generar guiones de subrayado, forzar identificadores a mayúsculas, limpieza de la pila por la función que realiza la llamada y paso de parámetros de izquierda a derecha).
Generalmente las llamadas de función resultantes son más pequeñas y rápidas que las generadas con la convención C, y también utilizan la pila para el paso de parámetros.  En este caso las funciones deben pasar el número exacto de argumentos y del tipo adecuado.  Los identificadores de las funciones declaradas con este modificador están sujetos al planchado de nombres

domingo, noviembre 20, 2005

Mejoras en la Interfaz Grafica

Mejoras en la Interfaz gráfica

Todas la palabras claves del lenguaje pascal (procedure, var, function, etc) se distinguen de lo demás mediante color, así sucede también con los números, caracteres, cadenas de string.
También la interfaz cuenta con una opción de poder realizar búsqueda de palabras, si la encuentra será remarcada mediante un color.

Además, cuando sucede un error el carrete del cursor se ubica en la posición del error.







Chequeo de Tipos

Chequeo de Tipos

  1. Verifica que una expresión sea del mismo tipo de la variable a la que es asignada, {x:=4+5 --> integer:=integer}. Esta verificación es valida para todo tipo de combinación de expresiones (números, caracteres, String, variables)

  1. Verifica que cuando una función o un procedimiento es llamado y este tiene parámetros, se verifica la cantidad de parámetros, el cual debe corresponder a la cantidad de parámetros cuando la función o procedimiento fue declarado. Además, verifica si la función o procedimiento en su declaración no tiene parámetros y al ser llamados se le asignaron parámetros.

  1. Chequea el tipo de los parámetros, los parámetros que se asignaron al ser llamada la función o procedimiento debe ser igual al tipo de parámetros cuando la función o procedimiento fue definida.

  1. Verifica que un procedimiento no pueda ser asignado a una variable.

  1. Con respecto a los operadores, verifica que todos los elementos sean del mismo tipo. {5+x*6, todos son del tipo integer, en caso contrario es error }

  1. Se verifica que cuando se define un arreglo, el rango siempre debe ser del tipo integer {c[1] ó c[x], 1 y x son del tipo integer }

Nota: las cadenas de string no son aceptado como parámetros, solamente parámetros de tipo integer ó char.

domingo, noviembre 13, 2005

Atributos Heredados

Atributos Heredados en CUP

En CUP los atributos heredados solo pueden ser simulados, es decir declarando variables (Objetos, clases, etc.) en la parte de declaración de usuario de CUP, y utilizar estas variables (como atributos heredados simulados) para almacenar la información y poder ser utilizada de acuerdo a la definición de Atributo Heredado. Por lo investigado en Internet, esta fue la mejor manera; es posible que internamente CUP hago utilidad de atributos heredados, pero no estoy seguro.

domingo, noviembre 06, 2005

Ejercicios 6.3 y 6.5 (Libro Aho)

Ejercicios 6.3 y 6.5 (Libro Aho)

6.3)      P ( D ; E
     D ( D1 ; D2
     D ( id : T { añadetipo(id.entrada,T.tipo) }
     T ( char { T.tipo := char }
     T ( integer { T.tipo := integer }
     T ( list of T1 { T.tipo := agregarLista(T1.tipo) }
     E ( literal { E.tipo := char }
     E ( num { E.tipo := integer }
     E ( id { E.tipo := buscar(id.entrada) }
     E ( ( L ) { E.tipo := L.tipo }     
     L ( E , L1 { L.tipo := if E.tipo=integer and L1=integer then integer
                                  else if E.tipo=char and L1=char then char
                    else error_tipo()  }
     L ( E { L.tipo := E.tipo }

6.5)
  1. c: char; i:integer;
     c mod i mod 3

     P( D ; E
     D( D ; D
     D( id : T { añadetipo(id.entrada,T.tipo) }
     E ( E1 mod L { E.tipo := if E1.tipo=integer and L.tipo=integer then integer
                      else error_tipo() }
     E( literal { E.tipo := char }
     E ( num { E.tipo := integer }
     E ( id { E.tipo := buscar(id.entrada) }
     L( E1 mod E2 { L.tipo := if E1.tipo=integer and E2.tipo=integer then integer
                      else error_tipo()  }
     T ( char { T.tipo := char }
     T ( integer { T.tipo := integer }

  1. P: ↑integer; a:array[10] of integer;
     a[↑p]

     P( D ; E
     D( D ; D
     D( id : T { añadetipo(id.entrada,T.tipo) }
     E ( num { E.tipo := integer }
     E ( id { E.tipo := buscar(id.entrada) }
     E ( E1 [ E2 ] { E.tipo := if E2.tipo =integer and E1.tipo=array(s,t) then t
                                      else error_tipo() }
     E ( E1↑ { E.tipo := if E.tipo=pointer(t) then t
                               else error_tipo() }
     T ( integer { T.tipo := integer }
     T ( ↑T1 { T.tipo := pointer(T1.tipo) }
     T ( array [ num ] of T1{ T.tipo:= array(1..num.value, T1.tipo) }





  1. f:integer ( boolean;
     i;integer; j:integer; k:ineger;
     while f(i) do
          k := i;
          i := j mod i;
          j := k

P( G ; D ; E
     G( id : T ( T { añadetipo(id.entrada,T.tipo) }
     D( D ; D
     D( id : T { añadetipo(id.entrada,T.tipo) }
     E( while E1 ( E2 ) S { E.tipo := if E2=integer then true                         
                          else false }
     E ( num { E.tipo := integer }
     E ( boolean { E.tipo := boolean }
     E ( id { E.tipo := buscar(id.entrada) }
     E ( E1 mod E2 { E.tipo := if E1.tipo=integer and E2.tipo=integer then integer
                      else error_tipo() }
     S( S ; S
     S( id := E
     T ( char { T.tipo := char }
     T ( integer { T.tipo := integer }
     T ( boolean { T.tipo :=  boolean }


domingo, octubre 30, 2005

Ejemplo Generar Código Spim

Ejemplo Generar Código Spim

Utilizando gramáticas (cup) para realizar cálculos matemáticos (suma, resta, multiplicación, división) hemos de generar código que se pueda ejecutar en Spim (este código se almacena en un archivo compatible con el emulador Spim).
Primero construí una clase que me maneja los registros ($t0...$t9) que serán utilizados en Spim, luego dentro de la gramática y verificando que operación se este realizando se convierte la operación matemática en código Spim.

Ej.: si se esta verificando la expresión “2+5”, en código Spim seria “add $t0, $t1, $t2”, donde “$t0” guarda la suma de los dos números y “$t1, $t2” son los números respectivamente.

El manejador de registros cuanta con funciones tales como: obtener un registro libre y el de liberar una lista de registros. Para saber si existe disponible un registro la clase cuanta con dos estructuras (ArrayList), una estructura que mantiene un valor booleano (false indicando que esta disponible, true indicando que esta no disponible), la otra estructura mantiene la lista de registros ($t0...$t9). Al final si todo resulto bien obtendremos un archivo con el código que fue generado por la gramática el cual podremos ejecutar en Spim.

Nota: cuando liberamos registros se le manda un parámetro, el cual es un ArrayList. Este mantendrá los registros que han sido utilizados hasta el momento.

public class ClsRegistros {
    private ArrayList Free = new ArrayList();
    private ArrayList Reg = new ArrayList();
    
    public ClsRegistros() { }
    
    public void initReg() {
        Free.clear(); Reg.clear();
        for (int i=0;i<10;i++){
           Free.add( String.valueOf(false) );
           Reg.add("$t"+i);
        }        
    }    
    public String getFreeReg(){
        String freeReg="";
        for (int i=0;i<10;i++){
            if ( !Boolean.valueOf( Free.get(i).toString() ).booleanValue() ) {
                Free.set(i, String.valueOf(true));
                freeReg = Reg.get(i).toString();
                break;
            }
        }
        if ( freeReg=="" ) { System.out.println("No hay registros disponibles.");}
        return freeReg;
    }

    public void setFreeReg( ArrayList regs ) {
        for (int i=0;i<regs.size();i++) {
            int index = Reg.indexOf(regs.get(i));
            Free.set(index, String.valueOf(false));
        }
    }    
}