Diferencia entre revisiones de «Usuario:ManuelRomero/preferencias/compiladores/analisisSemático»
De WikiEducator
(17 revisiones intermedias por el mismo usuario no mostrado) | |||
Línea 1: | Línea 1: | ||
+ | {{:Usuario:ManuelRomero/compiladores/nav}} | ||
+ | <br> | ||
==PROGRAMA== | ==PROGRAMA== | ||
+ | <br><br/> | ||
+ | {{Resumen|La estructura general de cada producción va a ser: | ||
+ | ;Producción | ||
+ | ;Atributos | ||
+ | ;Acción | ||
+ | ;Código Yacc | ||
+ | <source lang=C> | ||
+ | </source> | ||
+ | }} | ||
*primera producción | *primera producción | ||
*Producción obligatoria | *Producción obligatoria | ||
Línea 48: | Línea 59: | ||
; | ; | ||
− | + | ==lista_declaraciones== | |
<br><br/> | <br><br/> | ||
{{Definicion|'''Una lista''' de elementos uno o varios elementos}} | {{Definicion|'''Una lista''' de elementos uno o varios elementos}} | ||
Línea 61: | Línea 72: | ||
; | ; | ||
</source> | </source> | ||
− | + | ==declaracion== | |
<br><br/> | <br><br/> | ||
{{Definicion|'''declaracion de una variable''' es un tipo de variable seguido de una serie de identificadores que representan las variables}} | {{Definicion|'''declaracion de una variable''' es un tipo de variable seguido de una serie de identificadores que representan las variables}} | ||
Línea 75: | Línea 86: | ||
; | ; | ||
− | ===variable_simple=== | + | ==variable_simple== |
− | === | + | ;Producción |
− | === | + | [[imagen:variableSimple.png]] |
+ | ;Atributos | ||
+ | %type<tipo> variable_simple | ||
+ | <source lang=c> | ||
+ | TIPO_VARIABLE tipo; | ||
+ | typedef enum { | ||
+ | DESCONOCIDO, | ||
+ | ENTERO, | ||
+ | BOOLEANO, | ||
+ | CHAR, | ||
+ | CADENA, | ||
+ | ENUMERATIVO | ||
+ | } TIPO_VARIABLE; | ||
+ | </source> | ||
+ | ;Acción | ||
+ | *Asignar al atributo el valor de tipo de variable | ||
+ | ;Código Yacc | ||
+ | <source lang=c> | ||
+ | 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; | ||
+ | |||
+ | } | ||
+ | ; | ||
+ | </source> | ||
+ | |||
+ | ==Lista_identificadores== | ||
+ | ;Producción | ||
+ | [[Image: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 | ||
+ | <source lang=c> | ||
+ | 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); | ||
+ | } | ||
+ | ; | ||
+ | </source> | ||
+ | |||
+ | ==variable_compuesta== | ||
+ | ;Producción | ||
+ | [[imagen:variableCompuesta.png]] | ||
+ | |||
*Esta producción es un poco complicada ya que puede darse dos casos en la variable compuesta | *Esta producción es un poco complicada ya que puede darse dos casos en la variable compuesta | ||
#Vector | #Vector | ||
#Matriz | #Matriz | ||
*Esto lo detectaremos si hay un rango (vector) o si hay dos rangos (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''' | ||
+ | <source lang=C> | ||
+ | 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; | ||
+ | </source> | ||
+ | ;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: | variable_compuesta: | ||
tVECTOR '[' rango']' resto_variable_compuesta{$$=$5;} | tVECTOR '[' rango']' resto_variable_compuesta{$$=$5;} | ||
; | ; | ||
− | * | + | ==Resto_variable_compuesta== |
− | * | + | |
+ | ;Producción | ||
+ | [[imagen: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 | ||
<source lang=C> | <source lang=C> | ||
− | + | 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; | ||
+ | } | ||
+ | ; | ||
+ | </source> | ||
+ | ==rango== | ||
;Producción | ;Producción | ||
[[imagen:rango.png]] | [[imagen: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 | ||
+ | |||
+ | <source lang=c> | ||
+ | typedef struct { | ||
+ | int limiteInferior; | ||
+ | int limiteSuperior; | ||
+ | TIPO_VARIABLE tipoIndice; | ||
+ | }RANGO_VECTOR; | ||
+ | </source> | ||
+ | |||
+ | tipoIndice puede ser '''ENTERO, CARACTER o BOOLEANO''' | ||
+ | |||
+ | |||
;Acciones | ;Acciones | ||
#Comprobaciones | #Comprobaciones | ||
Línea 112: | Línea 271: | ||
*Como vemos el rango especifica dos valores | *Como vemos el rango especifica dos valores | ||
*Aquí hay que hacer comprobaciones, dando error semántico en caso de no ser respetadas | *Aquí hay que hacer comprobaciones, dando error semántico en caso de no ser respetadas | ||
− | #Que los dos valores del rango sean del mismo tipo | + | #Que los dos valores del rango no sean del mismo tipo es un error sintáctico (no existe esa producción) |
− | #Que el valor izquierdo sea estrictamente menor que el derecho | + | #Que el valor izquierdo sea estrictamente menor que el derecho hay que comprobarlo |
#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) | #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 | ;tabla de símbolos | ||
− | *Necesitamos los valores de límite inferior y superior | + | *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 | *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 | |
<source lang=C> | <source lang=C> | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
rango: tCONSTENTERA tPTO tPTO tCONSTENTERA | rango: tCONSTENTERA tPTO tPTO tCONSTENTERA | ||
− | |||
{ | { | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
$$.tipoIndice=ENTERO; | $$.tipoIndice=ENTERO; | ||
//verificar rangos correctos | //verificar rangos correctos | ||
Línea 162: | Línea 292: | ||
$$.limiteInferior=$1; | $$.limiteInferior=$1; | ||
$$.limiteSuperior=$1+1;//Asigno un rango valido | $$.limiteSuperior=$1+1;//Asigno un rango valido | ||
− | |||
}else{ | }else{ | ||
$$.limiteInferior=$1; | $$.limiteInferior=$1; | ||
$$.limiteSuperior=$4; | $$.limiteSuperior=$4; | ||
− | |||
} | } | ||
} | } | ||
Línea 175: | Línea 303: | ||
$$.tipoIndice=CHAR; | $$.tipoIndice=CHAR; | ||
//verificar rangos correctos | //verificar rangos correctos | ||
− | if (($1<32)||($ | + | //Verifico caracteres entre 32 y 126 |
+ | //primero verifico limite inferior | ||
+ | if (($1<32)||($1>125){ | ||
char msg[100]; | 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 | if ($1>=$4){//Rango incorrecto | ||
char msg[100]; | char msg[100]; | ||
sprintf(msg,"Rango de caracteres incorrecto %c debe ser menor que %c",$1,$4); | sprintf(msg,"Rango de caracteres incorrecto %c debe ser menor que %c",$1,$4); | ||
− | /*/Aunque ya esté usado ese identificador, lo | + | /*/Aunque ya esté usado ese identificador, lo incyo en XML*/ |
error_semantico(msg); | error_semantico(msg); | ||
CuentaErrores(); | CuentaErrores(); | ||
Línea 221: | Línea 370: | ||
$$.tipoIndice=ENTERO; | $$.tipoIndice=ENTERO; | ||
//verificar rangos correctos | //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); | error_semantico(msg); | ||
− | + | CuentaErrores(); | |
− | + | $$.limiteInferior=0; | |
− | + | $$.limiteSuperior=1;//Asigno un rango valido | |
}else{ | }else{ | ||
$$.limiteInferior=0; | $$.limiteInferior=0; | ||
Línea 244: | Línea 383: | ||
} | } | ||
} | } | ||
− | |||
; | ; | ||
+ | |||
</source> | </source> | ||
+ | ==cBooleano== | ||
+ | ;Producción | ||
+ | [[imagen:cBooleano.png]] | ||
+ | ;Atributos | ||
+ | |||
+ | '''VALOR_BOOLEANO bool;''' | ||
+ | '''%type<bool> cBooleana''' | ||
− | ==== | + | <source lang=c> |
+ | |||
+ | #define TRUE 1 | ||
+ | #define FALSE 0 | ||
+ | |||
+ | typedef enum{ | ||
+ | FALSE, | ||
+ | TRUE | ||
+ | } VALOR_BOOLEANO; | ||
+ | </source> | ||
+ | ;Acción | ||
+ | Asignamos el valor al atributo (ver código yacc) | ||
+ | ;Código Yacc | ||
+ | <source lang=C> | ||
+ | cBooleana: | ||
+ | tFALSE | ||
+ | { | ||
+ | $$=tFALSE; | ||
+ | } | ||
+ | |tTRUE | ||
+ | {$$=tTRUE; | ||
+ | } | ||
+ | ; | ||
+ | </source> | ||
+ | |||
+ | |||
+ | ==lista_identificadores_VC== | ||
;Producción | ;Producción | ||
− | [[imagen: | + | [[imagen: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 | ||
+ | <source lang=C> | ||
+ | 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); | ||
+ | } | ||
+ | ; | ||
+ | </source> | ||
+ | ==identificadores_variable_compuesta== | ||
+ | ;Producción | ||
+ | [[imagen:IdentificadoresVariableCompuesta.png]] | ||
== declaracion_acciones== | == declaracion_acciones== | ||
== bloque_instrucciones== | == bloque_instrucciones== |
Última revisión de 11:43 19 ago 2012
PROGRAMA
- primera producción
- Producción obligatoria
- define de qué consta un programa
programa : tPROGRAMA tIDENTIFICADOR ';' declaracion_variables declaracion_acciones bloque_instrucciones
- Acciones a realizar
- Dar de alta el identificador del programa para no volver a usarlo
- Después de la última instrucción eliminamos items de la tabla de símbolos
- Para crear el XML del programa, cada vez que hay un identificador creo un tag diciendo lo que es y lo cierro al final de su ámbito
programa: tPROGRAMA tIDENTIFICADOR ';' { nivel = 0; inicializar_tabla (tabsim); /*El identificador del programa Es el primer símbolo y por lo tanto seguro que no va a exixtir, por lo que no lo buscamos*/ introducir_programa(tabsim,$2.NId,0); AbreTag(xmlin,$2.NId,nivel-1); } declaracion_variables declaracion_acciones bloque_instrucciones { eliminar_variables (tabsim, nivel); eliminar_parametros_ocultos(tabsim,nivel+1); eliminar_acciones (tabsim, nivel); eliminar_programa(tabsim); CierraTag(xmlin,$2.NId,nivel-1); } ;
declaracion_variables
- produccion optativa (puede haber o no variables en un programa)
- lista de variables que puede tener un programa
- Acciones a realizar
- ninguna ya que no tenemos ninún terminal solo producciones
- Produccion para yacc
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
- 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
- ninguna ya que no tenemos ningún terminal solo producciones
lista_declaraciones ';' declaracion | declaracion ;
declaracion
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
- ninguna ya que no tenemos ninún terminal solo producciones
- Producción
- codigo en yacc
variable_simple lista_identificadores |variable_compuesta identificadores_variable_compuesta ;
variable_simple
- Producción
- 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
- Esta producción es un poco complicada ya que puede darse dos casos en la variable compuesta
- Vector
- 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
- 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
- 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
- Comprobaciones
- 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
- Que los dos valores del rango no sean del mismo tipo es un error sintáctico (no existe esa producción)
- Que el valor izquierdo sea estrictamente menor que el derecho hay que comprobarlo
- 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
- 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
- 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