%{
/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993 Jason I. Gobat and Darren C. Atkinson

    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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/************************************************************************
 * File:	parser.y						*
 *									*
 * Description:	This file contains the yacc specification for the	*
 *		input file parser.					*
 ************************************************************************/

# include <stdio.h>
# include <string.h>
# include <math.h>
# include "generator.h"
# include "allocate.h"
# include "error.h"

# define ln generator.line

static Line		  line;			/* current line		    */
static Grid		  grid;			/* current grid	   	    */
static TriMesh		  trimesh;		/* current triangle mesh    */
static Curve		  hole;			/* current hole	    	    */
static Curve	  	  boundary;		/* current boundary         */
static int		  numholes;		/* current # of holes	    */
static int		  nhpts;		/* number of hole points    */
static int		  nbpts;	        /* number of boundary pts   */
static int		  nlines;
static int		  ngrids;
static int		  ntrimeshes;
static int		  maxnbpts;
static int		  maxnhpts;
static int		  i;
%}

%union {
    char   *s;
    double  d;
    int	    i;
    GPair   p;
    Triplet t;
}


%left	'+' '-'
%left	'*' '/'
%right	UNARY

%token	DOUBLE INTEGER STRING BOLINTEGER BOLSTRING
%token	PROBLEM LINES GRIDS TRIANGLE BOUNDARY HOLE END
%token  LINES_EQ GRIDS_EQ TRIANGLES_EQ HOLES_EQ
%token	RULE_EQ TOLIN_EQ ANGSPC_EQ ANGTOL_EQ KAPPA_EQ DMIN_EQ MIN_EQ MAX_EQ
%token	XNUMBER_EQ YNUMBER_EQ ZNUMBER_EQ NUMBER_EQ
%token  FIRST_EQ LAST_EQ
%token	X_EQ Y_EQ Z_EQ
%token  SIN COS TAN

%type	<d> DOUBLE expression
%type	<i> INTEGER BOLINTEGER RULE_EQ
%type   <p> gpair
%type   <t> triplet
%%

specification
	: description definition_list END
	    {
		if (generator.numerrors) {
		    error ("%d error(s) found in input", generator.numerrors);
		    return generator.numerrors;
		}
	    }
	;


description
	: PROBLEM info_list
		{
			trimesh = NULL;	
			nlines = 0;
  			ngrids = 0;
			ntrimeshes = 0;
			maxnbpts = 50;
			maxnhpts = 30;
		}
	;

info_list
	: info_list info
	|
	;		

info	
	: LINES_EQ INTEGER	{
				   generator.numlines = $2;
 				   if ($2 != 0)
				      generator.lines = Allocate (Line, $2);
				}
	
	| GRIDS_EQ INTEGER	{
				   generator.numgrids = $2;
 				   if ($2 != 0)
				       generator.grids = Allocate (Grid, $2);
				}

	| TRIANGLES_EQ INTEGER	{
				   generator.numtrimeshes = $2;
 				   if ($2 != 0)
				      generator.tris = Allocate (TriMesh, $2);
				}
	;


definition_list
	: definition_list definition
	|
	;


definition
	: LINES line_list
	| GRIDS grid_list
	| TRIANGLE triangle_list
	;


line_list
	: line_list line 
	|
	;


grid_list
	: grid_list grid 
	|
	;


triangle_list
	: triangle_list triangle
	|
	;

line
	: BOLINTEGER
	    {

		line = Allocate (struct _line, 1);
                generator.lines [nlines++] = line;

	    }
	  line_arg_list
	| error
	;


grid
	: BOLINTEGER
	    {

		grid = Allocate (struct _grid, 1);
                generator.grids [ngrids++] = grid;

	    }
	  grid_arg_list
	| error
	;


triangle
	: BOLINTEGER
	    {

		trimesh = Allocate (struct _trimesh, 1);
                generator.tris [ntrimeshes++] = trimesh;
                numholes = 0;

	    }
	  triangle_arg_list
	| error
	;


line_arg_list
	: line_arg_list line_arg
	|
	;


grid_arg_list
	: grid_arg_list grid_arg
	|
	;

triangle_arg_list
	: triangle_arg_list triangle_arg
	|
	;


line_arg
	: FIRST_EQ triplet  {line -> xs = $2.x;
			     line -> ys = $2.y;
			     line -> zs = $2.z;}

	| LAST_EQ triplet   {line -> xe = $2.x;
			     line -> ye = $2.y;
			     line -> ze = $2.z;}


        | NUMBER_EQ INTEGER	{line -> number = $2;}

	| RULE_EQ
	    {
		switch ($1) {
		case 'o': line -> rule = LOG; break;
		case 'i': line -> rule = LINEAR; break;
		}
	    }

	;


grid_arg
	: FIRST_EQ triplet  {grid -> xs = $2.x;
		             grid -> ys = $2.y;
			     grid -> zs = $2.z;}

	| LAST_EQ triplet   {grid -> xe = $2.x;
			     grid -> ye = $2.y;
			     grid -> ze = $2.z;}

 	| XNUMBER_EQ INTEGER {grid -> xnumber = $2;}
      
        | YNUMBER_EQ INTEGER {grid -> ynumber = $2;}

        | ZNUMBER_EQ INTEGER {grid -> znumber = $2;}
	;


triangle_arg
	: TOLIN_EQ expression	{trimesh -> tolin = $2;}

	| ANGSPC_EQ expression	{trimesh -> angspc = $2;}

	| ANGTOL_EQ expression	{trimesh -> angtol = $2;}

	| KAPPA_EQ expression	{trimesh -> kappa = $2;}

	| DMIN_EQ expression	{trimesh -> dmin = $2;}

	| MAX_EQ INTEGER	{trimesh -> max = $2;}

	| MIN_EQ INTEGER	{trimesh -> min = $2;}

	| HOLES_EQ INTEGER 	{
				   trimesh -> numcurves = $2 + 1;
				   trimesh -> curves = Allocate (Curve, $2+1);
				}
	;


gpair
	: expression ',' expression ','
	   {
		$$.x = (double) $1;
		$$.y = (double) $3;
	   }
	;

	
triplet	
	: '(' expression ',' expression ',' expression ')'
	    {
 		$$.x = (double) $2;
		$$.y = (double) $4;
		$$.z = (double) $6;
	    }
 	; 


expression
	: expression '+' expression	{$$ = $1 + $3;}

	| expression '-' expression	{$$ = $1 - $3;}

	| expression '*' expression	{$$ = $1 * $3;}

	| expression '/' expression	{$$ = $3 ? $1 / $3 : 0;}

	| '-' expression    %prec UNARY {$$ = -$2;}

	| '+' expression    %prec UNARY {$$ = $2;}

	| '(' expression ')'		{$$ = $2;}

	| SIN '(' expression ')'	{$$ = sin ($3 * M_PI / 180);}

	| COS '(' expression ')'	{$$ = cos ($3 * M_PI / 180);}

	| TAN '(' expression ')'	{$$ = tan ($3 * M_PI / 180);}

	| DOUBLE			{$$ = $1;}

	| INTEGER			{$$ = $1;}

	;
