Un compilador para un lenguaje de programación sencillo

Iniciado por leogtz, 8 Enero 2012, 05:57 AM

0 Miembros y 1 Visitante están viendo este tema.

leogtz

Hola a todos.

Hola a todos, bueno, les cuento, como parte de un trabajo en la universidad, tuve que crear un "compilador", o por lo menos avanzarlo, sin utilizar flex, lex, bison, yacc y todo eso, desde 0 totalmente. Pues bueno, quería compartirles el código.

El compilador no tiene mucho, pero algo es algo  :P

Tiene su analizador léxico, analizador sintáctico, unas pequeñas comprobaciones de tipos de datos y demás..., el compilador crea correctamente su propio árbol sintáctico para el código fuente dado, que ya es un avance, y para ver si funcionaba la lectura del árbol sintáctico, hice un poco de generación de código intermedio para las expresiones aritméticas básicas, genera código P y pseudocódigo ensamblador (un código artesanal que hace movimientos con registros con nombres de tipo R[0-9]), pero solo para expresiones aritméticas sencillas.

Quiero compartirlos con ustedes y si quieren unirse a mi, adelante, son bienvenidos, ya que creanme que para mi no ha sido nada fácil, me ha resultado bastante complejo esto, y eso que aún no llego plenamente a la generación de código. En fin.

El "compilador" está hecho en Java, con la ayuda de NetBeans. ¿por qué en Java? porque tenía que hacer esto lo más pronto posible, en menos de 3 meses :s y en periodo escolar, por lo que no tenía mucho tiempo de dedicarle tiempo exclusivamente a esto :s, Java provee un fácil manejo con Strings, además de estructuras de datos que no iba a tener que armas desde 0, como las listas y las tablas de dispersión, además que es con lo que más se llevan mis compañeros.

Bueno, les comento un poco cómo se estructura el lenguaje, algunos ejemplos:

inicio miPrimerProgramaEnGLHBR
entero x = 3;
leer(x)
fin;


El código debe empezar por inicio ID sentencias fin;, siempre.

inicio Hello_Shit
entero x = 123;
inc(x, 2 * 3)
fin;


inicio X
entero x = 1;
write(x);
repetir
x = x + 5;
x = x - 4
hasta x == 10
fin;


inicio X
entero z = 1234 + 234 + 56 + 78;
infinito hacer
z = z + 12
porsiempre
fin;


El compilador procesa las operaciones aritméticas (obviamente las operaciones aritméticas se hacen checando precedencia de operadores) y hace el cálculo, por ejemplo esto:

inicio X
entero x = (3 * 69 - (5 * 85 - 14))
fin;


Y el código que se genera:

Código P:

;Código P para las sentencias enteras sencilla para el programa final.glhbr
ldc 3
ldc 69
mpi
ldc 5
ldc 85
mpi
ldc 14
sbi
sbi


Y el pseudocódigo ensamblador:

; Código ensamblador para el programa "final.glhbr"
MOV R0,#3 ; Cargamos 3
MOV R1,#69 ; Cargamos 69
MUL R0,R1     ;  Multiplicamos
MOV R1,#5 ; Cargamos 5
MOV R2,#85 ; Cargamos 85
MUL R1,R2     ;  Multiplicamos
MOV R2,#14 ; Cargamos 14
SUB R1,R2        ; Restamos
SUB R0,R1        ; Restamos
MOV x,R0    ; fin de la sentencia de asignación
; Rutina para mostrar el resultado de x
;        R = -204.0


Todo esto recorriendo el nodo de árbol sintáctico correspondiente a una operación aritmética en postorden y luego la evaluación por medio de una pila.

Quizá alguien que sepa assembly pueda ayudar a traducir el pseudocódigo ensamblador a assembly real.

Son algunos de los usos, por supuesto, como ya les he dicho, no se ejecuta nada, porque no hay generación de código.... y para eso pido su ayuda, si alguno quiere unirse y aportar ideas, bienvenido! así aprendemos todos.

Bueno, les dejo el link el link y una captura:



El proyecto está en github por si quieren ver ahí los cambios que he hecho:
https://github.com/leogtzr/glhbr

Saludos.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

WARG

viejo me gustaria ayudarte ya que tengo una idea similar para mi propuesta de grado a esta no tengo mucho conocimiento en esto pero estoy investigando mucho me gusta esto que estas haciendo ATT WARG

WarZ0n3

#2
EDITO: No me había fijado que era un post muerto de hace 1 año ¬¬

Voy a dar 3 simples ejemplo 2 de suma y 1 de resta (con la sintaxis de AT&T), por que la idea no es traducir el pseudocódigo si no que entiendas el concepto de suma/resta y luego tomar las acciones respectivas dependiendo de lo que quieras hacer...

También quería aclarar que hace mucho que no hago nada en ASM puro, por lo que los siguientes ejemplos los daré del lado del GCC pero si entiendes la mecánica luego podrás adaptarlo a intel o cualquier otro asm fácilmente...

(todo esto suponiendo que tiene una variable "x" de tipo integro en 0)
AT&T (suma con asm extendido "x"+15)
Código (cpp) [Seleccionar]

__asm__(
       "StartUp:\n"
       "lea 0xfffffffc(%%ebp), %%eax\n" //cargamos la variable con el puntero a ebp -4
       
       :"=r"(x) // output de la variable
       :"r"(15) // sumamos 15 desde el input
       :"%eax" // preservamos el registro eax
   );


AT&T (suma normal "x"+3)
Código (cpp) [Seleccionar]

__asm__(
       "StartUp:\n"
       "lea 0xfffffffc(%ebp), %eax\n"
       "addl $0x3, (%eax)" // sumamos 3 a eax
);


AT&T (resta normal "x"-3)
Código (cpp) [Seleccionar]

__asm__(
       "StartUp:\n"
       "lea 0xfffffffc(%ebp), %eax\n"
       "subl $0x3, (%eax)\n"
   );




Espero que te haya servido yo también sigo estudiando at&t

leogtz

@WarZ0n3

Gracias, la verdad que este proyecto lo descontinué hace muchísimo.

Continué con un nuevo proyecto, un lenguaje de programación ya terminado, te dejo más información aquí.

http://leonardogtzr.wordpress.com/2013/03/09/yare-un-lenguaje-de-programacin-propio/
https://github.com/leogtzr/yarelang-c--
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com