//*******************************************************************************
//ast.h
//*******************************************************************************
//This file is part of the Orb compiler,
//Copyright (C) 2007 Adrian Fraga Fernandez
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//*******************************************************************************

/***********************************************************************/
/* Arbol sintactico abstracto                                          */
/***********************************************************************/

#ifndef __AST_H
#define __AST_H

#ifndef __ERROR_H
#include "error.h"
#endif

/***********************************************************************/
/* Tipos de nodo						       */
/***********************************************************************/

typedef enum {
	A_PROGRAMA, A_OBJETO, A_IDLISTA, A_MODOBJETOLISTA,A_ABSTRACT,A_HIDDEN,
	A_CUERPOOBJETOLISTA, A_MIEMBRO, A_MIEMBROEXTERNO, A_MODMIEMBROLISTA,
	A_SHARED,A_VAR, A_ARGUMENTOSLISTA, A_PARAMETROSLISTA, A_IF, A_WHILE, 
	A_DOWHILE, A_FOR,A_BREAK,A_CONTINUE, A_RETURN, A_STATIC, A_RESEND, A_LET, A_DECLARACIONLISTA, A_SECUENCIA, A_BLOQUE, A_ASIGNACION, A_OR, A_AND, A_IGUAL, 
	A_NOIGUAL, A_MAYOR, A_MENOR, A_MAYORIGUAL, A_MENORIGUAL, A_IDENTICO, 
	A_NOIDENTICO, A_UNION, A_CONCATENACION, A_SUMA, A_RESTA, A_MULTIPLICACION, 
	A_DIVISION, A_MODULO, A_MENOS, A_MAS, A_NOT, A_IS, A_ISNOT, A_HAS, A_HASNOT, A_ACCESOARRAY, A_ACCESOMIEMBRO, A_IDATOMICO, A_LITERALSECUENCIA, 
	A_LITERALSECUENCIALISTA, A_LITERALCADENA, A_LITERALENTERO, A_LITERALREAL, 
	A_ID,A_ERROR,A_NATIVE,A_LITERALTRUE,A_LITERALFALSE,
	
	A_TIPO_SIZE /* Numero de tipos de nodo */
		    /*(mantener como ultimo elemento de la enumeracion) */
     } 
     A_TIPO;

/***********************************************************************/
/* Anotaciones al árbol sintáctico abstracto                           */
/***********************************************************************/

	/***************************************************************/
	/* Mascaras de bits para codificar modificadores               */
	/***************************************************************/

	/* tipo de dato para el contenido de las máscaras de bits */
					
typedef char A_MOD;
	
	/* Modificadores aplicables a miembros */

#define A_MODABSTRACT		1	/* Miembro abstracto */
#define A_MODNATIVE		2	/* Miembro nativo */
#define A_MODVAR		4	/* Miembro variable */
#define A_MODSHARED		8	/* Miembro compartido */
#define A_MODEXTERN		16 	/* Miembro externo */

	/* Modificadores aplicables a objetos */

#define A_MODABSTRACT		1	/* Objeto abstracto */
#define A_MODNATIVE		2 	/* Objeto nativo */
#define A_MODHIDDEN		4 	/* Objeto oculto */
#define A_MODHERENCIAMULTIPLE	8 	/* Objeto con herencia múltiple */
#define A_MODSOLAPADOS		16	/* Objeto con herencia múltiple y miembros solapados */

/***********************************************************************/
/* Nodos del árbol sintáctico abstracto				       */
/***********************************************************************/

	/************************************/
	/* Cabecera común a todos los nodos */
	/************************************/
	
typedef struct A_NODO {
	A_TIPO tipo __attribute__((packed));
		/* Comentario: Para poder utilizarse como cabecera  */
		/* común a todos los nodos, es necesario que el     */
		/* atributo "tipo" esté en la misma posición rela-  */
		/* tiva de memoria en todas las estructuras; ésta es*/
		/* la única razón de la utilización del atributo    */
		/* "packed", específico del compilador GCC          */
	
} A_NODO;

	/************************************/
	/* Nodo sin anotaciones (terminal)  */
	/************************************/

typedef struct A_NODO0{
	A_TIPO tipo __attribute__((packed));
	E_POSICION posicion;
} A_NODO0;

#define A_NODOERROR 	A_NODO0
#define A_NODOABSTRACT 	A_NODO0
#define A_NODOSHARED 	A_NODO0
#define A_NODODVAR 	A_NODO0
#define A_NODOCONTINUE	A_NODO0
#define A_NODOBREAK	A_NODO0
#define A_NODOHIDDEN	A_NODO0
#define A_NODONATIVE 	A_NODO0
#define A_NODOLITERALTRUE A_NODO0
#define A_NODOLITERALFALSE A_NODO0

	/************************************/
	/* Nodo sin anotaciones (1 hijo)    */
	/************************************/
	
typedef struct A_NODO1 {
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	E_POSICION posicion;
} A_NODO1;

#define A_NODORETURN		A_NODO1
#define A_NODOSTATIC   		A_NODO1
#define A_NODOMAS          	A_NODO1
#define A_NODOMENOS        	A_NODO1
#define A_NODONOT          	A_NODO1
#define A_NODOLITERALSECUENCIA 	A_NODO1

	/************************************/
	/* Nodo sin anotaciones (2 hijos)   */
	/************************************/
	
typedef struct A_NODO2 {
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	E_POSICION posicion;
} A_NODO2;

#define A_NODOOR               	A_NODO2
#define A_NODOAND              	A_NODO2
#define A_NODOIGUAL            	A_NODO2
#define A_NODOIDATOMICO        	A_NODO2
#define A_NODONOIGUAL          	A_NODO2
#define A_NODOIDENTICO         	A_NODO2
#define A_NODONOIDENTICO       	A_NODO2
#define A_NODOMAYOR            	A_NODO2
#define A_NODOMENOR            	A_NODO2
#define A_NODOMAYORIGUAL       	A_NODO2
#define A_NODOMENORIGUAL       	A_NODO2
#define A_NODOUNION            	A_NODO2
#define A_NODOCONCATENACION    	A_NODO2
#define A_NODOSUMA             	A_NODO2
#define A_NODORESTA            	A_NODO2
#define A_NODOMULTIPLICACION   	A_NODO2
#define A_NODODIVISION         	A_NODO2
#define A_NODOMODULO          	A_NODO2
#define A_NODOIS               	A_NODO2
#define A_NODOISNOT            	A_NODO2
#define A_NODOHAS              	A_NODO2
#define A_NODOHASNOT           	A_NODO2
#define A_NODOACCESOARRAY      	A_NODO2
#define A_NODOLITERALSECUENCIALISTA A_NODO2
#define A_NODOMODOBJETOLISTA   	A_NODO2
#define A_NODOIDLISTA          	A_NODO2
#define A_NODOCUERPOOBJETOLISTA	A_NODO2
#define A_NODOIDLISTA          	A_NODO2
#define A_NODODOWHILE          	A_NODO2
#define A_NODOWHILE            	A_NODO2
#define A_NODOMODMIEMBROLISTA  	A_NODO2
#define A_NODOARGUMENTOSLISTA  	A_NODO2
#define A_NODOASIGNACION       	A_NODO2
#define A_NODOPARAMETROSLISTA  	A_NODO2
#define A_NODOSECUENCIA        	A_NODO2
#define A_NODOBLOQUE           	A_NODO2
	
	/************************************/
	/* Nodo sin anotaciones (3 hijos)   */
	/************************************/
	
typedef struct A_NODO3 {
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	A_NODO *h3;
	E_POSICION posicion;
} A_NODO3;

#define A_NODORESEND		A_NODO3
#define A_NODODECLARACIONLISTA	A_NODO3
#define A_NODOIF		A_NODO3
#define A_NODOACCESOMIEMBRO	A_NODO3
#define A_NODOMIEMBROEXTERNO	A_NODO3

	/************************************/
	/* Nodo sin anotaciones (4 hijos)   */
	/************************************/
	
typedef struct A_NODO4 {
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	A_NODO *h3;
	A_NODO *h4;
	E_POSICION posicion;
} A_NODO4;

#define A_NODOFOR		A_NODO4

	/************************************/
	/* Nodo A_ID                        */
	/************************************/	

typedef struct A_NODOID{
	A_TIPO tipo __attribute__((packed));
	E_POSICION posicion;
	
	/* Anotaciones léxicas */
	
	char *id;		/* Identificador 					*/
} A_NODOID;

	/************************************/
	/* Nodo A_LITERALCADENA             */
	/************************************/	

typedef struct A_NODOLITERALCADENA{
	A_TIPO tipo __attribute__((packed));
	E_POSICION posicion;
	
	/* Anotaciones léxicas */

	char *s;		/* Valor del literal 					*/
} A_NODOLITERALCADENA;
	
	/************************************/
	/* Nodo A_LITERALENTERO             */
	/************************************/	

typedef struct A_NODOLITERALENTERO{
	A_TIPO tipo __attribute__((packed));
	E_POSICION posicion;	
	
	/* Anotaciones léxicas */
	
	int i;			/* Valor del literal 					*/
} A_NODOLITERALENTERO;					
	
	/************************************/
	/* Nodo A_LITERALREAL               */
	/************************************/	

typedef struct A_NODOLITERALREAL{
	A_TIPO tipo __attribute__((packed));
	E_POSICION posicion;
	
	/* Anotaciones léxicas */
	
	double f;		/* Valor del literal 					*/
} A_NODOLITERALREAL;

	/************************************/
	/* Nodo A_PROGRAMA                  */
	/************************************/	

typedef struct A_NODOPROGRAMA{
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	E_POSICION posicion;
	
	/* Anotaciones semánticas */
	
	void *tds;		/* Tabla de símbolos (miembros declarados)		*/	
} A_NODOPROGRAMA;

	/************************************/
	/* Nodo A_OBJETO                    */
	/************************************/	

typedef struct A_NODOOBJETO{
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	A_NODO *h3;
	A_NODO *h4;
	E_POSICION posicion;
	
	/* Anotaciones semánticas */
	
	A_MOD mod;		/* Modificadores                       			*/	
	char *id;		/* Identificador (NULL si es un objeto anonimo) 	*/
	void *padres;		/* Tabla de símbolos (padres del objeto) 		*/
	void *tds;       	/* Tabla de símbolos (miembros declarados) 		*/
	void *heredados;	/* Tabla de simbolos (miembros heredados) 		*/
	void *solapados;        /* Tabla de simbolos (miembros solapados) 		*/
	A_NODO *nodoEspNombres;	/* Nodo que define el espacio de nombres que engloba 	*/
				/* al actual 						*/
} A_NODOOBJETO;

	/************************************/
	/* Nodo A_MIEMBRO                   */
	/************************************/	

typedef struct A_NODOMIEMBRO{
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	A_NODO *h3;
	A_NODO *h4;
	E_POSICION posicion;

	/* Anotaciones semánticas */
		
	A_MOD mod;		/* Modificadores 					*/
	char *id;		/* Identificador 					*/
	unsigned char parametros;/* Número de parámetros 				*/
	void *tds;		/* Tabla de símbolos (parámetros declarados)		*/
	A_NODO *nodoEspNombres;	/* Nodo que define el espacio de nombres que engloba 	*/
				/* al actual 						*/
} A_NODOMIEMBRO;

	/************************************/
	/* Nodo A_LET                       */
	/************************************/	

typedef struct A_NODOLET{
	A_TIPO tipo __attribute__((packed));
	A_NODO *h1;
	A_NODO *h2;
	E_POSICION posicion;
	
	/* Anotaciones semánticas */
	
	void *tds;		/* Tabla de símbolos (variables locales declaradas)	*/
	A_NODO *nodoEspNombres;	/* Nodo que define el espacio de nombres que engloba 	*/
				/* al actual 						*/
} A_NODOLET;

/***********************************************************************/
/* Constructores						       */
/***********************************************************************/

	/* Nodos sin anotaciones */

A_NODO *a_nodo0(A_TIPO tipo,E_POSICION *posicion);

#define a_nodoerror(p) 	a_nodo0(A_ERROR,p)
#define a_nodoabstract 	a_nodo0
#define a_nodoshared 	a_nodo0
#define a_nododvar 	a_nodo0
#define a_nodocontinue	a_nodo0
#define a_nodobreak	a_nodo0
#define a_nodohidden	a_nodo0
#define a_nodoliteraltrue a_nodo0
#define a_nodoliteralfalse a_nodo0

A_NODO *a_nodo1(A_TIPO tipo,A_NODO *h1,E_POSICION *posicion);

#define a_nodoreturn		a_nodo1
#define a_nodostatic   		a_nodo1
#define a_nodomas          	a_nodo1
#define a_nodomenos        	a_nodo1
#define a_nodonot          	a_nodo1
#define a_nodoliteralsecuencia 	a_nodo1

A_NODO *a_nodo2(A_TIPO tipo,A_NODO *h1,A_NODO *h2,E_POSICION *posicion);

#define a_nodoor               	a_nodo2
#define a_nodoand              	a_nodo2
#define a_nodoigual            	a_nodo2
#define a_nodoidatomico        	a_nodo2
#define a_nodonoigual          	a_nodo2
#define a_nodoidentico         	a_nodo2
#define a_nodonoidentico       	a_nodo2
#define a_nodomayor            	a_nodo2
#define a_nodomenor            	a_nodo2
#define a_nodomayorigual       	a_nodo2
#define a_nodomenorigual       	a_nodo2
#define a_nodounion            	a_nodo2
#define a_nodoconcatenacion    	a_nodo2
#define a_nodosuma             	a_nodo2
#define a_nodoresta            	a_nodo2
#define a_nodomultiplicacion   	a_nodo2
#define a_nododivision         	a_nodo2
#define a_nodomodulo          	a_nodo2
#define a_nodois               	a_nodo2
#define a_nodoisnot            	a_nodo2
#define a_nodohas              	a_nodo2
#define a_nodohasnot           	a_nodo2
#define a_nodoaccesoarray      	a_nodo2
#define a_nodoliteralsecuencialista a_nodo2
#define a_nodomodobjetolista   	a_nodo2
#define a_nodoidlista          	a_nodo2
#define a_nodocuerpoobjetolista	a_nodo2
#define a_nodoidlista          	a_nodo2
#define a_nododowhile          	a_nodo2
#define a_nodowhile(x,y,p)      a_nodo2(A_WHILE,x,y,p)
#define a_nodomodmiembrolista  	a_nodo2
#define a_nodoargumentoslista  	a_nodo2
#define a_nodoasignacion       	a_nodo2
#define a_nodoparametroslista  	a_nodo2
#define a_nodosecuencia(x,y,p)  a_nodo2(A_SECUENCIA,x,y,p)
#define a_nodobloque(x,y,p)  	a_nodo2(A_BLOQUE,x,y,p)

A_NODO *a_nodo3(A_TIPO tipo,A_NODO *h1,A_NODO *h2,A_NODO *h3,E_POSICION *posicion);

#define a_nodoresend		a_nodo3
#define a_nododeclaracionlista	a_nodo3
#define a_nodoif(x,y,z,p)	a_nodo3(A_IF,x,y,z,p)
#define a_nodoaccesomiembro	a_nodo3
#define a_nodomiembroexterno	a_nodo3

A_NODO *a_nodo4(A_TIPO tipo,A_NODO *h1,A_NODO *h2,A_NODO *h3,A_NODO *h4,E_POSICION *posicion);

#define a_nodofor		a_nodo4
	
	/* Nodos con anotaciones */

A_NODO *a_literalCadena(char *s,E_POSICION *posicion);
A_NODO *a_literalEntero(int i,E_POSICION *posicion);
A_NODO *a_literalReal(double f,E_POSICION *posicion);
A_NODO *a_id(char *id,E_POSICION *posicion);
A_NODO *a_objeto(A_NODO *h1,A_NODO *h2,A_NODO *h3,A_NODO *h4,E_POSICION *posicion);
A_NODO *a_miembro(A_NODO *h1,A_NODO *h2,A_NODO *h3,A_NODO *h4,E_POSICION *posicion);
A_NODO *a_programa(A_NODO *h1,E_POSICION *posicion);
A_NODO *a_let(A_NODO *h1,A_NODO *h2,E_POSICION *posicion);

	/* Destructor genérico (común a todos los tipos de nodo) */

void    a_free (void *nodo);	
#endif

