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