Usuario:ManuelRomero/compiladores/AS/declaracionVariables

De WikiEducator
< Usuario:ManuelRomero
Revisión a fecha de 07:24 8 ene 2015; ManuelRomero (Discusión | contribuciones)

(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Saltar a: navegación, buscar



declaracion_variables

  • produccion optativa (puede haber o no variables en un programa)
  • lista de variables que puede tener un programa
  • Acciones a realizar
  1. ninguna ya que no tenemos ninún terminal solo producciones
  • Produccion para yacc
DeclaracionVariables.png

Vemos que puede estar vacía (épsidon) o que puede contener lista de declaraciones seguido del token punto y coma ;

Código en yaac
declaracion_variables:
|    lista_declaraciones ';'
;

lista_declaraciones




Icon define.gif

Definición

Una lista de elementos consite en uno o varios elementos


  • En este caso va a ser una lista de declaraciones: una (declaracion) o varias declaraciones (lista_declaraciones)
  • En yacc siempre usaremos una recursividad por la izquierda (ver producción)
  • Acciones a realizar
  1. ninguna ya que no tenemos ningún terminal solo producciones
   lista_declaraciones ';' declaracion
|    declaracion
;

declaracion




Icon define.gif

Definición

declaracion de una variable es un tipo de variable seguido de una serie de identificadores que representan las variables


  • Una declaracion puede ser de variables simple o un variables compuesta
  • La forma de daclarar es decir el tipo de variable y luego una lista (1 o mas) de identificadores
  • Acciones a realizar
  1. ninguna ya que no tenemos ninún terminal solo producciones
Producción

Declaracion.png

codigo en yacc
 variable_simple lista_identificadores
|variable_compuesta identificadores_variable_compuesta
;

variable_simple

Producción

VariableSimple.png

Atributos
%type<tipo> variable_simple 
 
TIPO_VARIABLE tipo;
 typedef enum {
        DESCONOCIDO,
        ENTERO,
        BOOLEANO,
        CHAR,
        CADENA,
	ENUMERATIVO
  } TIPO_VARIABLE;
Acción
  • Asignar al atributo el valor de tipo de variable
Código Yacc
variavariable_simple:
     tENTERO{
          DEBUGA("variable_simple: tipo entero\n",DVARIABLES,debug);
          $$=ENTERO;
     }
|    tCARACTER{
          DEBUGA("variable_simple: tipo caracter\n",DVARIABLES,debug);
          $$=CHAR;
     }
|    tBOOLEANO{
          DEBUGA("variable_simple: tipo booleano\n",DVARIABLES,debug);
          $$=BOOLEANO;
 
     }
;

Lista_identificadores

Producción

Archivo:ListaIdentificadores.png

Atributos
Acción
Análisis semántico: Verificar que no existe dicho identificador en la tabla de símbolos a ese nivel
Tabla de simbolos: Dar de alta el identificador con el tipo de variable heredado o sintetizado
Código Yacc
lista_identificadores:
     tIDENTIFICADOR{
        if (($1.PSimbolo==NULL)||($1.PSimbolo->nivel!=nivel)){
            char msg[200];
            introducir_variable(tabsim,$1.NId,$<tipo>0,nivel,0);
 
            sprintf(msg,"identificadores:tIDENTIFICADOR ->introducir_variable <%s>",$1.NId);
            DEBUGA(msg,DVARIABLES,debug);
 
        }
        else{
             char msg[100];
             sprintf(msg,"Identificador %s ya utilizado",$1.NId);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
        }
       AbreTag(xmlin,$1.NId,nivel);
       CierraTag(xmlin,$1.NId,nivel);   
     }
|    lista_identificadores ',' tIDENTIFICADOR{
        if (($3.PSimbolo==NULL)||$3.PSimbolo->nivel!=nivel){
            char msg[200];
            introducir_variable(tabsim,$3.NId,$<tipo>0,nivel,0);
            sprintf(msg,"identificadores: identificadores ',' tIDENTIFICADOR ->introducir_variable <%s>",$3.NId); 
            DEBUGA(msg,DVARIABLES,debug);
        }
        else{
             char msg[100];
             sprintf(msg,"Identificador %s ya utilizado",$3.NId);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
        }
       AbreTag(xmlin,$3.NId,nivel);
       CierraTag(xmlin,$3.NId,nivel);   
     }
;

variable_compuesta

Producción

VariableCompuesta.png

  • Esta producción es un poco complicada ya que puede darse dos casos en la variable compuesta
  1. Vector
  2. Matriz
  • Esto lo detectaremos si hay un rango (vector) o si hay dos rangos (matriz)
  • Vamos a crear la produccion resto_variable_compuesta la cual puede o no empeza por rango como veremos
  • Ademas a la produccion resto_variable_compuesta le vamos a asignar el siguiente atributo atributo
Atributo
ESTRUCTURA_VECTOR vector
%type <vector> variable_compuesta resto_variable_compuesta
typedef struct {
      	int limiteInferior;
      	int limiteSuperior;
	TIPO_VARIABLE tipoIndice;
}RANGO_VECTOR;
typedef union{
        RANGO_VECTOR vector;
	RANGO_VECTOR matriz[2];
}INDEX;
typedef struct{
	TIPO_VARIABLE_COMPUESTA tipoCompuesto;//si es vector o matriz
	TIPO_VARIABLE tipo;
      	INDEX indice;
}ESTRUCTURA_VECTOR;
Accion
  • La acción {$$=$5;} preciamente pasa el valor de dicho atributo de la producción ' resto_variable_compuesta a la producción variable_compuesta
Código en yacc
variable_compuesta:
tVECTOR '[' rango']' resto_variable_compuesta{$$=$5;}
;

Resto_variable_compuesta

Producción

RestoVariableCompuesta.png

Atributos
  • Vemos los mismos que en 'variable_compuesta'
 ESTRUCTURA_VECTOR vector
%type <vector> variable_compuesta resto_variable_compuesta
Acción
  • Aqui sabemos si en el 'resto_variable_compuesta' tenemos uno o dos rangos de índices
  • También sabemos cuál es el tipo base de la estructura compuesta
  • Y recogemos el /los rangos y los cargamos en el atributo de la producción
  • No se detectan errores semánticos
Código Yacc
resto_variable_compuesta:
tDE variable_simple
                         {
			 $$.tipo=$2;
			 $$.tipoCompuesto=VECTOR;
			 $$.indice.vector=$<indice>-1;
			 //Aqui introduzco la variable compuesta en la tabla de simbolos sabiendo que es vector
                         }
|'[' rango']'   tDE variable_simple
                         {
                         $<vector>-1.tipo=$5;
			 //Aqui introduzco la variable compuesta en la tabla de simbolos sabiendo que es matriz
			 $$.indice.matriz[0]=$<indice>-1;
			 $$.indice.matriz[1]=$2;
			 $$.tipoCompuesto=MATRIZ;
                         }
 
;

rango

Producción

Rango.png

  • Esta producción va a aportar información de los valores del rango así como de qué tipo son
Atributos
  • Para ello hemos creado el atributo indice de tipo RANGO_VECTOR cuya composición podemos ver:
RANGO_VECTOR indice;
%type<indice> rango 
typedef struct {
      	int limiteInferior;
      	int limiteSuperior;
	TIPO_VARIABLE tipoIndice;
}RANGO_VECTOR;

tipoIndice puede ser ENTERO, CARACTER o BOOLEANO


Acciones
  1. Comprobaciones
  2. Almacenar los valores para poderlos llevar a la tabja de símbolos
Comprobaciones
  • Como vemos el rango especifica dos valores
  • Aquí hay que hacer comprobaciones, dando error semántico en caso de no ser respetadas
  1. Que los dos valores del rango no sean del mismo tipo es un error sintáctico (no existe esa producción)
  2. Que el valor izquierdo sea estrictamente menor que el derecho hay que comprobarlo
  3. En caso de haber un sólo valor que sea entero en este caso el límite inferior lo tomaremos como 0 (DUDA A CONSULTAR)
tabla de símbolos
  • Necesitamos los valores de límite inferior y superior
  • También necesitamos saber de qué tipo son los índices (ENTERO, BOOLEANO, CARACTER) son los permitidos
Código de yacc con las comprobaciones realizadas es el siguiente
rango:  tCONSTENTERA     tPTO tPTO   tCONSTENTERA
        {
         $$.tipoIndice=ENTERO;
          //verificar rangos correctos
            if ($1>$4){//Rango incorrecto
                char msg[100];
                sprintf(msg,"Rango incorrecto %d debe ser menor que %d",$1,$4);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
                error_semantico(msg);
                CuentaErrores();
                $$.limiteInferior=$1;
                $$.limiteSuperior=$1+1;//Asigno un rango valido
           }else{
                $$.limiteInferior=$1;
                $$.limiteSuperior=$4;
           }
        }
 
        | tCONSTCHAR tPTO tPTO tCONSTCHAR 
 
        {
          $$.tipoIndice=CHAR;
          //verificar rangos correctos
	  //Verifico caracteres entre 32 y 126
	  //primero verifico limite inferior
          if (($1<32)||($1>125){
              char msg[100];
	      sprintf(msg,"Caracteres limite inferior no permitidos solo de a..z A..Z y no %c",$1);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
             $$.limiteInferior=32; //Asigno el caracter  'a'  como limite inferior
          }else{
	   $$.limiteInferior=$1;
	  }
	  //Ahora verificamos el limite superior
 
	   if (($4<33)||($4>126){
              char msg[100];
	      sprintf(msg,"Caracteres limite superior no permitidos solo de a..z A..Z y no %c",$4);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
             $$.limiteSuperior=126; //Asigno el caracter  'z'  como limite inferior
          }else{
	   $$.limiteInferior=$1;
	  }
	  //Ahora verifico los rangos que el inferior sea mayor que el superior
          if ($1>=$4){//Rango incorrecto
             char msg[100];
             sprintf(msg,"Rango de caracteres incorrecto %c debe ser menor que %c",$1,$4);
             /*/Aunque ya esté usado ese identificador, lo incyo en XML*/
             error_semantico(msg);
             CuentaErrores();
             $$.limiteInferior=$1;
             $$.limiteSuperior=$1+1;//Asigno un rango valido
          }
          else{
            $$.limiteInferior=$1;
            $$.limiteSuperior=$4;
          }
        } 
        | cBooleana tPTO tPTO cBooleana
        {   
            $$.tipoIndice=BOOLEANO;	
	    if ($1==$4){
             char msg[100];
             sprintf(msg,"Rango incorrecto, los extremos no pueden tener el mismo valor");
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
             $$.limiteInferior=0;
             $$.limiteSuperior=1;//Asigno un rango valido
 
	    }else{
                if ($1==tTRUE){
                   $$.limiteInferior=1;
		   $$.limiteSuperior=0;
		}
                else{
                   $$.limiteInferior=0;
		   $$.limiteSuperior=1;
		   }
	     }
 
        }
	|tCONSTENTERA{
 
	 $$.tipoIndice=ENTERO;
          //verificar rangos correctos
	  if ($1==0){
	            char msg[100];
                    sprintf(msg,"Indice no puede ser 0 (Cambiamos valor (+1))");
            			/*Cambio el signo de este limite y continuo*/
		            error_semantico(msg);
	            CuentaErrores();
               	    $$.limiteInferior=0;
                    $$.limiteSuperior=1;//Asigno un rango valido
	          }else{
	               $$.limiteInferior=0;
                       $$.limiteSuperior=$1;
		   }
           }
;

cBooleano

Producción

CBooleano.png

Atributos
VALOR_BOOLEANO bool;
%type<bool> cBooleana
#define TRUE            1
#define FALSE           0
 
typedef enum{
        FALSE,
	TRUE
        } VALOR_BOOLEANO;
Acción

Asignamos el valor al atributo (ver código yacc)

Código Yacc
cBooleana:
        tFALSE
        {
          $$=tFALSE;
        }
        |tTRUE          
        {$$=tTRUE;
        }
;


lista_identificadores_VC

Producción

ListaIdentificadoresVC.png

Atributos
Acción
Analisis semántica: Verificar que el identificador no existe en este nivel en la tabla de símbolos
Tabla de simbolos 
Dar de alta dicho identificador con todos los atributos heredados de Vector/Matriz y rangos correspondientes

Código Yacc

lista_identificadores_VC:
    tIDENTIFICADOR{
        if (($1.PSimbolo==NULL)||$1.PSimbolo->nivel!=nivel){
	    if ($<vector>0.tipoCompuesto==VECTOR)
                introducir_variable_vector(tabsim,$1.NId,$<vector>0,nivel,0);
	    else	
	        introducir_variable_matriz(tabsim,$1.NId,$<vector>0,nivel,0);
		        }
        else{
             char msg[100];
             sprintf(msg,"Identificador %s ya utilizado",$1.NId);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
        }
       AbreTag(xmlin,$1.NId,nivel);
       CierraTag(xmlin,$1.NId,nivel);   
     }
|    lista_identificadores_VC ',' tIDENTIFICADOR{
        if (($3.PSimbolo==NULL)||$3.PSimbolo->nivel!=nivel){
	 if ($<dimension>0==VECTOR)
                introducir_variable_vector(tabsim,$3.NId,$<vector>0,nivel,0);
	    else	
	        introducir_variable_matriz(tabsim,$3.NId,$<vector>0,nivel,0);
        }
        else{
             char msg[100];
             sprintf(msg,"Identificador %s ya utilizado",$3.NId);
             /*/Aunque ya esté usado ese identificador, lo incluyo en XML*/
             error_semantico(msg);
             CuentaErrores();
        }
       AbreTag(xmlin,$3.NId,nivel);
       CierraTag(xmlin,$3.NId,nivel);   
     }
;

identificadores_variable_compuesta

Producción

Archivo:IdentificadoresVariableCompuesta.png

declaracion_acciones

bloque_instrucciones