/* MODULO AUXILIAR PARA EL ROBOT KAREL */
/* ==================================================*/
/* === Programa: karel.yac ===*/
/* === TEcnica: Dirigida por la sintAxis ===*/
/* === Programador: J. Rafael R. ochoa ===*/
/* ==================================================*/
%{
struct codif // almacena el codigo objeto (*.ok)
{
int linea; // numero de linea
char *comando; // nombre de comando
struct codif *sig; // apuntador al siguiente nodo
struct codif *ant; // apuntador al nodo anterior
};
char e1[50], e2[50], b1[50], b2[50]; // variables de etiqueta(2) y brincos(2)
int etiqueta = 1;
int lineno = 1;
%}
%union
{
char str[80];
struct codif *robot;
}
/* =============PROGRAMA=======================*/
%token INICIO_DE_AMBIENTE FIN_DE_AMBIENTE
%token INICIO_DE_EJECUCION FIN_DE_EJECUCION
%token INICIO_DE_PROGRAMA FIN_DE_PROGRAMA
/* =============AMBIENTE=======================*/
%token KAREL_ESTA_EN_CALLE AVENIDA VIENDO_AL CON MONEDAS_EN_SU_BOLSA
%token NORTE SUR ESTE OESTE
%token PARED_JUNTO_A_AVENIDA PARED_JUNTO_A_CALLE DE_CALLE
%token DE_AVENIDA A HAY MONEDAS_EN_CALLE
/* ============BLOQUE==========================*/
%token INICIO FIN
/* ============CONDICION=======================*/
%token SI ENTONCES SINO
/* ============REPETICION======================*/
%token REPITE VECES MIENTRAS HAZ
/* =============PRIMITIVAS=====================*/
%token AVANZA GIRA_A_LA_IZQUIERDA RECOGE_MONEDA COLOCA_MONEDA
%token APAGATE
/* ============FUNCIONES=======================*/
%token DEFINE_NUEVA_INSTRUCCION COMO
/* ============PRUEBAS=========================*/
%token FRENTE_DESPEJADO FRENTE_BLOQUEADO
%token IZQUIERDA_DESPEJADA IZQUIERDA_BLOQUEADA
%token DERECHA_DESPEJADA DERECHA_BLOQUEADA
%token JUNTO_A_MONEDA NO_JUNTO_A_MONEDA
%token HACIA_EL_NORTE NO_HACIA_EL_NORTE
%token HACIA_EL_SUR NO_HACIA_EL_SUR
%token HACIA_EL_ESTE NO_HACIA_EL_ESTE
%token HACIA_EL_OESTE NO_HACIA_EL_OESTE
%token CON_MONEDAS_EN_SU_BOLSA SIN_MONEDAS_EN_SU_BOLSA
/* ============TOKENS QUE REGRESAN VALOR===========*/
%token <str> NUM FUNCION
%type <robot> karel ambiente describe_amb instr_karel instr_amb
%type <robot> pared moneda programa funciones funcion
%type <robot> ejecucion instrucciones instruccion instr_primitiva
%type <robot> call_to_func condicion direccion sino
%%
/* producciones de la gramatica */
karel : ambiente programa {archiva($1, $2);}
;
ambiente : INICIO_DE_AMBIENTE describe_amb FIN_DE_AMBIENTE
{ $$ = lista($2, nodo("jc kini")); }
;
describe_amb : instr_karel instr_amb {$$ = lista($1, $2);}
;
instr_karel : KAREL_ESTA_EN_CALLE NUM AVENIDA NUM VIENDO_AL
direccion CON NUM MONEDAS_EN_SU_BOLSA ';'
{ $$ = lista(nodo("k"),
lista(nodo($2),
lista(nodo($4),
lista($6, nodo($8)))) );
}
;
direccion : NORTE { $$ = nodo("NORTE"); }
| SUR { $$ = nodo("SUR"); }
| ESTE { $$ = nodo("ESTE"); }
| OESTE { $$ = nodo("OESTE"); }
;
instr_amb : pared instr_amb {$$ = lista($1, $2);}
| moneda instr_amb {$$ = lista($1, $2);}
| {$$ = NULL;}
;
pared : PARED_JUNTO_A_CALLE NUM DE_AVENIDA NUM A NUM ';'
{$$ = lista(nodo("pc"),
lista(nodo($2),
lista(nodo($4), nodo($6))));
}
| PARED_JUNTO_A_AVENIDA NUM DE_CALLE NUM A NUM ';'
{$$ = lista(nodo("pa"),
lista(nodo($2),
lista(nodo($4), nodo($6))));
}
;
moneda : HAY NUM MONEDAS_EN_CALLE NUM AVENIDA NUM ';'
{$$ = lista(nodo("m"),
lista(nodo($2),
lista(nodo($4), nodo($6))));
}
;
programa : INICIO_DE_PROGRAMA funciones ejecucion FIN_DE_PROGRAMA
{$$ = lista($2, $3);}
;
funciones : {$$ = NULL;}
| funcion funciones {$$ = lista($1, $2);}
;
funcion : DEFINE_NUEVA_INSTRUCCION FUNCION COMO instruccion
{$$ = lista(nodo($2), lista($4, nodo("rs"))); }
;
ejecucion : INICIO_DE_EJECUCION instrucciones FIN_DE_EJECUCION
{$$ = lista(nodo("kini"), $2);}
;
instrucciones : instruccion instrucciones {$$ = lista($1, $2);}
| {$$ = NULL;}
;
instruccion : instr_primitiva {$$ = $1;}
| INICIO instrucciones FIN {$$ = $2;}
| SI condicion ENTONCES instruccion sino
{ sprintf(e1, "%s", genera_etiqueta());
sprintf(e2, "%s", genera_etiqueta());
sprintf(b1, "jc %s", e1);
sprintf(b2, "jc %s", e2);
$$ = lista($2, lista(nodo(b1),
lista($4,
lista(nodo(b2),
lista(nodo(e1),
lista($5, nodo(e2))))))
);
}
| REPITE NUM VECES instruccion
{ $$ = repite($4, atoi($2));}
| MIENTRAS condicion HAZ instruccion
{
sprintf(e1, "%s", genera_etiqueta());
sprintf(e2, "%s", genera_etiqueta());
sprintf(b1, "jc %s", e1);
sprintf(b2, "jc %s", e2);
$$ = lista(nodo(e1), lista($2, lista(nodo(b2),
lista($4, lista(nodo(b1), nodo(e2)))))
);
}
| call_to_func {$$ = $1;}
;
sino : {$$ = NULL;}
| SINO instruccion {$$ = $2; }
;
instr_primitiva : GIRA_A_LA_IZQUIERDA ';' {$$ = nodo("gi");}
| AVANZA ';' {$$ = nodo("av");}
| APAGATE ';' {$$ = nodo("ap");}
| COLOCA_MONEDA ';' {$$ = nodo("cm");}
| RECOGE_MONEDA ';' {$$ = nodo("rm");}
;
call_to_func : FUNCION ';'
{ sprintf(b1, "js %s", $1);
$$ = nodo(b1);
}
;
condicion : FRENTE_DESPEJADO {$$ = nodo("fd") ;}
| FRENTE_BLOQUEADO {$$ = nodo("fb") ;}
| IZQUIERDA_DESPEJADA {$$ = nodo("id") ;}
| IZQUIERDA_BLOQUEADA {$$ = nodo("ib") ;}
| DERECHA_DESPEJADA {$$ = nodo("dd") ;}
| DERECHA_BLOQUEADA {$$ = nodo("db") ;}
| JUNTO_A_MONEDA {$$ = nodo("jm") ;}
| NO_JUNTO_A_MONEDA {$$ = nodo("njm");}
| HACIA_EL_NORTE {$$ = nodo("hn") ;}
| NO_HACIA_EL_NORTE {$$ = nodo("nhn");}
| HACIA_EL_SUR {$$ = nodo("hs") ;}
| NO_HACIA_EL_SUR {$$ = nodo("nhs");}
| HACIA_EL_ESTE {$$ = nodo("he") ;}
| NO_HACIA_EL_ESTE {$$ = nodo("nhe");}
| HACIA_EL_OESTE {$$ = nodo("ho") ;}
| NO_HACIA_EL_OESTE {$$ = nodo("nho");}
| CON_MONEDAS_EN_SU_BOLSA {$$ = nodo("din");}
| SIN_MONEDAS_EN_SU_BOLSA {$$ = nodo("smb");}
;
%%
/* funciones auxiliares */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylex(); /* Liga con la funcion yylex generada por LEX */
extern int yynerrs;
extern FILE *yyin;
int yyparse();
int main(int argc, char *argv[])
{
if (argc != 2) {printf ("\nOlvido el archivo karel\n"); return 0; }
yyin = fopen(argv[1],"r");
if (yyin == NULL) { printf ("error al abrir el archivo"); return 0; }
/*Llama al analizador sintactico */
yyparse();
fclose(yyin);
return 0;
}
yyerror() /* llamado por yyparse() cuando ocurra */
{ /* un error */
printf("\n [error en linea %d] \n", lineno);
return 1;
}
struct codif *nodo(char *cad)
{
struct codif *nodo_nuevo = NULL;
nodo_nuevo = (struct codif *)malloc(sizeof(struct codif));
nodo_nuevo->comando = strdup(cad);
nodo_nuevo->linea = lineno;
nodo_nuevo->sig = NULL;
nodo_nuevo->ant = NULL;
return nodo_nuevo;
}
struct codif *lista(struct codif *lista1, struct codif *lista2)
{
struct codif *lista_total = lista1;
struct codif *anterior;
if (!lista1 && !lista2) return NULL;
if (lista2 == NULL ) return lista1;
if (lista1 == NULL ) return lista2;
while(lista1) { anterior = lista1; lista1 = lista1->sig; }
anterior->sig = lista2;
lista2->ant = anterior;
return lista_total;
}
char *genera_etiqueta(void)
{
char etiq[10];
sprintf(etiq, "etiq_%d", etiqueta);
etiqueta++;
return strdup(etiq);
}
void archiva(struct codif *amb, struct codif *prog)
{
FILE *out;
printf("hola mundo ...");
if ((out = fopen("karel.ok", "wt")) == NULL) // archivo de salida
{ printf("No se puede crear el archivo karel.ok\n"); return; }
printf("\nAlmacenando el archivo karel.ok\n");
while(amb)
{
fprintf(out, "%d %s\n", amb->linea, amb->comando);
amb = amb->sig;
}
while(prog)
{
fprintf(out, "%d %s\n", prog->linea, prog->comando);
prog = prog->sig;
}
fprintf(out, "ok\n");
fclose(out);
}
struct codif *copia(struct codif *lista)
{
struct codif *salida = NULL;
struct codif *nuevo = NULL;
struct codif *temp = NULL;
while(lista)
{
nuevo = nodo(lista->comando);
nuevo->linea = lista->linea;
if(!salida) {salida = nuevo; temp = nuevo;}
else {temp->sig = nuevo; temp = nuevo;}
lista = lista->sig;
}
return salida;
}
struct codif *repite(struct codif *instr, int n)
{
struct codif *salida = NULL;
struct codif *temp;
while(n)
{
printf("\nN= %d y comando= %s",n,instr->comando);
temp = NULL;
temp = copia(instr);
salida = lista(salida, temp);
n--;
}
return salida;
}