/* * * Referencia adelantada * se intentan resolver los nombres, los que no se resuelvan se almacenan en al tabla de simbolos * se recorren los no resueltos, y se le asigna el nombre correspondiente * se recorre el ambito modulo, y se instalan las declaraciones en los no resueltos * **/ header{ import java.util.*; import antlr.*; import java.io.*; } class Anasint extends Parser; options{ buildAST=true; } tokens{ PROGRAMA; VISIBLE; OCULTO; NO_INST; ATRIBUTO; METODO; PROTOTIPO; PARAMETRO; PARAMETROS; EXPRESIONES; RESULTADO; DEFINICION; VACIO; VARIABLE_LOCAL; VARIABLES_LOCALES; INSTRUCCION; INSTRUCCIONES; MENOSUNARIO; LLAMADA; ACCESO_TABLA; ACCESO_OBJETO; ACCESO_SIMPLE; LISTA_ENTEROS; ERROR; } { logFile log; int margen = 0; Pila_Ambitos pilaambitos = new Pila_Ambitos(); LinkedList no_resueltos = new LinkedList(); void ambito_abrir_programa(){ if(pilaambitos.vacia() == true){ Ambito a = new Ambito("programa","PROGRAMA",null,null); pilaambitos.apilar_ambito(a); } } void ambito_abrir(AST nombre, String tipo){ Ambito act = pilaambitos.ambito_actual(); String tipoAct = act.getTipo(); if(tipo.equals("MODULO") && tipoAct.equals("PROGRAMA") || tipo.equals("CLASE") && tipoAct.equals("MODULO") || tipo.equals("METODO") && tipoAct.equals("CLASE")){ Ambito A = new Ambito(nombre.getText(), tipo, null, act); pilaambitos.apilar_ambito(A); } } void ambito_cerrar(){ if(pilaambitos.vacia() == false){ pilaambitos.desapilar_ambito(); } } void ambito_cerrar_programa(){ if(pilaambitos.vacia() == false && pilaambitos.ambito_actual().getTipo().equals("PROGRAMA")) pilaambitos.desapilar_ambito(); //TODO referencia adelantada Simbolo_no_resuelto snr; while(no_resueltos.size() > 0){ snr = no_resueltos.remove(0); System.out.println(snr.getNombre() + " - " + snr.getAmbito().getNombre()); } } AST crear_declaracion_modulo(AST nombre_modulo, AST definicion_modulo){ String m = nombre_modulo.getText(); AST M = #(#[MODULO, "modulo"],nombre_modulo, definicion_modulo); Simbolo S = new Simbolo(m, M); pilaambitos.ambito_actual().setDeclaracion(S); return M; } AST crear_declaracion_clase (AST nombre_clase, AST cualificador_clase, AST definicion_clase){ String c = nombre_clase.getText(); AST C = #(#[CLASE,"clase"],nombre_clase, cualificador_clase, definicion_clase); Simbolo S = new Simbolo(c,C); pilaambitos.ambito_actual().setDeclaracion(S); return C; } AST crear_declaracion_metodo (AST declaracion_metodo, AST cualificador_metodo){ AST MT = #(#[METODO,"metodo"], declaracion_metodo, cualificador_metodo); String mt = MT.getFirstChild().getFirstChild().getText(); Simbolo S = new Simbolo(mt,MT); pilaambitos.ambito_actual().setDeclaracion(S); return MT; } AST crear_declaracion_atributo (AST nombre_atributo, AST tipo_atributo, AST cualificador_atributo){ String a = nombre_atributo.getText(); AST A = #(#[ATRIBUTO,"atributo"], nombre_atributo, tipo_atributo, cualificador_atributo); Simbolo S = new Simbolo(a, A); pilaambitos.ambito_actual().setDeclaracion(S); return A; } AST crear_declaracion_parametro (AST nombre_parametro, AST tipo_parametro){ String p = nombre_parametro.getText(); AST P = #(#[PARAMETRO,"parametro"], nombre_parametro, tipo_parametro); Simbolo S = new Simbolo(p, P); pilaambitos.ambito_actual().setDeclaracion(S); return P; } AST crear_declaracion_variable_local (AST nombre_variable, AST tipo_variable){ String v = nombre_variable.getText(); AST V = #(#[VARIABLE_LOCAL,"variable_local"], nombre_variable, tipo_variable); Simbolo S = new Simbolo(v, V); pilaambitos.ambito_actual().setDeclaracion(S); return V; } AST ambito_tratar_acceso_simple (AST ident){ String acc = ident.getText(); AST dec_acc = null; Simbolo s; if ((s=pilaambitos.buscar_simbolo(acc)) != null){ dec_acc = s.getDeclaracion(); // AST de la declaracion del acceso simple log.writeNoIndent(" ("+dec_acc.getText()+")\n"); } else{ String men = "ERROR RN: Identificador " +acc+ " no declarado"; dec_acc = #(#[ERROR,"error"]); System.out.println(men); // identificador no declarado log.writeNoIndent(" (error)\n"); } AST ACC = #(#[ACCESO_SIMPLE,"acceso_simple"], ident, dec_acc); return ACC; } AST ambito_tratar_ident_tipo (AST ident){ String men = ""; String tipo = ident.getText(); men = "ERROR RN: Identificador de tipo "+tipo+" no declarado"; Ambito amb = pilaambitos.ambito_actual(); while (amb != null && !amb.getTipo().equals("MODULO")) amb = amb.getContenedor(); if (amb == null){ System.out.println(men); // el tipo no es un tipo clase return #(#[ERROR,"error"]); } Simbolo simb = amb.getDeclaracion(tipo); if (simb == null){ System.out.println(men); // el tipo no es un tipo clase //TODO referencia adelanatada no_resueltos.add(new Simbolo_no_resuelto(tipo, pilaambitos.ambito_actual())); return #(#[ERROR,"error"]); //#(#[ERROR,"error"]); } AST C = simb.getDeclaracion(); return C; } public AST arbol_crear(AST e1, AST e2){ if(e2 == null){ return #(#[CREAR,"crear"],e1, #[ERROR,"error"]); }else return #(#[CREAR,"crear"],e1, e2); } public AST arbol_escribir(AST e){ if(e == null){ return #(#[ERROR,"error"]); }else return #(#[ESCRIBIR,"escribir"],e); } //comprueba que existe la clase programa y el metodo inicio en esta public void comprobarPrograma(AST modulo){ boolean programa=false; AST clase = modulo.getFirstChild().getNextSibling(); while (!clase.getText().equals("exportacion")){ clase = clase.getNextSibling(); } clase = clase.getFirstChild(); String nombre = clase.getFirstChild().getText(); while(true){ if(nombre.equals("Programa") && !programa){ programa = true; if(clase.getFirstChild().getNextSibling().getText().equals("inst")){ System.out.println("ERROR AS: La clase Programa tiene que ser no instanciable"); } comprobarInicio(clase); } clase = clase.getNextSibling(); if(clase == null) break; nombre = clase.getFirstChild().getText(); } if(!programa){ System.out.println("ERROR AS: No se ha definido la clase Programa"); } } public void comprobarInicio(AST Prog){ boolean inicio = false; AST modulo = Prog.getFirstChild().getNextSibling().getNextSibling(); if(modulo != null){ while(modulo.getType() != METODO && modulo != null){ modulo = modulo.getNextSibling(); } if(modulo != null && !modulo.getFirstChild().getFirstChild().getText().equals("inicio")){ System.out.println("ERROR AS: Debe haber un metodo inicio en la clase Programa, y debe ser unico"); }if(modulo.getNextSibling() != null){ System.out.println("ERROR AS: Debe haber un metodo inicio en la clase Programa, y debe ser unico"); } } } } ///////////////////////////////////////////////////////// // DECLARACION DE MODULO ///////////////////////////////////////////////////////// declaracion_modulo![String f] : { ambito_abrir_programa(); log = new logFile(f); } n:nombre_modulo { ambito_abrir (#n,"MODULO"); log.write("MODULO: "+#n.getText()+"\n"); log.incNivel(); } d:definicion_modulo EOF { ambito_cerrar(); #declaracion_modulo=crear_declaracion_modulo(#n,#d); comprobarPrograma(#declaracion_modulo); ambito_cerrar_programa(); log.decNivel(); log.close(); } ; nombre_modulo : MODULO! IDENT ; definicion_modulo : (importacion)? (exportacion)+ (implementacion)? ; lista_ident: IDENT (COMA! IDENT)*; importacion : IMPORTACION^ DOS_PUNTOS! l:lista_ident ; exportacion : EXPORTACION^ DOS_PUNTOS! l:lista_declaraciones_clases ; implementacion : IMPLEMENTACION^ DOS_PUNTOS! l:lista_declaraciones_clases ; lista_declaraciones_clases : (declaracion_clase)* ; /////////////////////////////////////////////////////////// // DECLARACION DE CLASE /////////////////////////////////////////////////////////// declaracion_clase ! : c:cualificador_clase n:nombre_clase { ambito_abrir(#n,"CLASE"); log.write("CLASE: "+#n.getText()+"\n"); log.incNivel(); } d:definicion_clase { ambito_cerrar(); log.decNivel(); #declaracion_clase = crear_declaracion_clase(#n,#c,#d); } ; cualificador_clase! : INST {#cualificador_clase = #(#[INST]);} | {#cualificador_clase = #(#[NO_INST,"no_inst"]);} ; nombre_clase : CLASE! IDENT ; definicion_clase : LLAVE_ABIERTA! declaraciones_elemento_clase LLAVE_CERRADA! ; declaraciones_elemento_clase : (declaracion_elemento_clase)* ; ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // DECLARACION DE ELEMENTO CLASE: METODO O ATRIBUTO ///////////////////////////////////////////////////////////////////////////////////////////////////////////// declaracion_elemento_clase! : c:cualificador_elemento_clase ((IDENT PARENTESIS_ABIERTO) => a:declaracion_metodo { ambito_cerrar(); #declaracion_elemento_clase = crear_declaracion_metodo(#a,#c); } | t:tipo i:IDENT PUNTO_Y_COMA { #declaracion_elemento_clase = crear_declaracion_atributo(#i,#t,#c); log.write("ATRIBUTO: "+#i.getText()+"\n"); }) ; // Cualificador de visibilidad cualificador_elemento_clase! : OCULTO {#cualificador_elemento_clase = #(#[OCULTO]);} | {#cualificador_elemento_clase = #(#[VISIBLE,"visible"]);} ; declaracion_metodo : prototipo_metodo definicion_metodo ; prototipo_metodo! : i:IDENT { ambito_abrir(#i,"METODO"); log.write("METODO: "+#i.getText()+"\n"); } PARENTESIS_ABIERTO p:declaracion_parametros PARENTESIS_CERRADO (DEV t:tipo {#prototipo_metodo = #(#[PROTOTIPO,"prototipo"],#i,#(#[PARAMETROS,"parametros"],#p),#(#[RESULTADO,"resultado"],#t));} | {#prototipo_metodo = #(#[PROTOTIPO,"prototipo"],#i,#(#[PARAMETROS,"parametros"],#p),#(#[RESULTADO,"resultado"],#[VACIO, "vacio"]));} ) ; declaracion_parametros : declaracion_parametro (COMA! declaracion_parametro)* | ; /////////////////////////////////////////////////////////// // DECLARACION DE PARAMETRO /////////////////////////////////////////////////////////// declaracion_parametro!: t:tipo i:IDENT {#declaracion_parametro = crear_declaracion_parametro(#i,#t);} ; definicion_metodo! : LLAVE_ABIERTA {log.incNivel();} d:declaraciones_variables_locales b:bloque LLAVE_CERRADA {log.decNivel();} {#definicion_metodo= #(#[DEFINICION,"definicion"],#(#[VARIABLES_LOCALES,"variables_locales"],#d), #b);} ; declaraciones_variables_locales : (declaracion_variables_locales tipo IDENT) => declaracion_variables_locales declaraciones_variables_locales |(declaracion_variables_locales) => declaracion_variables_locales | ; declaracion_variables_locales : t:tipo! lista_nombres_variables_locales[#t] PUNTO_Y_COMA! ; lista_nombres_variables_locales [AST t] : nombre_variable_local[#t] (COMA! nombre_variable_local[#t])* ; ///////////////////////////////////////////////////////////////// // DECLARACION DE VARIABLE LOCAL ////////////////////////////////////////////////////////////////// nombre_variable_local! [AST t] : i:IDENT { #nombre_variable_local = crear_declaracion_variable_local(#i,#t); } ; /////////////////////////////////////////////////////////// // INSTRUCCIONES /////////////////////////////////////////////////////////// instrucciones : (instruccion)* ; instruccion! : i:instruccion_simple PUNTO_Y_COMA {#instruccion=#(#[INSTRUCCION,"instruccion"],#i);} | j:instruccion_compuesta {#instruccion=#(#[INSTRUCCION,"instruccion"],#j);} ; instruccion_simple : (expresion ASIGNACION CREAR) => crear | (expresion ASIGNACION) => asignacion | llamada_metodo | escribir | retorno ; instruccion_compuesta : condicion | iteracion ; asignacion! : e1:expresion ASIGNACION e2:expresion { #asignacion = #(#[ASIGNACION],#e1,#e2); } ; retorno! : DEV e:expresion { #retorno = #(#[DEV],#e); } ; llamada_metodo! : i:acceso PARENTESIS_ABIERTO s:lista_expresiones PARENTESIS_CERRADO { #llamada_metodo = #(#[LLAMADA,"llamada"],#i,#(#[EXPRESIONES,"expresiones"],#s)); } ; lista_expresiones : expresion (COMA! expresion)* | ; condicion : SI^ PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO! ENTONCES! bloque (SINO! bloque)? FINSI! ; iteracion : MIENTRAS^ PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO! HACER! bloque FINMIENTRAS! ; bloque!: i:instrucciones {#bloque=#(#[INSTRUCCIONES,"instrucciones"],#i);} ; ///////////////////////////////////////////////////////////// // EXPRESIONES //////////////////////////////////////////////////////////// expresion : expresion_nivel_1 (O^ expresion_nivel_1)* ; expresion_nivel_1 : expresion_nivel_2 (Y^ expresion_nivel_2)* ; expresion_nivel_2 : (NO^)? expresion_nivel_3 ; expresion_nivel_3 : expresion_nivel_4 ((MAYOR^|MAYOR_IGUAL^|MENOR^|MENOR_IGUAL^|IGUAL^|DISTINTO^) expresion_nivel_4)? ; expresion_nivel_4 : expresion_nivel_5 ((MAS^|MENOS^) expresion_nivel_5)* ; expresion_nivel_5 : expresion_nivel_6 ((POR^|DIVISION^) expresion_nivel_6)* ; expresion_nivel_6 : MENOS i:expresion_nivel_7 {#expresion_nivel_6=#(#[MENOSUNARIO,"menosunario"],#i);} | expresion_nivel_7 ; expresion_nivel_7: PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO! | entero_a_real | real_a_entero | (acceso PARENTESIS_ABIERTO) => llamada_metodo | (acceso CORCHETE_ABIERTO) => acceso_tabla | acceso | LIT_ENTERO | LIT_REAL | LIT_CAR | CIERTO | FALSO ; ////////////////////////////////////////////////////////////// // ACCESOS A TABLAS ////////////////////////////////////////////////////////////// acceso_tabla!: c:acceso CORCHETE_ABIERTO d:lista_expresiones_nv CORCHETE_CERRADO {#acceso_tabla=#(#[ACCESO_TABLA,"acceso_tabla"],#c,#(#[EXPRESIONES,"expresiones"],#d));} ; ////////////////////////////////////////////////////////////// // ACCESOS SIMPLES Y A OBJETOS ////////////////////////////////////////////////////////////// acceso!: (IDENT PUNTO)=> i1:IDENT PUNTO i2:IDENT { log.write("ACCESO SIMPLE: "+#i1.getText()); #acceso=#(#[ACCESO_OBJETO,"acceso_objeto"], ambito_tratar_acceso_simple(#i1), #i2); } | i:IDENT { log.write("ACCESO SIMPLE: "+#i.getText()); #acceso = ambito_tratar_acceso_simple(#i); } ; lista_expresiones_nv : expresion (COMA! expresion)* ; ////////////////////////////////////////////////////////// // TIPOS ///////////////////////////////////////////////////////// tipo : tipo_predefinido_simple | tipo_predefinido_compuesto | i:IDENT {#tipo = ambito_tratar_ident_tipo(#i); log.write("IDENTIFICADOR TIPO: "+#i.getText()+"\n"); } ; tipo_predefinido_simple : ENTERO | REAL | LOGICO | CARACTER ; tipo_predefinido_compuesto : formacion ; formacion! : FORMACION l:lista_enteros ( t:tipo_predefinido_simple {#formacion = #(#[FORMACION,"formacion"],#(#[LISTA_ENTEROS,"lista_enteros"],#l),#t);} | i:IDENT {#formacion = #(#[FORMACION,"formacion"], #(#[LISTA_ENTEROS,"lista_enteros"],#l), ambito_tratar_ident_tipo(#i)); log.write("IDENTIFICADOR TIPO: "+#i.getText()+"\n"); } ); lista_enteros : LIT_ENTERO (COMA! LIT_ENTERO)*; escribir!: ESCRIBIR PARENTESIS_ABIERTO e:expresion PARENTESIS_CERRADO { #escribir = arbol_escribir(#e); try{ log.write("IDENTIFICADOR TIPO: "+#e.getFirstChild().getNextSibling().getFirstChild().getText()+"\n"); }catch(NullPointerException n){} }; //de momento se pasa el arbol completo del tipo, pero creo que con el ident seria //suficiente para el analisis semantico crear!: e1:expresion ASIGNACION CREAR PARENTESIS_ABIERTO i:expresion PARENTESIS_CERRADO { #crear = arbol_crear(#e1,#i); try{ log.write("IDENTIFICADOR TIPO: "+#i.getFirstChild().getNextSibling().getFirstChild().getText()+"\n"); }catch(NullPointerException n){} }; entero_a_real!: ENTERO_A_REAL PARENTESIS_ABIERTO e1:expresion PARENTESIS_CERRADO {## = #(#[ENTERO_A_REAL],#e1);}; real_a_entero!: REAL_A_ENTERO PARENTESIS_ABIERTO e1:expresion PARENTESIS_CERRADO {## = #(#[REAL_A_ENTERO],#e1);};