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));
        }
    }    
}

sábado, octubre 22, 2005

Laboratorio SPIM

Laboratorio SPIM

Para realizar la modificación de poder multiplicar los dos números ingresados, se debe aplicar lo siguiente:

mul $s2,$s0,$s1

En donde, $s2 guarda el resultado de la multiplicación y $s0 y $s1 guarda los números ingresados por el usuario.

Para verificar que numero es menor de los dos, se hace la utilización de la siguiente instrucción:

blt $s0, $s1, menor
add $s2,$zero,$s1
b endif
menor: add $s2,$zero,$s0
endif:

La instrucción blt hace la comparación $s0<$s1, si la cumple nos movemos a la etiqueta “menor”  en donde guardamos el valor del primer numero indicando que ese fue el menor, para luego mandarlo a imprimir. En caso contrario no nos movemos a la etiqueta y guardamos el segundo número indicando que ese es el menor, luego nos movemos a la etiqueta “endif” la cual continúa con el programa

domingo, octubre 16, 2005

Telecomunicaciones

Esta carrera me llama mucho la atención ya que se relaciona en el modelado, simulación y análisis de sistemas de comunicaciones. Así también como el diseño, construcción, operación y mantenimiento de redes de comunicaciones. Me parece muy conveniente esta carrera ya que con la base de Ingeniería de Sistema puedo relacionar y llegar a aprender a diseñar, desarrollar e implementar programas de comunicación que yo mismo podría construir. Y lo que es realmente extraordinario como desarrollar interfases para acoplar equipos de radio con equipos de cómputo y sistemas telefónicos, por Ej.: me llamo la atención una herramienta muy utilizada que es el MSN Messenger, tengo una amiga que vive en Japón, platico bastante con ella, pero lo increíble es la rapidez con que los mensajes se trasmiten, es casi nula la diferencia de cómo estar platicando con alguien de mi mismo país, así como poder al mismo tiempo enviar video, sonido y transmisión de data, me gustaría mucho entender el funcionamiento que existe detrás de todo eso y de muchas otras cosas mas (la parte de software y la parte de hardware).

El campo de trabajo actual y potencial del ingeniero en telecomunicaciones es muy amplio e incluye, entre otras, las siguientes áreas: sistemas telefónicos, redes digitales de servicios integrados, sistemas satelitales, radio y microondas, redes de área local y expandida, sistemas basados en fibra óptica, redes de computadoras y de teleinformática, sistemas de transmisión analógica, digital, satelital y áreas de radiocomunicación.

Campo Laboral

El Técnico en Telecomunicaciones puede prestar servicios en empresas de telecomunicaciones, de computación, de transmisión de datos y todo tipo de empresas de comunicaciones tanto de las áreas del sector privado como público. En sí, en cualquier área que requiera de los servicios de un especialista en sistema de telecomunicaciones.

En fin me parece una interesante carrera en donde puedo extender mis conocimientos y así como también aplicar mis conocimientos con el fin de llegar a un nivel de vida social adecuado.

domingo, septiembre 25, 2005

Algunas Verificaciones Sintácticas

Parámetros: para limitar que los procedimientos o funciones solo tenga al menos 4 parámetros, se maneja el atributo “Parámetro” en la tabla de símbolos que es de tipo booleano (si el valor esta en verdadero indica que es parámetro, en caso contrario no es parámetro). Además en la tabla se agrego el atributo “Ámbito” el cual guarda el nombre del área de declaración (ya sea global, función o procedimiento). La búsqueda de la cantidad de parámetros se realiza mediante los atributos “Ámbito, Expresión (ó variables) y Parámetro”, se captura todas las expresiones de un ámbito y luego por medio de un contador se va aumentado si el parámetro es verdadero. Al final si el contador es mayor que 4 se despliega un mensaje de error, esta operación se realiza hasta recorrer todas las expresiones de los ámbitos.

Duplicados globales: Como ya se tiene almacenados toda la información (expresión, tipo, ámbito, línea, columna, parámetro, lexema) de las variables en la tabla de símbolos, primero se capturan todas la variables globales y después se hace una búsqueda en las variables locales, si se encuentra una variable local declarada igual a una variable global, el programa despliega un mensaje de error.

Verificación local: se despliega error si alguno de los parámetros tiene el mismo nombre que su función o procedimiento padre. También verifica que no se declaran variables con el mismo nombre que su función o procedimiento padre. Para ambos casos se despliega un mensaje de error.

Verificación de Tipos: esta verificación se realiza dentro del parser, cuando el parser llega a la gramática en donde se realizan las asignaciones (variable:=valor), primero tomo la información (texto, línea, columna) de la variable y la información del valor, segundo la tabla de símbolos cuanta con una función (sus parámetros son una expresión y el ámbito de la expresión) que retorna el tipo de la expresión (ó variable ó valor). Como ya tenemos el tipo de la variable y del valor ahora se verifican los siguientes casos:
  1. El valor es un Entero (variable:=12), este debe cumplir que la variable sea también de tipo entero.

  2. El valor es un carácter (variable:=”c”), este debe cumplir que la variable sea también de tipo carácter.

  3. El valor es un String (variable:=’hola’), no se pueden aplicar Strings a variables de tipo entero o carácter.

  4. Si retorna que el valor no tiene tipo es porque se esta aplicando una asignación a un procedimiento.

  5. El caso en donde los dos son identificadores (el valor puede ser un identificador simple o un a función) , simplemente se hace una comparación de los tipos, si no coinciden se despliega un error

  6. Nota: en este momento no se esta verificando el tipo de asignaciones complejas (x:=a+b)

domingo, septiembre 18, 2005

Tabla de Smbolos

Clase que mantiene los tokens que se son leídos durante la compilación, hasta el momento solamente por el analizador léxico (solo por prueba), esto no debería ser así, si no cuando se ejecute el parser empezar a ingresar.

package TurboDragon;
import java_cup.runtime.*;
import java.util.*;

public class ClsTablaSimbolos {
private ArrayList Linea = new ArrayList();
private ArrayList Columna = new ArrayList();
private ArrayList Lexema = new ArrayList();
private ArrayList Expresion = new ArrayList();
public ClsTablaSimbolos() { }

public void AddSymbol( ClsObjectToken objectToken ) {
this.Expresion.add( objectToken.GetExpresion() );
this.Lexema.add( objectToken.GetLexema() );
this.Linea.add( objectToken.GetLinea() );
this.Columna.add( objectToken.GetColumna() );
}

public void DelSymbol( int index ) {
this.Expresion.remove(index);
this.Lexema.remove(index);
this.Linea.remove(index);
this.Columna.remove(index);
}

public void ClearTable() {
this.Expresion.clear();
this.Lexema.clear();
this.Linea.clear();
this.Columna.clear();
}

public boolean ExistSymbol( Object expresion ){
return this.Expresion.contains(expresion);
}

public int FindSymbol( Object expresion ){
return this.Expresion.indexOf(expresion);
}

public int SizeTable(){
return this.Expresion.size();
}

public ClsObjectToken GetSymbol( int index ) {
return new ClsObjectToken( this.Expresion.get(index), this.Lexema.get(index), this.Linea.get(index), this.Columna.get(index) );
}
}

La clase ClsObjectToken es la que mantiene los atributos del token, como ser la expresión, el lexema o al tipo que pertenece, la línea y la posición del token.

domingo, septiembre 04, 2005

Comentarios Abiertos

Comentarios Abiertos sin Cerrar

Para resolver este problema utiliza la ayuda de una clase “ClsComments”, la cual lleva un control sobre los comentarios que han sido abiertos y cerrados, cada vez que se abre un comentario la clase cuenta con una ArrayList que guarda tipos boléanos (inicialmente esta con el valor falso) y cambia a valor verdadero cuando encuentra que se cerro el comentario, al terminar de leer el archivo (Fin de Archivo), se recorre el ArrayList y si encuentra con un comentario con valor falso, retorna un mensaje de error. Esta clase funciona dentro del lexer, cada vez que encuentre el estado de comentario la clase empieza a llevar el control de los comentario (Encontró Comentario Abierto, valor es igual a falso, este valor cambiara hasta que encuentre el comentario cerrado). Se implemento un ArrayList ya que cada vez que se encuentra un comentario abierto se crea un Objeto (que guarda la línea, la posición y el valor booleano).

public class ClsComments {
    private ArrayList Linea = new ArrayList();
    private ArrayList Columna = new ArrayList();    
    private ArrayList FinComments = new ArrayList();    
    
    public ClsComments() { }

    public void NewComment(int Row, int Col ) {
        Linea.add( String.valueOf(Row) );
        Columna.add( String.valueOf(Col) );
    }

    public void FinComentario( boolean Value ) {
        FinComments.add( String.valueOf(Value) );        
    }

    public int getLinea( int index ){      
        int value=0;
        try {
            value = Integer.valueOf( Linea.get(index).toString() ).intValue();            
        } catch(Exception e) {}
        return value;
    }

    public int getColumna( int index ) {
        int value = 0;
        try {
            value = Integer.valueOf( Columna.get(index).toString() ).intValue();            
        } catch(Exception e) {}        
        return value;
    }

    public boolean getFinComentario(int index) {
        boolean value=false;
        try {
            value = Boolean.valueOf( FinComments.get(index).toString() ).booleanValue();            
        } catch(Exception e) {}        
        return  value;
    }  

    public void newFinComentario( int index, boolean Value ) {
        FinComments.set(index,String.valueOf(Value) );
    }

    public int Len() {
        return Linea.size();
    }

    public void Limpiar() {
        Linea.clear();
        Columna.clear();
        FinComments.clear();
    }

}

domingo, agosto 28, 2005

Informe Avance Proyecto # 1 (Parte 2)

Puntos alcanzados del proyecto:


  • Verificación de comentarios tipo:”{ … }”

//-- Comentario Sin Abrir "}"
<YYINITIAL> {TK_COMENTARIOCERRADO_1}* {
ClsErrores Handler = new ClsErrores();
Handler.Error( 2, yyline, yychar );
}
//-- Comentario Sin Abrir "*)"
<YYINITIAL> {TK_COMENTARIOCERRADO_2}* {
ClsErrores Handler = new ClsErrores();
Handler.Error( 2, yyline, yychar );
}
//-- Verifica el tipo de comentario "{ ... }"
<YYINITIAL> {TK_COMENTARIOABIERTO_1} { yybegin(COMMENTS1); }
<COMMENTS1> [^({TK_COMENTARIOABIERTO_2TK_COMENTARIOCERRADO_2})] { /**/ }
<COMMENTS1> {TK_COMENTARIOCERRADO_1} { yybegin(YYINITIAL); }
//-- Si dentro de un comentario "{ ... }" se encuentra "(*" se toma como comentario anidado
<COMMENTS1> {TK_COMENTARIOABIERTO_2}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}
//-- Si dentro de un comentario "{ ... }" se encuentra "*)" se toma como comentario anidado
<COMMENTS1> {TK_COMENTARIOCERRADO_2}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}
//-- Si dentro de un comentario "{ ... }" se encuentra "{" se toma como comentario anidado
<COMMENTS1> {TK_COMENTARIOABIERTO_1}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}


  • Verificación de comentarios tipo:”(* … *)”

//-- Verifica el tipo de comentario "(* ... *)"
<YYINITIAL> {TK_COMENTARIOABIERTO_2} { yybegin(COMMENTS2); }
<COMMENTS2> [^({}TK_COMENTARIOABIERTO_2TK_COMENTARIOCERRADO_2)] { /**/ }
<COMMENTS2> {TK_COMENTARIOCERRADO_2} { yybegin(YYINITIAL); }
//-- Si dentro de un comentario "(* ... *)" se encuentra "{" se toma como comentario anidado
<COMMENTS2> {TK_COMENTARIOABIERTO_1}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}

//-- Si dentro de un comentario "(* ... )*" se encuentra "}" se toma como comentario anidado
<COMMENTS2> {TK_COMENTARIOCERRADO_1}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}

//-- Si dentro de un comentario "(* ... )*" se encuentra ")*" se toma como comentario anidado
<COMMENTS2> {TK_COMENTARIOABIERTO_2}* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 1, yyline, yychar );
}

Nota: en la verificación de comentarios no se ha definido cuando el comentario es abierto, pero no se ha cerrado, ¿Alguna sugerencia?



Informe Avance Proyeto #1 (Parte 1)

Puntos Alcanzados del proyecto:

  • Validar el tamaño de declaración de un Identificador

<YYINITIAL> {IDENTIFICADOR} {
int Len = yytext().length();
if (Len>12) {
ClsErrores Handler = new ClsErrores();
Handler.Error( 10, yyline, yychar );
}
else {
return new Symbol( sym.IDENTIFICADOR, new TokenValue( yytext(), yyline, yychar ) );
}
}

  • Validar Strings

//-- Definicion para identificar cadenas de String
<YYINITIAL> {TK_APOSTROFE} { yybegin(STRING); }
<STRING>[^(\n'{}TK_COMENTARIOABIERTO_2TK_COMNETARIOCERRADO_2TK_APOSTROFE_2)] { string.append( yytext() ); }
<STRING> {TK_APOSTROFE} {
yybegin(YYINITIAL);
int Len = string.length();
if (Len>255) {
ClsErrores Handler = new ClsErrores();
Handler.Error( 5, yyline, yychar );
}
else {
return new Symbol( sym.STRINGCONST, new TokenValue( string.toString(), yyline, yychar ) );
}
}
<STRING> {TK_APOSTROFE_2} { string.append( "\'" ); }
<STRING> [{] { string.append( "{" ); }
<STRING> [}] { string.append( "}" ); }
<STRING> {TK_COMENTARIOABIERTO_2} { string.append( "(*" ); }
<STRING> {TK_COMENTARIOCERRADO_2} { string.append( "*)" ); }
//-- Si encuentra un salto de linea se determina como cadena invalida
<STRING> [\n] {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 6, yyline, yychar );
}

  • Validar Carácter

//-- Definicion para identificar caracter
<YYINITIAL> {TK_COMILLA} { yybegin(CARACTER); }
<CARACTER> [^(\n\")] { caracter.append( yytext() ); }
<CARACTER> {TK_COMILLA} {
yybegin(YYINITIAL);
int Len = caracter.length();
System.out.println(caracter.toString());
if (Len==0) {
ClsErrores Handler = new ClsErrores();
Handler.Error( 8, yyline, yychar );
}
else if (Len>1) {
ClsErrores Handler = new ClsErrores();
Handler.Error( 7, yyline, yychar );
}
else {
return new Symbol( sym.CHARCONST, new TokenValue( caracter.toString(), yyline, yychar ) );
}
}

  • Validar Número

<YYINITIAL> {NUMERO} {
Integer Numero = new Integer( yytext() );
int Num = Numero.intValue();
if (Num<-65536 Num>65536){
ClsErrores Handler = new ClsErrores();
Handler.Error( 4, yyline, yychar );
}
else {
return new Symbol( sym.NUMERO, new TokenValue( yytext(), yyline, yychar ) );
}
}

  • Validar Números que empiecen con 0 amenos que sea el valor cero.

//-- Validacion para el token Número (no debe comenzar con cero a menos que sea el valor cero)
<YYINITIAL> [0]+[0-9]* {
yybegin(YYINITIAL);
ClsErrores Handler = new ClsErrores();
Handler.Error( 9, yyline, yychar );
}

domingo, agosto 21, 2005

Interfaz gráfica & Lexer
El ambiente grafica consta de tres áreas:
  1. Menú: esta formado por el menú “opciones” y “Ayuda”. El menú “Opciones” presenta las opciones de poder cargar un archivo ya sea un programa de pascal o un archivo de texto. Además, presenta la opción de poder compilar el archivo cargado (cada vez que se compile se guardara el archivo y se ejecutara el Lexer y el Parser) y por ultimo se cuenta con la opción de salir del programa. El menú “Ayuda” brinda información sobre el programa y sobre su desarrollador.
  2. Editor de Texto: es en donde se podrá editar código pascal este presentara en el lado izquierdo presentara la línea de código, en la parte inferior derecha presentara la columna en donde se encuentra actualmente y en la parte superior del editor se muestra la dirección del programa actualmente editando.
  3. Mensajes de Error: es la parte en donde se muestra la serie de problemas que se encontraron al momento de compilar el programa, aquí se muestra el tipo de error y la posición en donde se encuentra.

    Lexer: es la fase en donde se identifican si las palabras reservadas del lenguaje, identificadores, números, caracteres, Strings, comentarios cumplen con las reglas definidas por el programador. Para realizar el analizador léxico se esta utilizando el pluging “ANTLR” (me oriente a utilizar este pluging ya que lo encontré un poco mas sencillo de utilizar). Como primer paso fue crear un archivo en donde se encontrara la definición del Lexer, es aquí en donde se establecen los tokens para las palabras reservadas, operadores lógicos y otros signos que pertenecen al alfabeto del lenguaje de pascal como ser: ‘.’, ‘;’, ‘(‘, ‘)’, etc. Además, se aplicaron los métodos visto en clase para definir lo que son dígitos, letras y con estos poder definir lo que son números, identificadores.

    Problemas:
    1.) la restricción de que los números no pueden empezar con el digito cero a menos que este representado el valor cero, Mi definición para número es “NUMERO: ‘0’(‘1’..’9’)(DIGITO)*”, ahora cuando lo compilo y encuentra por ejemplo el numero 001 me retorna que no se encontró ningún error y entiendo por que se así, aquí va mi pregunta ¿El Lexer es el que detecta esta restricción o es el parser?

    2.) Otro problema que tengo es cuando aplico la definición para identificadores “ID:LETRA(LETRADIGITO)*” para palabras largas (“Ej: paleontologo”) no me las acepta, pero si captura palabras pequeñas y estas si son aceptadas.

miércoles, agosto 17, 2005

Editor Grafico de Turbo Dragon

El editor de pascal cuenta con las opciones de poder cargar archivos de pascal (*.pas) y archivos de texto, además el editor muestra en la parte izquierda el número de línea de cada línea de código que este contenido en el archivo. Al momento de compilar el código se mostrara todos los errores generados en un área de texto no editable en la cual se mostrar información acerca del error y en que posición se encuentra.

Nota: Todas las palabras reservadas se mostraran en negrita, Ej.: “for i=1 to 10”

¿Porque micro-pascal?, lo habia definido así por las restricciones que se tiene, como ser que solo numeros enteros, limite de parametros de funciones, etc.



domingo, agosto 07, 2005

Laboratorio # 1

Al principio tuve problemas para configurar las opciones jflex.bat, ya que la ruta el path de java no estaba correcto, por lo cual estuve un buen rato tratando de corregirlo, además, no sabia que el comando rem significaba comentarios.

Al no tener correcto el path de java no podía compilar Cup, pero después de corrgir el path todo salio muy bien. Después de esto no tuve problemas la generar el archivo yyler.java.

Tuve problemas para poder compilar los archivos parser.java, sym.java y yylex.java, me genero varios errore, los cuales quise corregir pero no puede llegar a compilar el archivo yylex.java, ya que no estaban definidas en la clase sym, algunos términos como “TIMES, PLUS, etc”, por consiguiente no pude correr Example.parser ni tampoco realizar los cambios que requería el laboratorio # 1.
También tuve problemas para aplicar las opciones de jflex en eclipse, no entendí muy bien que es lo que debía realizar.
Para el inciso de que solo acepte número menores que 64, primero construi una expresión regular en donde solamente incluyo los digitos del 0 al 64, cuando ingreso el numero aplico la expresión y si ese número no se encuentra definido muestro un mensaje de error.
para cambiar que la operacion se ejecutara con el ENTER y no con el punto y como, en el estado inicial verifico cuando se encuentre con una nueva linea...si la encuentra entonces ejecuta la operación.
Para generar la documentación del programa en Netbeans 3.6 es en la opción de generar Javadoc, primero debemos seleccionar la ubicación en donde se encuentra el archivo ejecutable de javadoc, que generalmente es en donde instalamos -j2sdk1-

Otra forma de verificar que el numero ingresado sea menor que 64, es mediante la función Yytext() (devuelve un String), la cual mantiene la información que se ingreso, este valor lo convertimos en su valor entero mediante la clase Integer, y luego verificamos que este valor entero sea menor que 64.
Eclipse Vs. Netbeans

El primer compilador de Java que utilice fue Netbeans 3.6, es una herramienta muy completa, el cual ofrece un entorno muy fácil de utilizar, y al que me he acostumbrado a usar. Una de las desventaja de Netbeans 3.6 es el consumo de recursos y pensé, es Java! así deben ser los compiladores, Pero no! Después de haber instaldo Eclipse compare el consumo de recursos entre ambos, y resulto que Eclipse consume menos recursos que Netbeans 3.6. Empecé a navegar en el entorno de Eclipse, el cual tiene a primera vista un bonito entorno. Eclipse es muy parecido a netbeans 3.6, lo cual me parece muy perfecto ya que estoy acostumbrado a Netbeans 3.6 y mucho mejor no consume muchos recursos.Algo que no me gusta es que Eclipse no hace diferencia de los "main Class", sino que hay que estar asignando mediante "Run..."cual es el Main. En cambio en Netbeans 3.6 si hace la diferencia y uno solo ejecuta el main que desea correr sin tener antes que asignar cual en "Main Class"

domingo, julio 31, 2005

Just In Time Compiler: En la programación y ambiente Java, JIT compiler es un programa trasforma bytecode de Java (un programa que contiene instrucciones que deben interpretarse) en instrucciones que pueden enviarse directamente al procesador. El bytecode es código plataforma-independiente que puede enviarse y correrse en cualquier plataforma. Además permite una mejor actuación de los programas

Links:
Compiler-Compilers: Es una herramienta de depuración que utilizan los escritores de compiladores (sistemas para ayudar en el proceso de escritura de compiladores), que como cualquier programador puede usar con provecho. Esta herramienta se orienta en torno a modelos particulares de lenguaje y son más adecuados para generar compiladores de lenguajes similares al de los modelos. En pocas palabras es un traductor que tiene como entrada la definición de un lenguaje y como salida el compilador para dicho lenguaje.

Links:


  1. http://www.monografias.com/trabajos11/compil/compil2.shtml
  2. http://algebra.iespana.es/compiladores.htm

Cross-Compiler: Compiladores que pueden ejecutarse en una máquina y produce código objeto para otra máquina.

Links:

  1. http://www.pc-actual.com/Pr%C3%A1ctico/Microconsultas/Inform%C3%A1tica_personal/Linux/20040730014
  2. http://compiler.area51.ipupdater.com/
Intérprete: Acepta programas escritos en un lenguaje de alto nivel, los analiza y los ejecuta bajo control del propio intérprete. En este caso, no se genera un programa equivalente en otro lenguaje, como ocurre con un compilador por lo que, si se desea repetir la ejecución del programa, es preciso volver a traducirlo.

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.

¿No entendiste?...bueno ahí te va una Analogía: Comparando su actuación con la de una persona, 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.

Ejemplos: PHP, Javascript, ASP (hasta la versión 3) y HTML son ejemplos de lenguajes interpretados.

Links:
Maquinas Virtuales: El concepto de máquinas virtuales consiste en la posibilidad de ejecutar simultáneamente varios sistemas operativos en una misma máquina, de modo que cada uno de ellos "crea" que tiene una máquina dedicada para si mismo.

Por Ejemplo: La máquina virtual "VMWare" debido a que permite aplicar este concepto sobre PC's (linux o windows). Un Poco de Historia: El concepto de virtualización lo introdujo IBM en sus sistemas operativos hace unos 20 años. También de esta misma compañía viene, a mi entender, el logro más espectacular con respecto a la virtualización del hardware. Lograron ejecutar más de 44.000 Sistemas Operativos Linux simultáneamente en la misma máquina real!!!

¿Has Escuchado el Termino...JAVA?: Cuando una persona desarrolla una aplicación en un lenguaje como C o C++, el archivo binario que genera el compilador y que contiene el código que implementa dicha aplicación, se puede ejecutar únicamente sobre la plataforma sobre la cual fue desarrollada, debido a que dicho código es especifico a esa plataforma.

La plataforma Java se encuentra por encima de otras plataformas. El código que generan sus compiladores no es específico de una maquina física en particular, sino de una máquina virtual. Aún cuando existen múltiples implantaciones de la Máquina Virtual Java, cada una específica de la plataforma sobre la cual subyace, existe una única especificación de la máquina virtual, que proporciona una vista independiente del hardware y del sistema operativo sobre el que se esté trabajando. De esta manera un programador en Java “escribe su programa una vez, y lo ejecuta donde sea”

Ventajas: La primera es que presentan un medio excelente para alcanzar la portabilidad y no cabe duda que introduce otro nivel de abstracción y de protección, entre la computadora y el software que ejecuta sobre ella. Esto cobra particular importancia en un ambiente donde el código que ejecutamos proviene de algún lugar del mundo y es escrito por alguna "buena" persona.

Desventaja: Los lenguajes basados en máquina virtual son más lentos que los lenguajes completamente compilados, debido a la sobrecarga que genera tener una capa de software intermedia entre la aplicación y el hardware de la computadora.


Links:

  1. http://labsopa.dis.ulpgc.es/so-itig/tema3/tsld027.htm
  2. http://www.enbytes.com/noticias/enbytesidf03.htm
  3. http://www.microsoft.com/spain/windowsxp/virtualpc/evaluation/overview2004.asp

miércoles, julio 20, 2005

¿Qué es un Ing. de Sistemas para Mí?

Es una leyenda Personal, un paso mas para finalizar un capitulo de la vida, con el cual me ayuda a iniciar otro. Es una clasificación eduacativa y social que inicia a la persona a desarrollarse como independiente e interactuar en un ambiente de resposanbilidad con el fin de ayudar a eliminar obstaculos que intervienen ha alcanzar nuestro proposito: "Satisfacer nuestras necesidades"