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