%{

/*
 * Copyright (C) 2003 Clemens Fuchslocher
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

#include <stdio.h>
#include <stdlib.h>

#include "VRMLReaderInternals.h"

#define YYMAXDEPTH 1000000

extern int VRMLReader_lineno;

%}

%type <literal_value> use
%type <literal_value> def
%type <boolean_value> boolean

%token VRML_HEADER
	COMMENT
	UNCATCHED
	<double_value> NUMBER
	<literal_value> LITERAL

%token DEF
	USE
	GROUP
	TRANSFORM
	CENTER
	ROTATION
	SCALE
	SCALEORIENTATION
	TRANSLATION
	BBOXCENTER
	BBOXSIZE
	CHILDREN
	SHAPE
	APPEARANCE
	MATERIAL
	DIFFUSECOLOR
	EMISSIVECOLOR
	SPECULARCOLOR
	AMBIENTINTENSITY
	TRANSPARENCY
	SHININESS
	GEOMETRY
	INDEXEDFACESET
	COORD
	COORDINATE
	POINT
	COORDINDEX
	NORMAL
	NORMALINDEX
	NORMALPERVERTEX
	VECTOR
	COLOR
	COLORINDEX
	COLORPERVERTEX
	TEXCOORD
	TEXTURECOORDINATE
 	TEXCOORDINDEX
	CCW
	CONVEX
	CREASEANGLE
	SOLID
	VRML_TRUE
	VRML_FALSE

%union
{
	int integer_value;
	int boolean_value;
	double double_value;
	char *literal_value;
}

%%

start: VRML_HEADER nodes
	;


nodes: nodes group
	| nodes transform
	| /* void */
	;


// Group
group: def GROUP { VRMLReader_Group_new(); } '{' group_attributes '}'
	{
		VRMLReader_Group_finish();
	}
	;


group_attributes: CHILDREN '[' children ']'
	;


// Transform
transform: def TRANSFORM
	{
		VRMLReader_Transform_new();

		if ($1 != NULL) // No name given through DEF
		{
			if (VRMLReader_GraphNode_setNodeName($1) != VRML_READER_OK)
			{
				fprintf(stderr, "%s[%d]: transform\n", __FILE__, __LINE__);
				return VRML_READER_KO;
			}

			if (VRMLReader_GraphNode_addDefReference($1) != VRML_READER_OK)
			{
				fprintf(stderr, "%s[%d]: transform\n", __FILE__, __LINE__);
				return VRML_READER_KO;
			}

			free($1);
		}
	} '{' transform_attributes '}'
	{
		VRMLReader_Transform_finish();
	}
	;


transform_attributes: CENTER NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Transform_setCenter($2, $3, $4) != VRML_READER_OK)
		{
			return VRML_READER_KO;
		}
	} transform_attributes
	| CHILDREN '[' children ']' transform_attributes
	| ROTATION NUMBER NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Transform_setRotation($2, $3, $4, $5) != VRML_READER_OK)
		{
			return VRML_READER_KO;
		}
	} transform_attributes
	| SCALE NUMBER NUMBER NUMBER { fprintf(stderr, "%s[%d]: Transform: ignoring scale field.\n", __FILE__, __LINE__); } transform_attributes
	| SCALEORIENTATION NUMBER NUMBER NUMBER NUMBER { fprintf(stderr, "%s[%d]: Transform: ignoring scaleOrientation field.\n", __FILE__, __LINE__); } transform_attributes
	| TRANSLATION NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Transform_setTranslation($2, $3, $4) != VRML_READER_OK)
		{
			return VRML_READER_KO;
		}
	} transform_attributes
	| BBOXCENTER NUMBER NUMBER NUMBER { fprintf(stderr, "%s[%d]: Transform: ignoring bboxCenter field.\n", __FILE__, __LINE__); } transform_attributes
	| BBOXSIZE NUMBER NUMBER NUMBER { fprintf(stderr, "%s[%d]: Transform: ignoring bboxSize field.\n", __FILE__, __LINE__); } transform_attributes
	| /* void */
	;


// Children
children: shape comma children
	| transform comma children
	| group comma children
	| /* void */
	;


// Shape
shape: SHAPE '{' shape_children '}'
	;


shape_children: APPEARANCE appearance shape_children
	| GEOMETRY geometry shape_children
	| /* void */
	;


// Appearance
appearance: APPEARANCE '{' material '}'
	;


// Material
material: MATERIAL def MATERIAL { VRMLReader_Material_new(); } '{' material_attributes '}'
	{
		if ($2 != NULL) // No name given through DEF
		{
			if (VRMLReader_GraphNode_setNodeName($2) != VRML_READER_OK)
			{
				fprintf(stderr, "%s[%d]: material\n", __FILE__, __LINE__);
				return VRML_READER_KO;
			}

			if (VRMLReader_GraphNode_addDefReference($2) != VRML_READER_OK)
			{
				fprintf(stderr, "%s[%d]: material\n", __FILE__, __LINE__);
				return VRML_READER_KO;
			}

			free($2);
		}

		VRMLReader_Material_finish();
	}
	| MATERIAL use
	{
		VRMLReader_Material_new();

		if ($2 == NULL) // No name given through DEF
		{
			fprintf(stderr, "%s[%d]: material\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}

		if (VRMLReader_GraphNode_setNodeName($2) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: material\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}

		if (VRMLReader_GraphNode_resolveUseReference($2) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: material\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}

		free($2);

		VRMLReader_Material_finish();
	}
	;


material_attributes: diffusecolor material_attributes
	| emissivecolor material_attributes
	| specularcolor material_attributes
	| ambientintensity material_attributes
	| transparency material_attributes
	| shininess material_attributes
	| /* void */
	;


diffusecolor: DIFFUSECOLOR NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Material_setDiffuseColor($2, $3, $4) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: diffusecolor\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


emissivecolor: EMISSIVECOLOR NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Material_setEmissiveColor($2, $3, $4) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: emissivecolor\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


specularcolor: SPECULARCOLOR NUMBER NUMBER NUMBER
	{
		if (VRMLReader_Material_setSpecularColor($2, $3, $4) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: specularcolor\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


ambientintensity: AMBIENTINTENSITY NUMBER
	{
		if (VRMLReader_Material_setAmbientIntensity($2) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: ambientintensity\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


transparency: TRANSPARENCY NUMBER
	{
		if (VRMLReader_Material_setTransparency($2) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: transparency\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


shininess: SHININESS NUMBER
	{
		if (VRMLReader_Material_setShininess($2) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: shininess\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	;


// IndexedFaceSet
geometry: def INDEXEDFACESET { VRMLReader_VertexArray_new(); } '{' indexfaceset_attributes '}'
	{
		if ($1 != NULL)
		{
			fprintf(stderr, "%s[%d]: geometry\n", __FILE__, __LINE__);

			if (VRMLReader_GraphNode_setNodeName($1) != VRML_READER_OK)
			{
				return VRML_READER_KO;
			}

			free($1);
		}

		VRMLReader_VertexArray_finish();
	}
	;


indexfaceset_attributes: COORD COORDINATE '{' POINT '[' coord_data ']' '}' indexfaceset_attributes
	| COORDINDEX '[' coordindex_data ']' indexfaceset_attributes
	| NORMAL NORMAL  '{' VECTOR '[' normal_data ']' '}' indexfaceset_attributes
	| NORMALINDEX '[' normalindex_data ']' indexfaceset_attributes
	| NORMALPERVERTEX boolean { VRMLReader_VertexArray_setNormalPerVertex($2); } indexfaceset_attributes
	| COLOR COLOR '{' COLOR '[' color_data ']' '}' { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring color field.\n", __FILE__, __LINE__); } indexfaceset_attributes
	| COLORINDEX '[' colorindex_data ']' { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring colorIndex field.\n", __FILE__, __LINE__); } indexfaceset_attributes
	| COLORPERVERTEX LITERAL { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring colorPerVertex field(colorPerVertex == %s).\n", __FILE__, __LINE__, $2); free($2); } indexfaceset_attributes
	| TEXCOORD TEXTURECOORDINATE '{' POINT '[' texcoord_data ']' '}' { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring texCoord field.\n", __FILE__, __LINE__); } indexfaceset_attributes
	| TEXCOORDINDEX '[' texcoordindex_data ']' { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring texCoordIndex field.\n", __FILE__, __LINE__); } indexfaceset_attributes
	| CCW LITERAL { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring ccw field(ccw == %s).\n", __FILE__, __LINE__, $2); free($2); } indexfaceset_attributes
	| CONVEX LITERAL { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring convex field(convex == %s).\n", __FILE__, __LINE__, $2); free($2); } indexfaceset_attributes
	| CREASEANGLE NUMBER { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring creaseAngle field(creaseAngle == %.3f).\n", __FILE__, __LINE__, $2); } indexfaceset_attributes
	| SOLID boolean { fprintf(stderr, "%s[%d]: IndexedFaceSet: ignoring solid field(solid == %s).\n", __FILE__, __LINE__, $2 == 1 ? "true" : "false"); } indexfaceset_attributes
	| /* void */
	;

coord_data: coord_data NUMBER NUMBER NUMBER comma
	{
		if (VRMLReader_VertexArray_addVertexArrayEntry($2, $3, $4) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: coord_data\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	| /* void */
	;


coordindex_data: coordindex_data NUMBER comma NUMBER comma NUMBER comma NUMBER comma
	{
		if ($8 != -1)
		{
			fprintf(stderr, "%s[%d]: coordindex_data: VRMLReader_lineno == %d\n", __FILE__, __LINE__, VRMLReader_lineno);
			return VRML_READER_KO;
		}

		if (VRMLReader_VertexArray_addVertexIndexEntry($2, $4, $6) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: coordindex_data\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	| /* void */
	;


normal_data: normal_data NUMBER NUMBER NUMBER comma
	{
		if (VRMLReader_VertexArray_addNormalArrayEntry($2, $3, $4) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: normal_data\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	| /* void */
	;


normalindex_data: normalindex_data NUMBER comma NUMBER comma NUMBER comma NUMBER comma
	{
		if ($8 != -1)
		{
			fprintf(stderr, "%s[%d]: normalindex_data: VRMLReader_lineno == %d\n", __FILE__, __LINE__, VRMLReader_lineno);
			return VRML_READER_KO;
		}

		if (VRMLReader_VertexArray_addNormalIndexEntry($2, $4, $6) != VRML_READER_OK)
		{
			fprintf(stderr, "%s[%d]: normalindex_data\n", __FILE__, __LINE__);
			return VRML_READER_KO;
		}
	}
	| /* void */
	;


color_data: color_data NUMBER NUMBER NUMBER comma { fprintf(stderr, "color_data = { %.3f, %.3f, %.3f }\n", $2, $3, $4); }
	| /* void */
	;


colorindex_data: colorindex_data NUMBER comma { fprintf(stderr, "colorindex_data = { %d }\n", (int) $2); }
	| /* void */
	;


texcoord_data: texcoord_data NUMBER NUMBER comma { fprintf(stderr, "texcoord_data = { %.3f , %.3f }\n", $2, $3); }
	| /* void */
	;


texcoordindex_data: texcoordindex_data NUMBER comma NUMBER comma NUMBER comma NUMBER comma { fprintf(stderr, "texcoordindex_data = { %d , %d, %d, %d }\n", (int) $2, (int) $4, (int) $6, (int) $8); }
	| /* void */
	;


// Others
use: USE LITERAL { $$ = $2; }
	| /* void */ { $$ = NULL; }
	;


def: DEF LITERAL { $$ = $2; }
	| /* void */ { $$ = NULL; }
	;


comma: ','
	| /* void */
	;


boolean: VRML_TRUE { $$ = 1; }
	| VRML_FALSE { $$ = 0; }
	;

%%
