/* GENERAR PSEUDOCODIGO INTERMEDIO DE C */ /* -------------------------------------------------- --- Programa: com.yac --- --- TEcnica: dirigida por la sintAxis --- --- Objetivo: generar pseudocOdigo --- --- intermedio del lenguaje c --- --- Recibe: un archivo con codigo c --- --- Regresa: un archivo con pseudocOdigo --- --- Programador: J. Rafael R. Ochoa --- -------------------------------------------------- */ %{ struct codigo /* almacena el codigo objeto (*.ok)*/ { char comando[50]; /* nombre de comando*/ struct codigo *sig; /* apuntador al siguiente nodo*/ }; struct args { char tipo[50]; char nombre[50]; struct args *sig; }; struct var_locs { char tipo[50]; char nombre[50]; char valor[50]; struct var_locs *sig; }; struct prototipos { char tipo[50]; char nombre[80]; // struct args *arg; struct prototipos *sig; }; char e1[20], e2[20], b1[20], b2[20]; /* variables de etiqueta y brinco*/ char varia[256], variable[256]; /* variable para formar cadenas */ char ret[10]; /* tipo de variable a regresar */ int n, ok=0; /* variable para ciclos*/ int etiqueta = 0; /* inicio de la etiqueta*/ int rafa = 0,flag = 0; /* banderas para los espacios */ struct args *checa_args; struct var_locs *checa_var_locs; struct prototipos *checa_protos; struct codigo *nodo(char *cad); int quita_espacios(char arch[]); struct codigo *append(struct codigo *append1, struct codigo *append2); char *genera_etiqueta(void); void archiva(struct codigo *programa); void inserta_proto(char [], char []); void inserta_arg (char [], char []); void inserta_var_locs(char [], char [], char []); int checa_n_args(struct codigo *, struct codigo *); int checa_tipos(struct codigo *, struct codigo *); char *substr(int , char *); char *extrae_nom(struct codigo *lista); %} %union { struct codigo *pseudo; char str[80]; } /* __________________________________________________________dominio_*/ %token <str> L_LLAVE R_LLAVE L_PARENT R_PARENT L_CUADRO R_CUADRO /* _____________________________________________________________tipo_*/ %token <str> F_LIN F_INT F_CAD F_CAR CAD CHAR INT VOID /* ___________________________________________________________varios_*/ %token <str> DIAGONAL COMILLA APOSTROFE PUNTO_COMA COMA GATO %token <str> INCLUDE DEFINE AMPER PUNTO FORMATO ESPACIO /* _________________________________________________________operacion_*/ %token <str> MAS MENOS DIV ASTER %token <str> IDENTICO ASIGNA OR AND MENOR MAYOR NOT NOT_EQ %token <str> MAYOR_IGUAL MENOR_IGUAL %token <str> TEXTO RETURN /* ___________________________________________________________ciclos_*/ %token <str> WHILE FOR %token <str> PRINTF PUTS %token <str> GETS SCANF FFLUSH STDOUT %token <str> IF ELSE /* ________________________________________tokens que regresan valor_*/ %token <str> NUM /* ______________________________________________reglas gramaticales_*/ %type <pseudo> programa %type <pseudo> includes include %type <pseudo> resto ambos_pro_fun pro_fun %type <pseudo> instrucciones instruccion %type <pseudo> args arg arg_resto %type <pseudo> atomica progresion %type <pseudo> llamada_funcion parametros parametro param_coma %type <pseudo> var_locs var_loc var_resto %type <pseudo> expr termino factor var asignacion %type <pseudo> condicion printf else %type <pseudo> textos %type <pseudo> var_format v_format v_for_fin var_scan %type <str> tipo asig_resto operador %% programa : includes resto { archiva($2); } ; includes : include { $$ = $1; } | include includes { $$ = append($1, $2); } ; include : GATO INCLUDE MENOR TEXTO PUNTO TEXTO MAYOR { sprintf(variable,"ic %s",$4); $$ = nodo(variable); } ; resto : tipo TEXTO PUNTO_COMA resto { sprintf(variable,"vl %s",$2); $$ = append(nodo(variable), $4); } | tipo TEXTO L_PARENT ambos_pro_fun resto { if(rafa==0) { sprintf(variable,"vl %s",$2); rafa = 0; $$ = nodo(variable); } if(rafa==1) { sprintf(variable,"fu %s",$2); sprintf(varia,"mv %s %s",ret,$2); rafa = 1; $$ = append(nodo(variable), append(nodo(varia), append($4,$5))); } } | { $$ = NULL; } ; ambos_pro_fun : args R_PARENT pro_fun /* prototipo o funcion */ { if (!$3) { $$ = NULL; rafa=0; } else { strcpy(ret,"num"); rafa = 1; $$ = $3; } } ; args : { $$ = NULL; } | VOID { $$ = NULL; } | arg { $$ = $1; } ; arg : tipo arg_resto /*{ $$ = NULL; }*/ { $$ = $2; } ; arg_resto : { $$ = NULL; } | COMA arg { $$ = $2; } | TEXTO { $$ = nodo($1); } | TEXTO COMA arg { $$ = append(nodo($1), $3); } ; pro_fun : PUNTO_COMA /* prototipo */ { $$ = NULL; } | L_LLAVE var_locs instrucciones R_LLAVE /* funcion */ { $$ = append($2, append($3,nodo("rs"))); checa_var_locs = NULL; } ; var_locs : { $$ = NULL; } | var_loc var_locs { $$ = append($1,$2); } ; var_loc : tipo TEXTO var_resto PUNTO_COMA { sprintf(variable,"vl %s",$2); $$ = append(nodo(variable), $3); inserta_var_locs($1,$2,""); } ; var_resto : { $$ = NULL; } | ASIGNA NUM { $$ = append(nodo("va"),nodo($2)); } | COMA TEXTO var_resto { $$ = append(nodo($2),$3); } ; tipo : INT { strcpy($$,"int"); } | CHAR { strcpy($$,"char"); } | CAD { strcpy($$,"char *"); } | VOID { strcpy($$,"void"); } ; instrucciones : instruccion { $$ = $1; } | instruccion instrucciones { $$ = append($1,$2); } ; instruccion : PUNTO_COMA { $$ = NULL; } | atomica PUNTO_COMA { $$ = $1; } | IF L_PARENT condicion R_PARENT instruccion else { sprintf(e1, "%s", genera_etiqueta()); sprintf(e2, "%s", genera_etiqueta()); sprintf(b1, "sa %s", e1); sprintf(b2, "sa %s", e2); $$ = append($3, append(nodo(b1), append($5, append(nodo(b2), append(nodo(e1), append($5, nodo(e2)))))) ); } | FOR L_PARENT asignacion PUNTO_COMA condicion PUNTO_COMA progresion R_PARENT instruccion { sprintf(e1, "%s", genera_etiqueta()); sprintf(e2, "%s", genera_etiqueta()); sprintf(b1, "sa %s", e1); sprintf(b2, "sa %s", e2); $$ = append($3, append(nodo(e1), append($5, append(nodo(b2), append($9, append($7, append(nodo(b1), nodo(e2))))))) ); } | WHILE L_PARENT condicion R_PARENT instruccion { sprintf(e1, "%s", genera_etiqueta()); sprintf(e2, "%s", genera_etiqueta()); sprintf(b1, "sa %s", e1); sprintf(b2, "sa %s", e2); $$ = append(nodo(e1), append($3, append(nodo(b2), append($5, append(nodo(b1), nodo(e2))))) ); } | L_LLAVE instrucciones R_LLAVE { $$ = $2; } ; else : { $$ = NULL; } | ELSE instruccion { $$ = $2; } ; llamada_funcion : TEXTO L_PARENT parametros R_PARENT { sprintf(varia,"mv %s %s",ret, $1); sprintf(variable,"ca %s",$1); $$ = append(nodo(varia), append($3, nodo(variable))); } ; asignacion : TEXTO ASIGNA asig_resto { if(strncmp($3,"mu",2)==0 || strncmp($3,"ad",2)==0) { sprintf(variable,"mv %s %s",substr(2,$3),$1); $$ = append(nodo($3), nodo(variable)); } else { sprintf(variable,"mv %s %s",$3,$1); $$ = nodo(variable); } /* sprintf(variable,"mv %s %s",substr(2,$3),$1); $$ = append(nodo($3), nodo(variable)); */ } ; asig_resto : TEXTO { strcpy($$, $1); } | NUM { strcpy($$, $1); } | expr { strcpy($$, $1->comando); } ; progresion : TEXTO MAS MAS { sprintf(variable,"mm %s",$1); $$ = nodo(variable); } | TEXTO MENOS MENOS { sprintf(variable,"ll %s",$1); $$ = nodo(variable); } | MAS MAS TEXTO { sprintf(variable,"mm %s",$1); $$ = nodo(variable); } | MENOS MENOS TEXTO { sprintf(variable,"ll %s",$1); $$ = nodo(variable); } | asignacion { $$ = $1; } ; condicion : TEXTO operador TEXTO { sprintf(variable,"%s %s %s",$1,$2,"num"); $$ = nodo(variable); } | TEXTO operador NUM { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | TEXTO operador expr { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | NUM operador TEXTO { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | NUM operador NUM { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | NUM operador expr { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | expr operador NUM { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | expr operador TEXTO { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | expr operador expr { sprintf(variable,"%s %s %s",$1,$2,$3); $$ = nodo(variable); } | NOT expr { sprintf(variable,"no %s",$1,$2); $$ = nodo(variable); } ; operador : IDENTICO { strcpy($$, "id"); } | MAYOR { strcpy($$, "ma"); } | MENOR { strcpy($$, "me"); } | MAYOR_IGUAL { strcpy($$, "ge"); } | MENOR_IGUAL { strcpy($$, "le"); } | NOT_EQ { strcpy($$, "ne"); } ; parametros : { $$ = NULL; } | parametro parametros { $$ = append($1,$2); } ; parametro : NUM param_coma { $$ = append(nodo("pa"), append(nodo($1),$2)); } | TEXTO { sprintf(ret,"%s",$1); $$ = NULL; } | APOSTROFE TEXTO APOSTROFE param_coma { $$ = append(nodo("pa"), append(nodo($2),$4)); } | var param_coma { $$ = append(nodo("pa"), append($1, $2)); } | expr param_coma { $$ = append(nodo("pa"), append($1, $2)); } ; param_coma : { $$ = NULL; } | COMA parametro { $$ = $2; } ; atomica : PRINTF L_PARENT COMILLA {flag=1;} textos {flag=0;} COMILLA printf R_PARENT { $$ = append($5, $8); /*if(!checa_n_args($5, $8)) { strcpy(error, "n_args != n_var en printf"); return 0; } if(!checa_tipos($5,$8)) { strcpy(error, "tipos no compatibles en printf"); return 0; }*/ } | RETURN TEXTO { sprintf(ret,"%s",$2); $$ = NULL; } | FFLUSH L_PARENT STDOUT R_PARENT { $$ = nodo("ff"); } | PUTS L_PARENT COMILLA textos COMILLA R_PARENT { $$ = append(nodo("pu"),$4); } | GETS L_PARENT var R_PARENT { $$ = append(nodo("ge"),$3); } | SCANF L_PARENT COMILLA textos COMILLA COMA var_scan R_PARENT { $$ = $7; } | asignacion { $$ = $1; } | expr { $$ = $1; } | llamada_funcion { $$ = $1; } ; printf : { $$ = NULL; } | COMA var_format { $$ = $2; } ; textos : { $$ = NULL; } | F_LIN textos { sprintf(variable,"pr f_lin",$1); $$ = append(nodo(variable), $2); } | TEXTO textos { sprintf(variable,"pr \"%s\"",$1); $$ = append(nodo(variable), $2); } ; expr : expr MAS termino { sprintf(variable,"ad %s %s",$1,$3); $$ = nodo(variable); } | expr MENOS termino { sprintf(variable,"su %s %s",$1,$3); $$ = nodo(variable); } | termino { $$ = $1; } ; termino : termino ASTER factor { sprintf(variable,"mu %s %s",$1,$3); $$ = nodo(variable); } | termino DIV factor { sprintf(variable,"di %s %s",$1,$3); $$ = nodo(variable); } | factor { $$ = $1; } ; factor : var { $$ = $1; } | NUM { $$ = nodo($1); } | TEXTO ASIGNA expr { sprintf(variable,"mv %s %s",$3->comando,$1); $$ = nodo(variable); } | TEXTO ASIGNA llamada_funcion { sprintf(variable,"mv %s %s",extrae_nom($3),$1); sprintf(varia,"ca %s",extrae_nom($3)); $$ = append(nodo(varia), nodo(variable)); } | L_PARENT expr R_PARENT { $$ = $2; } ; var : TEXTO { $$ = nodo($1); } ; var_scan : TEXTO { sprintf(variable,"sc %s", $1); $$ = nodo(variable); } | AMPER TEXTO { sprintf(variable,"sc %s", $2); $$ = nodo(variable); } ; var_format : { $$ = NULL; } | v_format var_format { $$ = append($1,$2); } ; v_format : NUM v_for_fin { sprintf(variable,"pr %s",$1); $$ = append(nodo(variable),$2); } | TEXTO v_for_fin /* es una variable */ { sprintf(variable,"pr %s",$1); $$ = append(nodo(variable),$2); } | expr v_for_fin { sprintf(variable,"pr %s",$1->comando); $$ = append(nodo(variable),$2); } ; v_for_fin : { $$ = NULL; } | COMA v_format { $$ = $2; } ; %% /* funciones de apoyo */ #include <stdio.h> #include <stdlib.h> #include <string.h> extern int yylex(); /* Liga con la funcion yylex generada por FLEX */ extern int yynerrs; extern FILE *yyin; int yyparse(); int main(int argc, char *argv[]) { if (argc != 2) { printf ("\nuso: com archivo.c\n:-)\n"); return 1; } quita_espacios(argv[1]); if ((yyin = fopen("arch.c","rt")) == NULL) // archivo de entrada { printf ("error al abrir el archivo\n:-(\n"); return 0; } checa_args = NULL; checa_var_locs = NULL; checa_protos = NULL; yyparse(); /* Llama al analizador sintactico */ fclose(yyin); if(strlen(error)>5) printf("error: %s\n",error); printf("\n:-)\n"); return 1; } yyerror() /* llamado por yyparse() cuando ocurra */ { /* un error */ printf("\n [error en linea %d]", n_lines); printf("\n %s ==> %d",yylval.str, ok); return 1; } struct codigo *nodo(char *cad) { struct codigo *nodo_nuevo = NULL; nodo_nuevo = (struct codigo *)malloc(sizeof(struct codigo)); strcpy(nodo_nuevo->comando, cad); nodo_nuevo->sig = NULL; return nodo_nuevo; } struct codigo *append(struct codigo *append1, struct codigo *append2) { struct codigo *append_total = append1; struct codigo *anterior; if (!append1 && !append2) return NULL; if (append2 == NULL ) return append1; if (append1 == NULL ) return append2; while(append1) { anterior = append1; append1 = append1->sig; } anterior->sig = append2; return append_total; } char *genera_etiqueta(void) { char etiq[20]; sprintf(etiq, "etiq_%d", etiqueta); etiqueta++; return strdup(etiq); } void archiva(struct codigo *programa) { FILE *out; printf("hola mundo ..."); if ((out = fopen("pseudo.ok", "wt")) == NULL) // archivo de salida { printf("No se puede crear el archivo pseudo.ok\n"); return; } printf("\nAlmacenando el archivo pseudo.ok\n"); while(programa) { fprintf(out, "%s\n", programa->comando); programa = programa->sig; } fprintf(out, "ok\n"); fclose(out); } int quita_espacios(char arch[]) { FILE *in,*out; char car1,car2; int ok = 0; if ((in = fopen(arch,"rt")) == NULL) // archivo fuente { printf("No se puede abrir el archivo"); return 0; } if ((out = fopen("arch.c","w")) == NULL) // archivo sin comentarios { printf("No se puede abrir el archivo"); return 0; } car1 = fgetc(in); while (car1 != EOF) { if( car1 == '/') { car2 = fgetc(in); ok = 1; if (car2 == EOF) break; if( car2 == '/') { ok = 0; while(car1 != '\n' && car1 != EOF) car1=fgetc(in); continue; } if( car2 == '*') { ok = 0; while(1) { car1 = fgetc(in); if(car1 == '*') if(fgetc(in) == '/') { car1 = fgetc(in); break; } } continue; } } fputc(car1, out); if (ok) fputc(car2,out); car1 = fgetc(in); } if (car1 != EOF) fputc(car1,out); fclose(in); fclose(out); return 1; } void inserta_proto(char tipo[], char nombre[]) { struct prototipos *act = NULL; act = (struct prototipos *)malloc(sizeof(struct prototipos)); strcpy(act->tipo,tipo); strcpy(act->nombre, nombre); act->sig = NULL; if (!checa_protos) checa_protos = act; else { act->sig = checa_protos; checa_protos = act; } } void inserta_var_locs(char tipo[], char nombre[], char valor[]) { struct var_locs *act = NULL; act = (struct var_locs *)malloc(sizeof(struct var_locs)); strcpy(act->tipo, tipo); strcpy(act->nombre, nombre); strcpy(act->valor, valor); act->sig = NULL; if (!checa_var_locs) checa_var_locs = act; else { act->sig = checa_var_locs; checa_var_locs = act; } } void inserta_arg(char tipo[], char nombre[]) { struct args *act = NULL; act = (struct args *)malloc(sizeof(struct args)); strcpy(act->tipo, tipo); strcpy(act->nombre, nombre); act->sig = NULL; if (!checa_args) checa_args = act; else { act->sig = checa_args; checa_args = act; } } int checa_n_args(struct codigo *args, struct codigo *vars) { char formato[256]; while(args) { strcpy(formato, args->comando); if( !strncmp(formato,"f_int",5) || !strncmp(formato,"f_car",5) || !strncmp(formato,"f_cad",5) ) { if(vars) vars = vars->sig; else return 0; } args = args->sig; } return 1; } int checa_tipos(struct codigo *args, struct codigo *vars) { char formato[256]; while(args) { strcpy(formato, args->comando); if( !strncmp(formato,"f_int",5) || !strncmp(formato,"f_car",5) || !strncmp(formato,"f_cad",5) ) { if( strncmp(vars->comando, formato,5)!=0) return 0; else vars = vars->sig; } args = args->sig; } return 1; } char *extrae_nom(struct codigo *lista) { struct codigo *copia = lista; while(copia) { if(strncmp(copia->comando,"ca",2)==0) break; copia = copia->sig; } if (!copia) { printf("error, es llamada a funcion sin nombre de funcion"); return '\0'; } return substr(2, copia->comando); } char *substr(int n, char *string) // devuelve palabra n de string { char ch = string[0], car[1], ret[100], *cadena; cadena = (char *)malloc(80); cadena=strdup(string); while(n>1) { while (ch != ' ') { cadena++; ch = cadena[0]; } // busca posicion cadena = cadena++; ch = cadena[0]; n--; } ch = cadena[0]; ret[0] = '\0'; while (ch != ' ' && ch != '\0' && ch != '\n' && ch != ';') // busca finalizador { car[0] = ch; car[1] = '\0'; strcat(ret, car); cadena++; ch = cadena[0]; } return strdup(ret); }