KAREL.YAC



/* 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;
}