|
|
(3 revisiones intermedias por el mismo usuario no mostrado) |
Línea 1: |
Línea 1: |
− | {{:Usuario:ManuelRomero/compiladores/nav}} | + | {{:Usuario:ManuelRomero/compiladores/AS/nav}} |
| <br> | | <br> |
− | ==PROGRAMA== | + | |
| + | ===OBJETIVO=== |
| + | *Esta parte realizará el análisis sintáctico y semántico de nuestro programa |
| + | *La forma de trabajar será interpretando diferentes producciones y en el momento adecuado validaremos la situación |
| + | |
| + | ==PLANTILLA UTILIZADA PARA CADA PRODUCCIÓN== |
| <br><br/> | | <br><br/> |
| {{Resumen|La estructura general de cada producción va a ser: | | {{Resumen|La estructura general de cada producción va a ser: |
Línea 15: |
Línea 20: |
| *define de qué consta un programa | | *define de qué consta un programa |
| programa : tPROGRAMA tIDENTIFICADOR ';' declaracion_variables declaracion_acciones bloque_instrucciones | | 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
| |
− |
| |
− | <source lang=cpp>
| |
− | 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);
| |
− | }
| |
− | ;
| |
− | </source>
| |
− |
| |
− | ==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
| |
− | [[Archivo: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==
| |
− | <br><br/>
| |
− | {{Definicion|'''Una lista''' de elementos 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
| |
− | #ninguna ya que no tenemos ningún terminal solo producciones
| |
− |
| |
− | <source lang=cpp>
| |
− | lista_declaraciones ';' declaracion
| |
− | | declaracion
| |
− | ;
| |
− | </source>
| |
− | ==declaracion==
| |
− | <br><br/>
| |
− | {{Definicion|'''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
| |
− | [[imagen:declaracion.png]]
| |
− | ;codigo en yacc
| |
− | variable_simple lista_identificadores
| |
− | |variable_compuesta identificadores_variable_compuesta
| |
− | ;
| |
− |
| |
− | ==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
| |
− | #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'''
| |
− | <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:
| |
− | 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>
| |
− | 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
| |
− | [[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
| |
− | #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
| |
− | <source lang=C>
| |
− |
| |
− | 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;
| |
− | }
| |
− | }
| |
− | ;
| |
− |
| |
− | </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
| |
− | [[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==
| |
− | == bloque_instrucciones==
| |