header{ import java.util.*; } class AnaSem2 extends TreeParser; options{ buildAST=true; importVocab=Analex; importVocab=Anasint; } { int cont_dev; // variable contador del numero de instrucciones DEV en un metodo Atr_Expr AS_Literal(AST lit){ Atr_Expr result = new Atr_Expr(); AST tipo; if(lit == null) return null; switch(lit.getType()){ case LIT_ENTERO: tipo = #(#[ENTERO,"entero"]); break; case LIT_REAL: tipo = #(#[REAL,"real"]); break; case LIT_CAR: tipo = #(#[CARACTER,"caracter"]); break; case CIERTO: case FALSO: tipo = #(#[LOGICO,"logico"]); break; default: return null; } result.setTipo(tipo); result.setLVal(false); result.setRVal(true); return result; } Atr_Expr AS_Acceso_Simple(AST dec){ Atr_Expr result = new Atr_Expr(); AST tipo = null; if (dec == null) return null; switch(dec.getType()){ case MODULO: System.out.println("ERROR CT: el tipo es modulo"); return null; case CLASE: //acceso a clase no instanciable tipo = dec; result.setLVal(false); result.setRVal(false); break; case ATRIBUTO://acceso a un atributo de la propia clase tipo = dec.getFirstChild().getNextSibling(); result.setLVal(true); result.setRVal(true); break; case METODO: //acceso a un metodo de la propia clase tipo = dec.getFirstChild(); result.setLVal(false); result.setRVal(false); break; case PARAMETRO: tipo = dec.getFirstChild().getNextSibling(); result.setLVal(false); result.setRVal(true); break; case VARIABLE_LOCAL: tipo = dec.getFirstChild().getNextSibling(); result.setLVal(true); result.setRVal(true); break; case ERROR: return null; } result.setTipo(tipo); return result; } Atr_Expr AS_Acceso_Objeto(Atr_Expr atr_raiz, AST raiz, AST atrib){ Atr_Expr result = new Atr_Expr(); AST tipo, tipo_raiz, aux; if(atr_raiz == null || raiz == null || atrib ==null) return null; //comprobar que el tipo de la raiz sea clase tipo_raiz = atr_raiz.getTipo(); if(tipo_raiz.getType() != CLASE){ System.out.println("ERROR CT: "+raiz.getFirstChild().getText()+" no es una clase"); return null; } //si la raiz es una clase instanciable if(raiz.getFirstChild().getNextSibling().getType() == CLASE){ if(tipo_raiz.getFirstChild().getNextSibling().getType() != NO_INST){ System.out.println("ERROR CT: "+raiz.getFirstChild().getText()+" es una clase instanciable"); return null; } } //si la raiz es un objeto else{ if(tipo_raiz.getFirstChild().getNextSibling().getType() != INST){ System.out.println("ERROR CT: "+raiz.getFirstChild().getText()+" es un objeto de clase no instanciable"); return null; } } //comprobar que "atrib" sea un atributo o metodo de la clase y ademas sea visible aux = tipo_raiz.getFirstChild().getNextSibling().getNextSibling(); while(aux!= null){ if(aux.getType() == METODO){ if(aux.getFirstChild().getFirstChild().equals(atrib)) break; }else{ //atributo if(aux.getFirstChild().equals(atrib)) break; } aux = aux.getNextSibling(); } if(aux == null){ System.out.println("ERROR CT: el atributo "+atrib.getText()+" no pertenece a la clase "+raiz.getFirstChild().getText()); return null; } if(aux.getFirstChild().getNextSibling().getNextSibling().getType() != VISIBLE){ System.out.println("ERROR CT: el atributo "+atrib.getText()+" no es visible"); return null; } //tipo de la expresion if(aux.getType() == METODO){ tipo = aux.getFirstChild(); result.setLVal(false); result.setRVal(false); }else{ //atributo tipo = aux.getFirstChild().getNextSibling(); result.setLVal(true); result.setRVal(true); } result.setTipo(tipo); return result; } //hay que pasarle la raiz para saber el nombre de la raiz cuando no es un metodo Atr_Expr AS_Llamada(Atr_Expr atr_raiz, LinkedList expresiones){ ListIterator it = expresiones.listIterator(); Atr_Expr result = new Atr_Expr(); AST pars, par_f, tipo; Atr_Expr par_r; //comprobar que atr_raiz no se a null if(atr_raiz == null || expresiones == null){ return null; } //comprobar que la raiz sea de tipo prototipo if(atr_raiz.getTipo().getType() != PROTOTIPO){ System.out.println("ERROR CT: "+atr_raiz.getTipo().getText()+" no es un metodo."); return null; } //comprobar que los parametros reales coinciden con los formales pars = atr_raiz.getTipo().getFirstChild().getNextSibling(); par_f = pars.getFirstChild(); while (it.hasNext() && (par_f != null)){ par_r = (Atr_Expr)it.next(); if(! par_f.getFirstChild().getNextSibling().equalsTree(par_r.getTipo())){ System.out.println("ERROR CT: El numero de parametros en el metodo \""+atr_raiz.getTipo().getFirstChild().getText()+"\" es incorrecto."); return null; } par_f = par_f.getNextSibling(); } if(it.hasNext() && (par_f == null)){ System.out.println("ERROR CT: El numero de parametros en el metodo \""+atr_raiz.getTipo().getFirstChild().getText()+"\" es incorrecto."); return null; } if(!it.hasNext() && (par_f != null)){ System.out.println("ERROR CT: El numero de parametros en el metodo \""+atr_raiz.getTipo().getFirstChild().getText()+"\" es incorrecto."); return null; } //el tipo de la expresion es el rango del metodo tipo = atr_raiz.getTipo().getFirstChild().getNextSibling().getNextSibling().getFirstChild(); result.setLVal(false); result.setRVal(true); result.setTipo(tipo); return result; } Atr_Expr AS_Acceso_Tabla(Atr_Expr atr_raiz, LinkedList expresiones){ if(atr_raiz == null || expresiones == null) return null; ListIterator it = expresiones.listIterator(); Atr_Expr result = new Atr_Expr(); Atr_Expr aux; AST tipo; int tam = 0; //comprobar que el tipo de la raizes una formacion //TODO if(atr_raiz.getTipo().getType() != FORMACION){ System.out.println("ERROR CT: intentando acceder a \""+atr_raiz.getTipo().getText()+"\" como formacion"); return null; } //comprobar que el numero de expresiones coincida con el numero de dimensiones while(it.hasNext()){ tam++; aux = (Atr_Expr) it.next(); if(aux == null) return null; if(aux.getTipo().getType() != ENTERO){ System.out.println("ERROR CT: no coinciden el numero de expresiones en el acceso a formacion"); return null; } } if(tam != atr_raiz.getTipo().getFirstChild().getNumberOfChildren()){ System.out.println("ERROR CT: no coinciden el numero de expresiones en el acceso a formacion"); return null; } tipo = atr_raiz.getTipo().getFirstChild().getNextSibling(); result.setTipo(tipo); result.setLVal(atr_raiz.getLVal()); result.setRVal(atr_raiz.getRVal()); return result; } //AS DE EXPRESIONES //Expresiones binarias aritmeticas Atr_Expr AS_Exp_Bin_Arit(Atr_Expr e1, Atr_Expr e2){ Atr_Expr result = new Atr_Expr(); String men=""; if(e1 == null || e2 == null) return null; //Comprobamos que e1 y e2 sean consultables if(!e1.getLVal() || !e2.getRVal()){ if (!e2.getRVal()) men="ERROR LR: la expresion no puede aparecer a la derecha de una expresion binaria" ; if (!e1.getLVal()) men="ERROR LR: la expresion no puede aparecer a la izquierda de una expresion binaria" ; System.out.println(men); return null; } //Comprobamos que e1 y e2 sean numericas y compatibles if((e1.getTipo().getType()!=ENTERO) && (e1.getTipo().getType()!=REAL) || (e2.getTipo().getType()!=ENTERO) && (e2.getTipo().getType()!=REAL)){ System.out.println("ERROR CT: no son expresiones numericas ("+e1.getTipo().getText()+" y "+e2.getTipo().getText()+")"); return null; } if(!e1.getTipo().equals(e2.getTipo())){ System.out.println("ERROR CT: Los tipos no son compatibles ("+e1.getTipo().getText()+" y "+e2.getTipo().getText()+")"); return null; } //Calculamos el tipo result.setTipo(e1.getTipo()); result.setLVal(false); result.setRVal(true); return result; } //Expresiones binarias logicas Atr_Expr AS_Exp_Bin_Log(Atr_Expr e1, Atr_Expr e2){ Atr_Expr result = new Atr_Expr(); String men = ""; if(e1 == null || e2 == null) return null; //Comprobar que las expresiones son consultables if(!e1.getLVal() || !e2.getRVal()){ if (!e2.getRVal()) men ="ERROR LR: la expresion no puede aparecer a la derecha de la expresion" ; if (!e1.getLVal()) men ="ERROR LR: la expresion "+e1.getTipo().getFirstChild().getText()+" no puede aparecer a la izquierda de la expresion" ; System.out.println(men); return null; } //Comprobamos que sean de tipo logico if((e1.getTipo().getType()!=LOGICO) || (e2.getTipo().getType()!=LOGICO)){ if (e1.getTipo().getType()!=LOGICO) men = "ERROR CT: la expresion "+e1.getTipo().getFirstChild().getText()+"no es de tipo logico"; if (e2.getTipo().getType()!=LOGICO) men = "ERROR CT: la expresion "+e2.getTipo().getFirstChild().getText()+"no es de tipo logico"; System.out.println(men); return null; } //Calculamos el tipo result.setTipo(e1.getTipo()); result.setLVal(false); result.setRVal(true); return result; } //Expresiones binarias relacionales Atr_Expr AS_Exp_Bin_Rel(Atr_Expr e1, Atr_Expr e2, AST operador){ Atr_Expr result = new Atr_Expr(); AST tipo; String men = ""; if(e1 == null || e2 == null || operador == null) return null; //Comprobamos que las expresiones son consultables if(!e1.getLVal() || !e2.getRVal()){ if (!e2.getRVal()) men ="ERROR LR: la expresion no se puede consultar en la expresion binaria" ; if (!e1.getLVal()) men ="ERROR LR: la expresion "+e1.getTipo().getFirstChild().getText()+" no puede aparecer a la izquierda en la expresion"; System.out.println(men); return null; } //No dejamos que se utilicen formaciones y comprobamos la compatibilidad de las expresiones if(e1.getTipo().getType()==FORMACION){ System.out.println("ERROR CT: no puede tener formaciones en expresiones relacionales"); return null; } men = "ERROR CT: Los tipos no son compatibles ("+e1.getTipo().getText()+" y "+e2.getTipo().getText()+")"; if(!e1.getTipo().equals(e2.getTipo())){ System.out.println(men); return null; } if((e1.getTipo().getType() == CLASE) && (!e1.getTipo().getFirstChild().equals(e2.getTipo().getFirstChild()))){ //Comparamos las clases por nombre System.out.println(men); return null; } //Miramos los grupos de operadores if((operador.getType()!=IGUAL && operador.getType()!=DISTINTO) && (e1.getTipo().getType()==CLASE || e1.getTipo().getType()==LOGICO)){ System.out.println("ERROR CT: el operador \""+operador.getText()+"\" no esta permitido para los tipos usados ("+e1.getTipo().getText()+" y "+e2.getTipo().getText()+")"); return null; } //Establecemos el tipo tipo = #(#[LOGICO,"logico"]); result.setTipo(tipo); result.setLVal(false); result.setRVal(true); return result; } //Expresiones unarias aritmeticas == MENOS UNARIO Atr_Expr AS_Exp_Una_Arit(Atr_Expr e){ Atr_Expr result = new Atr_Expr(); String men=""; if(e == null) return null; //e tiene que ser consultable if(!e.getRVal()){ men ="ERROR LR: la expresion no es consultable" ; System.out.println(men); return null; } //comprobar que e es de tipo numerico if( e.getTipo().getType()!=ENTERO && e.getTipo().getType()!=REAL){ System.out.println("ERROR CT: el menos unario solo puede ser utilizado en expresiones numericas"); return null; } //Establecemos el tipo result.setTipo(e.getTipo()); result.setLVal(false); result.setRVal(true); return result; } //Expresiones unarias logicas == NEGACION //Identica a la anterior Atr_Expr AS_Exp_Una_Log(Atr_Expr e){ Atr_Expr result = new Atr_Expr(); if(e == null) return null; //e tiene que ser consultable if(!e.getRVal()){ System.out.println("ERROR LR: la expresion no es consultable" ); return null; } //comprobar que e es de tipo numerico if( e.getTipo().getType()!=LOGICO){ System.out.println("ERROR CT: la negacion solo se puede utilizar con expresiones logicas"); return null; } //Establecemos el tipo result.setTipo(e.getTipo()); result.setLVal(false); result.setRVal(true); return result; } //Instrucciones //Asignacion void AS_Asignacion(Atr_Expr e1, Atr_Expr e2, AST e3, AST e4){ //comprobar si alguno es null String men = ""; if(e1==null || e2 == null) return; //Comprobamos la consultabilidad de las expresiones if(!e1.getLVal() || !e2.getRVal()){ if (!e2.getRVal()) men ="ERROR LR: la expresion "+e4.getFirstChild().getText()+" no puede aparecer a la derecha de una asignacion." ; if (!e1.getLVal()) men ="ERROR LR: el "+e3.getFirstChild().getNextSibling().getText()+" "+e3.getFirstChild().getText()+" no puede aparecer a la izquierda de una asignacion." ; System.out.println(men); return; } //No dejamos asignar formaciones y comprobamos la compatibilidad de tipos if(e1.getTipo().getType()==FORMACION){ System.out.println("ERROR CT: no dejamos asignar formaciones"); } men = "ERROR CT: Los tipos no son compatibles ("+e1.getTipo().getText()+" y "+e2.getTipo().getText()+")"; if(!e1.getTipo().equals(e2.getTipo())){ System.out.println(men); } if((e1.getTipo().getType() == CLASE) && (!e1.getTipo().getFirstChild().equals(e2.getTipo().getFirstChild()))){ //Comparamos las clases por nombre System.out.println(men); } } //Condiciones void AS_Condicional(Atr_Expr e){ String men = ""; if (e == null) return; if(!e.getRVal()){ men ="ERROR LR: la expresion no es consultable" ; System.out.println(men); return; } //Comprobamos que es de tipo logico if(e.getTipo().getType()!=LOGICO){ System.out.println("ERROR CT: no es un tipo logico"); } } //Instruccion de devolucion int AS_Devolucion(AST tipo_dev, Atr_Expr e, int cont){ String men = ""; // String men = "ERROR CT: Los tipos no son compatibles (entero y real)" if(tipo_dev == null || e == null) return cont+1; //Comprobamos que el metodo sea funcional if(cont == -1){ System.out.println("ERROR CT: el metodo no es funcional"); return -1; } //Comprobar que la expresion e es consultable if(!e.getRVal()){ System.out.println("ERROR CT: la expresion no es consultable, no se puede devolver"); } men = "ERROR CT: Los tipos no son compatibles ("+e.getTipo().getText()+" y "+tipo_dev.getText()+")"; //Comprobamos que el tipo de la expresion es compatible con el tipo que se devuelve if(!e.getTipo().equals(tipo_dev)){ System.out.println(men); } if(tipo_dev.getType()==CLASE && (!tipo_dev.getFirstChild().equals(e.getTipo().getFirstChild()))){ System.out.println(men); } if(tipo_dev.getType()==FORMACION && (!tipo_dev.equals(e.getTipo()))){ System.out.println(men); } return cont + 1; } Atr_Expr AS_Crear(Atr_Expr as, AST clase){ if (as == null || clase == null){ System.out.println("ERROR CT: no se puede crear"); return null; } //comprobar que el tipo de la variable es el mismo que el del interior de crear Atr_Expr result = new Atr_Expr(); AST tipo = as.getTipo(); if(tipo.getType() != CLASE){ System.out.println("ERROR CT: no es una clase"); return null; } if(!(tipo.getFirstChild().getNextSibling().getType() == INST)){ System.out.println("ERROR CT: la clase no es instanciable"); return null; } AST tipo_var = tipo.getFirstChild(); AST interior = clase; if(!tipo_var.getText().equals(interior.getText())){ if(interior.getType() == ACCESO_SIMPLE) System.out.println("ERROR CT: Los tipos no son compatibles ("+tipo_var.getText()+" y "+interior.getFirstChild().getText()+")"); else System.out.println("ERROR CT: Los tipos no son compatibles ("+tipo_var.getText()+" y "+interior.getText()+")"); return null; } result.setLVal(false); result.setRVal(false); //el tipo es el de la variable result.setTipo(tipo); return result; } //AS Escribir void AS_Escribir(Atr_Expr e, AST exp){ if (e == null){ if(exp.getType() == ACCESO_SIMPLE) System.out.println("ERROR CT: no se puede escribir "+ exp.getFirstChild().getText()); else System.out.println("ERROR CT: no se puede escribir "+ exp.getText()); return; } //Comprobamos que la expresion se pueda consultar if(!e.getRVal()){ System.out.println("ERROR CT: la expresion no es consultable, no se puede escribir"); } } //AS Entero A Real Atr_Expr AS_Entero_A_Real(Atr_Expr e1){ Atr_Expr result = new Atr_Expr(); if (e1 == null) return null; AST tipo = e1.getTipo(); if(tipo.getType() != ENTERO){ System.out.println("ERROR CT: El tipo del parametro del operador enteroareal es incorrecto."); return null; } result.setTipo(#(#[REAL,"real"])); result.setLVal(false); result.setRVal(true); return result; } Atr_Expr AS_Real_A_Entero(Atr_Expr e1){ Atr_Expr result = new Atr_Expr(); if (e1 == null) return null; AST tipo = e1.getTipo(); if(tipo.getType() != REAL){ System.out.println("ERROR CT: El tipo del parametro del operador realaentero es incorrecto."); return null; } result.setTipo(#(#[ENTERO,"entero"])); result.setLVal(false); result.setRVal(true); return result; } } // ========= FIN DE DECLARACION DE FUNCIONES declaracion_modulo: #(MODULO nombre_modulo definicion_modulo); nombre_modulo : IDENT ; definicion_modulo: (importacion)? (exportacion)+ (implementacion)? ; importacion : #(IMPORTACION lista_ident); lista_ident: (IDENT)+; exportacion : #(EXPORTACION lista_declaraciones_clases); implementacion : #(IMPLEMENTACION lista_declaraciones_clases); lista_declaraciones_clases: (declaracion_clase)* ; declaracion_clase : #(CLASE nombre_clase cualificador_clase definicion_clase) ; cualificador_clase : INST | NO_INST ; nombre_clase : IDENT ; definicion_clase : declaraciones_elementos_clase ; declaraciones_elementos_clase : (declaracion_elemento_clase)* ; declaracion_elemento_clase : #(METODO declaracion_metodo cualificador_elemento_clase) | #(ATRIBUTO IDENT tipo cualificador_elemento_clase) ; cualificador_elemento_clase: OCULTO | VISIBLE ; declaracion_metodo {AST tipodev;} : tipodev =prototipo_metodo definicion_metodo[tipodev] { if (cont_dev == 0){ System.out.println("ERROR: Metodo funcional que no devuelve nada"); System.exit(-1); } } ; prototipo_metodo returns [AST tipodev=null]: #(PROTOTIPO IDENT #(PARAMETROS declaracion_parametros) #(RESULTADO ( t: tipo {cont_dev = 0; // inicializa el contador de instrucciones DEV tipodev = t; } | v: VACIO {cont_dev = -1; // marca a -1 para indicar que es un procedimiento tipodev = v; } ))) ; declaracion_parametros : (declaracion_parametro)* ; declaracion_parametro : #(PARAMETRO IDENT tipo) ; definicion_metodo [AST tipodev]: #(DEFINICION #(VARIABLES_LOCALES declaracion_variables_locales) #(INSTRUCCIONES instrucciones[tipodev])) ; declaracion_variables_locales : (declaracion_variable_local)* ; declaracion_variable_local : #(VARIABLE_LOCAL IDENT tipo) ; declaracion_error : ERROR; instrucciones [AST tipodev] : (instruccion[tipodev])* ; instruccion [AST tipodev] : #(INSTRUCCION ( instruccion_simple[tipodev] | instruccion_compuesta[tipodev])) ; instruccion_simple [AST tipodev] : crear | llamada_metodo | escribir | asignacion | retorno [tipodev] ; crear{Atr_Expr e1;} : #(CREAR e1=expresion e2:expresion) {AS_Crear(e1,#e2);} ; escribir{Atr_Expr e1;}: #(ESCRIBIR e1=e:expresion) {AS_Escribir(e1, #e);}; instruccion_compuesta [AST tipodev] : condicion [tipodev] | iteracion [tipodev] ; asignacion {Atr_Expr e1, e2;}: #(ASIGNACION e1=e3:expresion e2=e4:expresion ) { AS_Asignacion(e1,e2,#e3,#e4); }; retorno [AST tipodev] {Atr_Expr e;}: #(DEV e=expresion) {/*AS_Devolucion(tipodev, e); cont_dev++;*/ cont_dev=AS_Devolucion(tipodev,e,cont_dev); } ; llamada_metodo {Atr_Expr a, res; LinkedList l;}: #(LLAMADA a=acceso #(EXPRESIONES l=lista_expresiones)) {res=AS_Llamada(a,l); if (res != null && res.getTipo().getType() != VACIO){ System.out.println("ERROR: Llamada a funcion sin asignar valor devuelto."); System.exit(1); } } ; lista_expresiones returns [LinkedList l= new LinkedList()] {Atr_Expr e;}: (e=expresion {l.add(e);})* ; condicion [AST tipodev] {Atr_Expr e;} : #(SI e=expresion #(INSTRUCCIONES instrucciones[tipodev]) (#(INSTRUCCIONES instrucciones[tipodev]))?) {AS_Condicional(e); } ; iteracion [AST tipodev] {Atr_Expr e;} : #(MIENTRAS e=expresion #(INSTRUCCIONES instrucciones[tipodev])) {AS_Condicional(e); } ; expresion returns [Atr_Expr res=null] {Atr_Expr e1,e2; LinkedList l;}: #(O e1=expresion e2=expresion) {res=AS_Exp_Bin_Log( e1, e2); } | #(Y e1=expresion e2=expresion) {res=AS_Exp_Bin_Log( e1, e2); } | #(NO e1=expresion) {res=AS_Exp_Una_Log( e1); } | #(op1:MAYOR e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op1); } | #(op2:MAYOR_IGUAL e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op2); } | #(op3:MENOR e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op3); } | #(op4:MENOR_IGUAL e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op4); } | #(op5:IGUAL e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op5); } | #(op6:DISTINTO e1=expresion e2=expresion) {res=AS_Exp_Bin_Rel( e1, e2, op6); } | #(MAS e1=expresion e2=expresion) {res=AS_Exp_Bin_Arit( e1, e2); } | #(MENOS e1=expresion e2=expresion) {res=AS_Exp_Bin_Arit( e1, e2); } | #(MENOSUNARIO e1=expresion) {res=AS_Exp_Una_Arit( e1); } | #(POR e1=expresion e2=expresion) {res=AS_Exp_Bin_Arit( e1, e2); } | #(DIVISION e1=expresion e2=expresion) {res=AS_Exp_Bin_Arit( e1, e2); } | #(LLAMADA e1=acceso #(EXPRESIONES l=lista_expresiones)) {res=AS_Llamada( e1, l); if (res != null){ if (res.getTipo().getType() == VACIO){ System.out.println("ERROR: No se puede recoger el valor devuelto por un procedimiento (no devuelve nada)."); System.exit(1); } } } | #(ACCESO_TABLA e1=acceso #(EXPRESIONES l=lista_expresiones_nv)) {res=AS_Acceso_Tabla( e1, l); } | e1=acceso {res=e1;} | i:LIT_ENTERO {res=AS_Literal( i);} | j:LIT_REAL {res=AS_Literal( j);} | k:LIT_CAR {res=AS_Literal( k);} | m:CIERTO {res=AS_Literal( m);} | n:FALSO {res=AS_Literal( n);} | #(ENTERO_A_REAL e1=expresion) {res = AS_Entero_A_Real(e1);} | #(REAL_A_ENTERO e1=expresion) {res = AS_Real_A_Entero(e1);} | ERROR ; acceso returns [Atr_Expr res=null] {Atr_Expr e;}: e=acceso_simple {res=e;} | #(ACCESO_OBJETO e=r:acceso_simple a:IDENT) { res=AS_Acceso_Objeto( e, r, a); } ; acceso_simple returns [Atr_Expr res=null]: #(ACCESO_SIMPLE IDENT d:declaracion_acceso) {res=AS_Acceso_Simple(#d);} ; declaracion_acceso: declaracion_modulo | declaracion_clase | declaracion_elemento_clase | declaracion_parametro | declaracion_variable_local | declaracion_error ; lista_expresiones_nv returns [LinkedList l= new LinkedList()] {Atr_Expr e;}: (e=expresion {l.add(e);})+ ; tipo : tipo_predefinido_simple | tipo_predefinido_compuesto | IDENT | declaracion_error ; tipo_predefinido_simple : ENTERO | REAL | LOGICO | CARACTER ; tipo_predefinido_compuesto : formacion ; formacion {AST t=null;}: #(FORMACION #(LISTA_ENTEROS lista_enteros)(tipo_predefinido_simple)) ; lista_enteros : (LIT_ENTERO)+ ;