/**************************************************************************
  Copyright (C) 1992 Guy Moreillon
  All rights reserved.

  This software may be freely copied, modified, and redistributed
  provided that this copyright notice is preserved on all copies.

  You may not distribute this software, in whole or in part, as part of
  any commercial product without the express consent of the authors.

  There is no warranty or other guarantee of fitness of this software
  for any purpose.  It is provided solely "as is".
**************************************************************************/
/**************************************************************************
				RAD
		    (Programme de calcul de Radiosite)
		    	    Version 2.0
			       1991		    	    
		    	    
		  
		    	  Guy Moreillon
		    	  
		Projet de 8eme Semestre - Informatique
		  Laboratoire d'Infographie LIG-EPFL
		  
		      Professeur: D. Thalmann
		       Assistant: E. Gobbetti
**************************************************************************/

/**************************************************************************
  Fichier	: gram.y
  Description	: Definition de grammaire pour le format des fichiers de
		  description de scene
**************************************************************************/

%{

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "types.h"
#include "macros.h"
#include "rad.h"
#include "ioread.h"
#include "misc.h"

typedef struct {
	VECTOR	vector;
	} VECTOR_S;

typedef enum {
	x_axis,
	y_axis,
	z_axis
	} Axis_type;

VECTOR_S	v_dum, v_dum1, v_dum2, v_dum3;
TRIANGLE	p_dum;
TRIANGLE	*tp_dum;
DATAS		*datas;
int		tp_size, tp_max;
PURE_O		pure, caract;
COMPOSITE_O	composite;
ASSEMBLY_O	assembly;
OBJECT_OP	object;			/* Pointeur ! */

%}

%union{
	float 		 y_flt;
	char		*y_str;
	BOOLEAN		 y_etat;
	VECTOR_S	*y_vect;
	Axis_type	 y_upaxis;
	TRIANGLEP	 y_trianglep;
	DATAS		*y_datas;
	OBJECT_OP	 y_object;
	PURE_OP		 y_pure;
	COMPOSITE_O	*y_composite;
	ASSEMBLY_O	*y_assemblage;
};


%token		OBJECT
%token		ASSEMBLY
%token		COMPOSITE
%token		PURE
%token		REFLECTIVITY
%token		COLOR
%token		EMISS
%token		TFILE
%token		DATA
%token		SHADOWS
%token		ON
%token		OFF
%token		TEXTURE
%token		DIRECTION
%token		VIEWUP
%token		SCALE
%token		UPAXIS
%token		XAXIS
%token		YAXIS
%token		ZAXIS

%token	<y_flt>		REEL
%token	<y_str>		NOM NOMFICHIER CHAINE

%type	<y_vect>	vecteur vecteur1 vecteur2 vecteur3
%type	<y_trianglep>	tab_polys poly
%type	<y_datas>	fichier donnees geometrie
%type	<y_etat>	etat
%type	<y_pure>	pure caracteristique
%type	<y_composite>	composite
%type	<y_assemblage>	assemblage
%type	<y_object>	composition complex objets simple
%type	<y_upaxis>	axis

%token ACCOLG ACCOLD PPQ PGQ

%%
scene		: CHAINE UPAXIS axis composition
		{ OBJECT_OP obj;
		  the_scene.scene = (OBJECT_OP)malloc(sizeof(OBJECT_O));
		  assert(the_scene.scene);
		  the_scene.scene->type = assembly_type;
		  the_scene.scene->dad  = NULL;
		  the_scene.scene->next = NULL;
		  strncpy(the_scene.scene->name, $1, NAME_SIZE);
		  the_scene.scene->object.assembly.sons = $4;
		  for(obj = the_scene.scene->object.assembly.sons;
		      obj != NULL;
		      obj = obj->next)
		    obj->dad = the_scene.scene;
		  switch($3) {
		    case x_axis:
		      M4D_init(the_scene.state.visu.mod,
			       0.0, 1.0,  0.0, 0.0,
			       1.0, 0.0,  0.0, 0.0,
			       0.0, 0.0, -1.0, 0.0,
			       0.0, 0.0,  0.0, 1.0);
		      break;
		    case y_axis:
		      M4D_init(the_scene.state.visu.mod,
			       1.0, 0.0, 0.0, 0.0,
			       0.0, 1.0, 0.0, 0.0,
			       0.0, 0.0, 1.0, 0.0,
			       0.0, 0.0, 0.0, 1.0);
		      break;
		    case z_axis:
		      M4D_init(the_scene.state.visu.mod,
			       -1.0, 0.0, 0.0, 0.0,
			        0.0, 0.0, 1.0, 0.0,
			        0.0, 1.0, 0.0, 0.0,
			        0.0, 0.0, 0.0, 1.0);
		      break;
		    default:
		      yyerror("Impossible axis choice");
		  };
		  M4D_invert(the_scene.state.visu.imod, the_scene.state.visu.mod);
		}

axis		: XAXIS
		{ $$ = x_axis; }
		| YAXIS
		{ $$ = y_axis; }
		| ZAXIS
		{ $$ = z_axis; }

composition	: complex
		{ $$ = $1; }
            	| composition complex
		{ $2->next = $1->next;
		  $1->next = $2;
		  $$ = $1; }

complex		: OBJECT CHAINE assemblage
		{ OBJECT_OP obj;
		  object = (OBJECT_OP)malloc(sizeof(OBJECT_O));
		  assert(object);
		  object->type = assembly_type;
		  strncpy(object->name, $2, NAME_SIZE);
		  object->next = NULL;
		  object->object.assembly = *($3);
		  for(obj = object->object.assembly.sons;
		      obj != NULL;
		      obj = obj->next)
		    obj->dad = object;
		  $$ = object; }
		| OBJECT CHAINE composite
		{ OBJECT_OP obj;
		  object = (OBJECT_OP)malloc(sizeof(OBJECT_O));
		  assert(object);
		  object->type = composite_type;
		  strncpy(object->name, $2, NAME_SIZE);
		  object->next = NULL;
		  object->object.composite = *($3);
		  for(obj = object->object.composite.sons;
		      obj != NULL;
		      obj = obj->next)
		    obj->dad = object;
		  $$ = object; }
		| simple
		{ $$ = $1; }

assemblage 	: ASSEMBLY ACCOLG composition ACCOLD
		{ assembly.sons = $3;
		  $$ = &assembly; }

composite 	: COMPOSITE ACCOLG objets ACCOLD
		{ composite.grid = NULL;
		  composite.sons = $3;
		  $$ = &composite; }

objets		: simple
		{ $$ = $1; }
		| objets simple
		{ $2->next = $1->next;
		  $1->next = $2;
		  $$ = $1; }

simple		: OBJECT CHAINE pure
		{ object = (OBJECT_O *)malloc(sizeof(OBJECT_O));
		  assert(object);
		  object->type = pure_type;
		  strncpy(object->name, $2, NAME_SIZE);
		  object->next = NULL;
		  object->object.pure = *($3);
		  $$ = object; }

pure 		: PURE ACCOLG caracteristique geometrie ACCOLD
		{ pure = *($3);
		  pure.nb_polys = $4->size;
		  pure.polys = $4->data;
		  free($4);
		  $$ = &pure; }

caracteristique	: base
		{ caract.texmap.index = -1;
		  $$ = &caract; }
		| texture base
		{ $$ = &caract; }

base		: REFLECTIVITY REEL COLOR vecteur1 EMISS REEL SHADOWS etat
		{ caract.ro = $2;
		  V_copy(caract.color, $4->vector);
		  caract.E = $6;
		  caract.shadows = $8; }

texture		: TEXTURE TFILE NOMFICHIER DIRECTION vecteur1 VIEWUP vecteur2 SCALE REEL
		{ caract.texmap.index = new_texture($3, &the_scene);
		  V_copy(caract.texmap.s, $5->vector);
		  V_copy(caract.texmap.t, $7->vector);
		  caract.texmap.scale = 1.0/$9; }
		  
etat		: ON
		{ $$ = TRUE; }
		| OFF
		{ $$ = FALSE; }

geometrie 	: fichier
		{ $$ = $1; }
          	| donnees
		{ $$ = $1; }

fichier 	: TFILE NOMFICHIER
		{ $$ = read_geo_file($2); }

donnees 	: DATA ACCOLG tab_polys ACCOLD
		{ datas = (DATAS *)malloc(sizeof(DATAS));
		  assert(datas);
		  datas->size = tp_size;
		  datas->maxr = tp_max;
		  datas->data = $3;
		  $$ = datas; }

tab_polys 	: poly
		{ tp_max  = 0;
		  tp_size = 1;
		  tp_dum = (TRIANGLE *)arr_realloc(tp_dum, tp_size,
						   &tp_max, sizeof(TRIANGLE),
						   TRI_BLOCK_SIZE);
		  assert(tp_dum);
		  tp_dum[0] = *$1;
		  $$ = tp_dum; }
          	| tab_polys poly
		{ tp_size++;
		  tp_dum = (TRIANGLE *)arr_realloc(tp_dum, tp_size,
						   &tp_max, sizeof(TRIANGLE),
						   TRI_BLOCK_SIZE);
		  tp_dum[tp_size-1] = *$2;
		  $$ = tp_dum; }

poly 		: vecteur1 vecteur2 vecteur3
		{ init_poly(&p_dum, $1->vector, $2->vector, $3->vector);
		  $$ = &p_dum; }

vecteur1 	: vecteur
		{ V_copy(v_dum1.vector, $1->vector);
		  $$ = &v_dum1; }
		  
vecteur2 	: vecteur
		{ V_copy(v_dum2.vector, $1->vector);
		  $$ = &v_dum2; }
		  
vecteur3 	: vecteur
		{ V_copy(v_dum3.vector, $1->vector);
		  $$ = &v_dum3; }

vecteur 	: PPQ REEL REEL REEL PGQ
		{ V_init(v_dum.vector, $2, $3, $4);
		  $$ = &v_dum; }

%%
#include "lex.yy.c"
