Acceso a clase
[PL2.git] / Anasint.g
1 /*
2  *
3  * Referencia adelantada
4  * se intentan resolver los nombres, los que no se resuelvan se almacenan en al tabla de simbolos
5  * se recorren los no resueltos, y se le asigna el nombre correspondiente
6  * se recorre el ambito modulo, y se instalan las declaraciones en los no resueltos
7  *
8 **/
9
10 header{
11         import java.util.*;
12         import antlr.*;
13         import java.io.*;
14 }
15
16 class Anasint extends Parser;
17
18 options{
19         buildAST=true;
20 }
21
22 tokens{
23         PROGRAMA;
24         VISIBLE;
25         OCULTO;
26         NO_INST;
27         ATRIBUTO;
28         METODO;
29         PROTOTIPO;
30         PARAMETRO;
31         PARAMETROS;
32         EXPRESIONES;
33         RESULTADO;
34         DEFINICION;
35         VACIO;
36     VARIABLE_LOCAL;
37         VARIABLES_LOCALES;
38         INSTRUCCION;
39         INSTRUCCIONES;
40         MENOSUNARIO;
41         LLAMADA;
42         ACCESO_TABLA;
43         ACCESO_OBJETO;
44         ACCESO_SIMPLE;
45         LISTA_ENTEROS;
46         ERROR;
47 }
48
49 {
50         logFile log;
51         int margen = 0;
52         Pila_Ambitos pilaambitos = new Pila_Ambitos();
53         Tabla_Global t = new Tabla_Global();
54         Hashtable<String,String> declaraciones = new Hashtable<String,String>();
55
56         LinkedList<Simbolo_no_resuelto> no_resueltos = new LinkedList<Simbolo_no_resuelto>();
57         
58         void ambito_abrir_programa(){
59                 if(pilaambitos.vacia() == true){
60                         Ambito a = new Ambito("programa","PROGRAMA",null,null);
61                         pilaambitos.apilar_ambito(a);
62                 }
63         }
64   
65         void ambito_abrir(AST nombre, String tipo){
66                 Ambito act = pilaambitos.ambito_actual();
67                 String tipoAct = act.getTipo();
68                 if(tipo.equals("MODULO") && tipoAct.equals("PROGRAMA")
69                         || tipo.equals("CLASE") && tipoAct.equals("MODULO")
70                         || tipo.equals("METODO") && tipoAct.equals("CLASE")){
71                         Ambito A = new Ambito(nombre.getText(), tipo, null, act);
72                         pilaambitos.apilar_ambito(A);
73                 }
74         }
75         
76         void ambito_cerrar(){
77                 if(pilaambitos.vacia() == false){
78                         ambito_instalar();
79                         pilaambitos.desapilar_ambito();
80                 }
81         }
82         void ambito_cerrar_programa(){
83                 if(pilaambitos.vacia() == false && pilaambitos.ambito_actual().getTipo().equals("PROGRAMA")){
84                         ambito_instalar();
85                         pilaambitos.desapilar_ambito();
86         }
87         }
88         
89         //XX TODO referencia adelantada
90         void ambito_instalar(){
91                 Ambito a = pilaambitos.ambito_actual();
92                 t.tablaambitos.apilar_ambito(a);
93                 if(a.getTipo().equals("MODULO")){
94                         t.ambitomodulo = a;
95                 }
96         }
97         
98         AST crear_declaracion_modulo(AST nombre_modulo, AST definicion_modulo){
99                 String m = nombre_modulo.getText();
100                 AST M = #(#[MODULO, "modulo"],nombre_modulo, definicion_modulo);
101                 Simbolo S = new Simbolo(m, M);
102                 pilaambitos.ambito_actual().setDeclaracion(S);
103                 return M;
104         }
105         
106         AST crear_declaracion_clase (AST nombre_clase, AST cualificador_clase, AST definicion_clase){
107                 String c = nombre_clase.getText();
108                 AST C = #(#[CLASE,"clase"],nombre_clase, cualificador_clase, definicion_clase);
109                 Simbolo S = new Simbolo(c,C);
110                 pilaambitos.ambito_actual().setDeclaracion(S);
111                 return C;
112         }
113
114         AST crear_declaracion_metodo (AST declaracion_metodo, AST cualificador_metodo){
115                 AST MT = #(#[METODO,"metodo"], declaracion_metodo, cualificador_metodo);
116                 String mt = MT.getFirstChild().getFirstChild().getText();
117                 Simbolo S = new Simbolo(mt,MT);
118                 pilaambitos.ambito_actual().setDeclaracion(S);
119                 return MT;
120         }
121         
122         AST crear_declaracion_atributo (AST nombre_atributo, AST tipo_atributo, AST cualificador_atributo){
123                 declaraciones.put(nombre_atributo.getText(), tipo_atributo.getText());
124         String a = nombre_atributo.getText();
125         AST A = #(#[ATRIBUTO,"atributo"], nombre_atributo, tipo_atributo, cualificador_atributo);
126         Simbolo S = new Simbolo(a, A);
127         pilaambitos.ambito_actual().setDeclaracion(S);
128         return A;
129         }
130
131         AST crear_declaracion_parametro (AST nombre_parametro, AST tipo_parametro){
132                 String p = nombre_parametro.getText();
133                 declaraciones.put(nombre_parametro.getText(), tipo_parametro.getText());
134                 AST P = #(#[PARAMETRO,"parametro"], nombre_parametro, tipo_parametro);
135                 Simbolo S = new Simbolo(p, P);
136                 pilaambitos.ambito_actual().setDeclaracion(S);
137                 return P;
138                 
139         }
140         
141         
142         AST crear_declaracion_variable_local (AST nombre_variable, AST tipo_variable){
143                 String v = nombre_variable.getText();
144                 declaraciones.put(nombre_variable.getText(), tipo_variable.getText());
145                 AST V = #(#[VARIABLE_LOCAL,"variable_local"], nombre_variable, tipo_variable);
146                 Simbolo S = new Simbolo(v, V);
147                 pilaambitos.ambito_actual().setDeclaracion(S);
148                 return V;
149         }
150
151         AST ambito_tratar_acceso_simple (AST ident){
152                 String acc = ident.getText();
153                 AST dec_acc = null;
154                 AST ACC = null;
155                 Simbolo s;
156                 if ((s=pilaambitos.buscar_simbolo(acc)) != null){
157                 dec_acc = s.getDeclaracion(); // AST de la declaracion del acceso simple
158                 ACC = #(#[ACCESO_SIMPLE,"acceso_simple"], ident, dec_acc);
159                         log.writeNoIndent(" ("+dec_acc.getText()+")\n");
160                 }
161                 else{
162                         //referencia adelantada o error
163                         String n = t.accesossinresolver.setAcceso(acc, pilaambitos.ambito_actual(), ((ArbolLineas)ident).getLinea());
164                         AST LI = #(#[LIT_ENTERO, "lit_entero"]);
165                         LI.setText(n);
166                         ACC = #(#[ACCESO_SIMPLE, "acceso_simple"], ident, LI);
167                 }
168                 
169                 return ACC;
170         }
171
172         AST ambito_tratar_ident_tipo (AST ident){
173                 String men = "";
174                 String tipo = ident.getText();
175                 men = "ERROR RN: Identificador de tipo "+tipo+" no declarado";
176                 Ambito amb = pilaambitos.ambito_actual();
177                 while (amb != null && !amb.getTipo().equals("MODULO"))
178                         amb = amb.getContenedor();
179                 if (amb == null){
180                         System.out.println("ERROR: El tipo" + tipo + "no es un tipo clase"); // el tipo no es un tipo clase
181                         return #(#[ERROR,"error"]);
182                 }
183                 Simbolo simb = amb.getDeclaracion(tipo);
184                 if (simb == null){
185                         //referencia adelantada o error
186                         Identificador_Tipo IT = new Identificador_Tipo(tipo);
187                         IT.setLinea(((ArbolLineas)ident).getLinea());
188                         t.identtiposinresolver.setIdentificador(IT);
189                 }
190                 return ident;
191         }
192         
193         
194         public AST arbol_crear(AST e1, AST e2){
195                 if(e2 == null){
196                         return #(#[CREAR,"crear"],e1, #[ERROR,"error"]);
197                 }else
198                         return  #(#[CREAR,"crear"],e1, e2);
199         }
200         
201         public AST arbol_escribir(AST e){
202                 if(e == null){
203                         return #(#[ERROR,"error"]);
204                 }else
205                         return  #(#[ESCRIBIR,"escribir"],e);
206         }
207
208         //comprueba que existe la clase programa y el metodo inicio en esta
209         public void comprobarPrograma(AST modulo){
210                 boolean programa=false;
211                 AST clase = modulo.getFirstChild().getNextSibling();
212                 while (!clase.getText().equals("exportacion")){
213                         clase = clase.getNextSibling();
214                 }
215                 clase = clase.getFirstChild();
216                 String nombre = clase.getFirstChild().getText();
217                 while(true){
218                         if(nombre.equals("Programa") && !programa){
219                                 programa = true;
220                                 if(clase.getFirstChild().getNextSibling().getText().equals("inst")){
221                                         System.out.println("ERROR AS: La clase Programa tiene que ser no instanciable");
222                                 }
223                                 comprobarInicio(clase);
224                         }
225                         
226                         clase = clase.getNextSibling();
227                         if(clase == null)
228                                 break;
229                         nombre = clase.getFirstChild().getText();
230                 }
231                 if(!programa){
232                         System.out.println("ERROR AS: No se ha definido la clase Programa");
233                 }
234         }
235         
236         public void comprobarInicio(AST Prog){
237                 boolean inicio = false;
238
239                 AST modulo = Prog.getFirstChild().getNextSibling().getNextSibling();
240                 if(modulo != null){
241                         while(modulo.getType() != METODO && modulo != null){
242                                 modulo = modulo.getNextSibling();
243                         }
244                         if(modulo != null && !modulo.getFirstChild().getFirstChild().getText().equals("inicio")){
245                                 System.out.println("ERROR AS: Debe haber un metodo inicio en la clase Programa, y debe ser unico");
246                         }if(modulo.getNextSibling() != null){
247                                 System.out.println("ERROR AS: Debe haber un metodo inicio en la clase Programa, y debe ser unico");
248                         }
249                 }
250         }
251         
252         
253 }
254         
255 /////////////////////////////////////////////////////////
256 // DECLARACION DE MODULO          
257 /////////////////////////////////////////////////////////
258  
259 declaracion_modulo![String f] returns [Auxiliar tab=null] :
260    {
261         ambito_abrir_programa();
262         log = new logFile(f);
263    }
264    n:nombre_modulo
265    {
266         ambito_abrir (#n,"MODULO");
267         log.write("MODULO: "+#n.getText()+"\n");
268         log.incNivel();
269    }
270    d:definicion_modulo EOF
271    {
272         ambito_cerrar();
273     #declaracion_modulo=crear_declaracion_modulo(#n,#d);
274     //comprobarPrograma(#declaracion_modulo);
275     ambito_cerrar_programa();
276     log.decNivel();
277     log.close();
278     tab = new Auxiliar(t, declaraciones);}
279    ;
280  
281 nombre_modulo : MODULO! IDENT ;
282
283 definicion_modulo :
284    (importacion)?
285    (exportacion)+
286    (implementacion)?
287           ;
288
289 lista_ident: IDENT (COMA! IDENT)*;
290
291 importacion :
292         IMPORTACION^ DOS_PUNTOS! l:lista_ident
293         ;
294
295 exportacion :
296         EXPORTACION^ DOS_PUNTOS!
297         l:lista_declaraciones_clases
298         ;
299
300 implementacion :
301         IMPLEMENTACION^ DOS_PUNTOS!
302         l:lista_declaraciones_clases
303         ;
304
305 lista_declaraciones_clases :    
306    (declaracion_clase)*
307    ;
308
309              
310 ///////////////////////////////////////////////////////////
311 // DECLARACION DE CLASE          
312 ///////////////////////////////////////////////////////////
313  
314 declaracion_clase ! : 
315    c:cualificador_clase 
316    n:nombre_clase
317    {
318         ambito_abrir(#n,"CLASE");
319         log.write("CLASE: "+#n.getText()+"\n");
320         log.incNivel();
321         }
322    d:definicion_clase 
323    {
324         ambito_cerrar();
325     log.decNivel();
326     #declaracion_clase = crear_declaracion_clase(#n,#c,#d);
327     }
328    ;
329
330 cualificador_clase! :  
331     INST {#cualificador_clase = #(#[INST]);}
332    |     {#cualificador_clase = #(#[NO_INST,"no_inst"]);}
333    ;
334
335 nombre_clase : CLASE! IDENT ;
336
337 definicion_clase : 
338    LLAVE_ABIERTA! 
339       declaraciones_elemento_clase 
340    LLAVE_CERRADA! 
341    ; 
342
343 declaraciones_elemento_clase : 
344      (declaracion_elemento_clase)* ;
345
346 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
347 // DECLARACION DE ELEMENTO CLASE: METODO O ATRIBUTO          
348 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
349
350 declaracion_elemento_clase! : 
351     c:cualificador_elemento_clase 
352     ((IDENT PARENTESIS_ABIERTO) => 
353        a:declaracion_metodo 
354        {
355         ambito_cerrar();
356         #declaracion_elemento_clase = crear_declaracion_metodo(#a,#c);
357        }
358        
359     | t:tipo i:IDENT PUNTO_Y_COMA
360        {
361         #declaracion_elemento_clase = crear_declaracion_atributo(#i,#t,#c);
362         log.write("ATRIBUTO: "+#i.getText()+"\n");
363        })
364     ;
365
366 // Cualificador de visibilidad
367 cualificador_elemento_clase! :  
368    OCULTO {#cualificador_elemento_clase = #(#[OCULTO]);}
369    | {#cualificador_elemento_clase = #(#[VISIBLE,"visible"]);}
370    ;
371
372 declaracion_metodo :
373    prototipo_metodo
374    definicion_metodo
375    ;
376    
377 prototipo_metodo! :   
378    i:IDENT
379    {
380    ambito_abrir(#i,"METODO");
381    log.write("METODO: "+#i.getText()+"\n");
382    }
383    PARENTESIS_ABIERTO 
384    p:declaracion_parametros 
385    PARENTESIS_CERRADO 
386    (DEV t:tipo 
387    {#prototipo_metodo = #(#[PROTOTIPO,"prototipo"],#i,#(#[PARAMETROS,"parametros"],#p),#(#[RESULTADO,"resultado"],#t));}
388    | {#prototipo_metodo = #(#[PROTOTIPO,"prototipo"],#i,#(#[PARAMETROS,"parametros"],#p),#(#[RESULTADO,"resultado"],#[VACIO, "vacio"]));}
389    )
390    ;
391
392 declaracion_parametros : 
393       declaracion_parametro (COMA! declaracion_parametro)* 
394     |
395     ;
396
397  ///////////////////////////////////////////////////////////
398 // DECLARACION DE PARAMETRO         
399 ///////////////////////////////////////////////////////////   
400  
401 declaracion_parametro!: t:tipo i:IDENT 
402     {#declaracion_parametro = crear_declaracion_parametro(#i,#t);}
403     ;
404
405 definicion_metodo! : 
406    LLAVE_ABIERTA {log.incNivel();}
407       d:declaraciones_variables_locales  
408       b:bloque     
409    LLAVE_CERRADA {log.decNivel();}
410    {#definicion_metodo=   #(#[DEFINICION,"definicion"],#(#[VARIABLES_LOCALES,"variables_locales"],#d), #b);}
411    ;
412
413 declaraciones_variables_locales  : 
414     (declaracion_variables_locales tipo IDENT) => 
415        declaracion_variables_locales  declaraciones_variables_locales 
416    |(declaracion_variables_locales) =>  
417        declaracion_variables_locales 
418    | 
419    ;
420    
421 declaracion_variables_locales  : 
422    t:tipo! lista_nombres_variables_locales[#t] PUNTO_Y_COMA! ;
423
424 lista_nombres_variables_locales [AST t] : 
425    nombre_variable_local[#t] (COMA! nombre_variable_local[#t])* ;
426   
427  /////////////////////////////////////////////////////////////////
428 // DECLARACION DE VARIABLE LOCAL         
429 //////////////////////////////////////////////////////////////////   
430  
431 nombre_variable_local! [AST t] : 
432    i:IDENT 
433    { #nombre_variable_local = crear_declaracion_variable_local(#i,#t);}
434    ;
435    
436 ///////////////////////////////////////////////////////////
437 // INSTRUCCIONES 
438 ///////////////////////////////////////////////////////////
439 instrucciones : (instruccion)* ;
440
441 instruccion! : 
442    i:instruccion_simple PUNTO_Y_COMA
443    {#instruccion=#(#[INSTRUCCION,"instruccion"],#i);}
444  | j:instruccion_compuesta 
445    {#instruccion=#(#[INSTRUCCION,"instruccion"],#j);}
446  ;
447
448 instruccion_simple : 
449         (expresion ASIGNACION CREAR) => crear
450   | (expresion ASIGNACION) => asignacion
451   | llamada_metodo
452   | escribir
453   | retorno
454   ;
455
456 instruccion_compuesta : 
457      condicion
458    | iteracion
459    ;
460  
461 asignacion! : 
462    e1:expresion ASIGNACION e2:expresion
463    { #asignacion = #(#[ASIGNACION],#e1,#e2); }
464    ;
465     
466  
467 retorno! : DEV e:expresion 
468    { #retorno = #(#[DEV],#e); }
469    ;   
470
471  
472 llamada_metodo! :  
473    i:acceso 
474    PARENTESIS_ABIERTO 
475            s:lista_expresiones 
476    PARENTESIS_CERRADO 
477    { #llamada_metodo = #(#[LLAMADA,"llamada"],#i,#(#[EXPRESIONES,"expresiones"],#s)); }
478    ;
479
480 lista_expresiones :  expresion (COMA! expresion)*
481                   |
482                   ;
483  
484 condicion : SI^ PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO! ENTONCES! 
485                bloque 
486            (SINO! bloque)? FINSI! ;
487
488  
489 iteracion : MIENTRAS^ PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO! HACER! 
490                bloque 
491             FINMIENTRAS! ;    
492
493 bloque!: i:instrucciones 
494         {#bloque=#(#[INSTRUCCIONES,"instrucciones"],#i);}
495 ;
496
497 /////////////////////////////////////////////////////////////
498 // EXPRESIONES 
499 ////////////////////////////////////////////////////////////
500
501 expresion : 
502    expresion_nivel_1 (O^ expresion_nivel_1)*  ;
503    
504 expresion_nivel_1 : 
505    expresion_nivel_2 (Y^ expresion_nivel_2)* ;
506    
507 expresion_nivel_2 : 
508    (NO^)? expresion_nivel_3 ;   
509
510 expresion_nivel_3 : 
511    expresion_nivel_4 
512   ((MAYOR^|MAYOR_IGUAL^|MENOR^|MENOR_IGUAL^|IGUAL^|DISTINTO^) 
513     expresion_nivel_4)? ;
514
515 expresion_nivel_4 :
516      expresion_nivel_5 ((MAS^|MENOS^) expresion_nivel_5)* ;
517    
518 expresion_nivel_5 :
519       expresion_nivel_6 ((POR^|DIVISION^) expresion_nivel_6)* ;
520
521 expresion_nivel_6 :
522         MENOS i:expresion_nivel_7
523         {#expresion_nivel_6=#(#[MENOSUNARIO,"menosunario"],#i);}
524         | expresion_nivel_7
525         ;
526
527 expresion_nivel_7:
528         PARENTESIS_ABIERTO! expresion PARENTESIS_CERRADO!
529   | entero_a_real
530   | real_a_entero
531   | (acceso PARENTESIS_ABIERTO) => llamada_metodo
532   | (acceso CORCHETE_ABIERTO) => acceso_tabla
533   | acceso
534   | LIT_ENTERO
535   | LIT_REAL
536   | LIT_CAR
537   | CIERTO
538   | FALSO
539   ;    
540 //////////////////////////////////////////////////////////////
541 // ACCESOS A TABLAS
542 //////////////////////////////////////////////////////////////
543 acceso_tabla!: c:acceso CORCHETE_ABIERTO d:lista_expresiones_nv CORCHETE_CERRADO
544         {#acceso_tabla=#(#[ACCESO_TABLA,"acceso_tabla"],#c,#(#[EXPRESIONES,"expresiones"],#d));}
545 ;
546
547 //////////////////////////////////////////////////////////////
548 // ACCESOS SIMPLES Y A OBJETOS
549 //////////////////////////////////////////////////////////////
550  
551 acceso!: 
552    (IDENT PUNTO)=> i1:IDENT PUNTO i2:IDENT
553            {
554                 log.write("ACCESO SIMPLE: "+#i1.getText());
555                 #acceso=#(#[ACCESO_OBJETO,"acceso_objeto"], ambito_tratar_acceso_simple(#i1), #i2);
556 }
557  | i:IDENT  
558            {
559            log.write("ACCESO SIMPLE: "+#i.getText());
560                 #acceso = ambito_tratar_acceso_simple(#i);
561            }
562  ;
563
564 lista_expresiones_nv :  
565     expresion (COMA! expresion)*
566                   ;
567
568 //////////////////////////////////////////////////////////
569 // TIPOS
570 /////////////////////////////////////////////////////////
571 tipo : 
572    tipo_predefinido_simple 
573  | tipo_predefinido_compuesto
574  | i:IDENT {#tipo = ambito_tratar_ident_tipo(#i);
575  log.write("IDENTIFICADOR TIPO: "+#i.getText()+"\n");
576  }
577  ;
578
579 tipo_predefinido_simple :
580      ENTERO 
581    | REAL   
582    | LOGICO
583    | CARACTER
584    ;
585
586 tipo_predefinido_compuesto :
587    formacion
588    ;
589  
590 formacion! : FORMACION l:lista_enteros
591          ( t:tipo_predefinido_simple
592             {#formacion = #(#[FORMACION,"formacion"],#(#[LISTA_ENTEROS,"lista_enteros"],#l),#t);}
593             | i:IDENT
594             {#formacion = #(#[FORMACION,"formacion"], #(#[LISTA_ENTEROS,"lista_enteros"],#l), ambito_tratar_ident_tipo(#i));
595                 log.write("IDENTIFICADOR TIPO: "+#i.getText()+"\n");
596 }
597 );
598
599 lista_enteros :  LIT_ENTERO (COMA! LIT_ENTERO)*;
600
601
602 escribir!: ESCRIBIR PARENTESIS_ABIERTO e:expresion PARENTESIS_CERRADO
603 {
604         #escribir = arbol_escribir(#e);
605         try{
606                 log.write("IDENTIFICADOR TIPO: "+#e.getFirstChild().getNextSibling().getFirstChild().getText()+"\n");
607         }catch(NullPointerException n){}
608 };
609
610 //de momento se pasa el arbol completo del tipo, pero creo que con el ident seria 
611 //suficiente para el analisis semantico
612 crear!: e1:expresion ASIGNACION CREAR PARENTESIS_ABIERTO i:expresion PARENTESIS_CERRADO
613 {
614         #crear = arbol_crear(#e1,#i);
615         try{
616                 log.write("IDENTIFICADOR TIPO: "+#i.getFirstChild().getNextSibling().getFirstChild().getText()+"\n");
617         }catch(NullPointerException n){}
618
619 };
620
621 entero_a_real!: ENTERO_A_REAL PARENTESIS_ABIERTO e1:expresion PARENTESIS_CERRADO
622 {## = #(#[ENTERO_A_REAL],#e1);};
623
624 real_a_entero!: REAL_A_ENTERO PARENTESIS_ABIERTO e1:expresion PARENTESIS_CERRADO
625 {## = #(#[REAL_A_ENTERO],#e1);};