 /*
  * Khoros: $Id: poly_yacc.y,v 1.1 1991/05/10 15:43:54 khoros Exp $
  */

 /*
  * $Log: poly_yacc.y,v $
 * Revision 1.1  1991/05/10  15:43:54  khoros
 * Initial revision
 *
  */ 

%{

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name: poly_yacc.y                            <<<<
   >>>>                                                       <<<<
   >>>>   description: yacc source for polynomial parser      <<<<
   >>>>                                                       <<<<
   >>>>      routines: 					      <<<<
   >>>>                                                       <<<<
   >>>> modifications:					      <<<<
   >>>>                                                       <<<<
   >>>>          NOTE: this routine is not for public use!    <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

#include <stdio.h>
#include "vpoly.h"
#include "y.tab.h"

extern struct polystack *stack;

int polypush();
int func_count = 0;	
%}

%token TERM WORD NUMBER EXPON END CONST COUNT FUNC 
%left UNARYMINUS
%left '*' '+' '-'
%right '/'
%right '=' EXPON

%%
/*
** BEGINNING OF GRAMMAR
*/

list:	  /* nothing */
	| list func TERM
	| list error ';'
	| END 
		{ return(0); }
	;

func:	  WORD '(' WORD ')' '=' expr
		{
                  polypush(&$3);
                  polypush(&$1);
		}
	;

expr:	  poly
		{ 
		  polypush(&$1);
		}
	| quot
		{ }
	| stages
		{ }
	;

stages:	  stage
		{ }
	| stage '*' stages
		{ 
		  $$.type='*';
		  polypush(&$$);
		}
	;

stage:	  '[' poly ']'
		{
                  polypush(&$1); 
		  $$.type=']';
		  polypush(&$$);
		}
	| '[' quot ']'
		{ 
		  $$.type=']';
		  polypush(&$$);
		}
	;

quot:	  '(' poly ')' '/' '(' poly ')'
		{ 
		  $$.type='/';
		  polypush(&$2);
		  polypush(&$6);
		  polypush(&$$);
		}
	;

poly:	  term
                {
		  polypush(&$1);
		  $$.type  = COUNT;
		  $$.value = 1;
		}
	| poly '+' term
                { 
		  polypush(&$3);
		  $$.value = $1.value + 1;
		}
	| poly '-' term
                { 
		  $3.value = 0.0 - $3.value;
		  polypush(&$3);
		  $$.value = $1.value + 1;
		}
	| '(' poly ')'
		{
		  $$.type = $2.type; 
		}
	;

term:	  number
		{
                  $$.type = EXPON;
                  $$.order = 0.0;
                  $$.value = $1.value;
		  strcpy($$.string,"NUMBER");
		}
	| prim	
		{
		}
	| number '*' prim
                {
		  if($3.type==WORD){
		     $$.type = EXPON;
		     $$.order = 1.0;
		     $$.value = $1.value;
		     strcpy($$.string,$3.string);
                  }else if($3.type==FUNC){
                     $$.type = FUNC;
                     $$.order = $3.order;
                     strcpy($$.string,$3.string);
                     strcpy($$.fname,$3.fname);
                     $$.value = $1.value;
                  }else{
                     $$.type = EXPON;
                     $$.order = $3.order;
                     $$.value = $1.value;
		     strcpy($$.string,$3.string);
		  }
		}
        | prim '*' number
                {
                  if($1.type==WORD){
                     $$.type = EXPON;
                     $$.order = 1.0;
                     $$.value = $3.value;
                     strcpy($$.string,$1.string);
		  }else if($1.type==FUNC){
		     $$.type = FUNC;
		     $$.order = $1.order;
		     strcpy($$.string,$1.string);
		     strcpy($$.fname,$1.fname);
		     $$.value = $3.value;
                  }else{
                     $$.type = EXPON;
                     $$.order = $1.order;
                     $$.value = $3.value;
                     strcpy($$.string,$1.string);
                  }
                }

	;

/*
** a prim consists of (1) a variable, (2) a variable raised to a power,
** (3) a function with a variable argument, (4) a function with a variable
** argument adjusted by a delay.  In the cases (1) and (2) value referse to
** the coefficient, and order refers to the exponent.  In the cases (3) and 
** (4), order refers to the delay, value refers to the coefficient value.
*/

prim:	  WORD
		{
		  $$.type = EXPON;
		  strcpy($$.string,$1.string);
		  $$.order = 1.0;
		  $$.value = 1.0;
		}
	| WORD EXPON number
		{ 
		  $$.type = EXPON; 
		  strcpy($$.string,$1.string); 
		  $$.value = 1.0;
		  $$.order = $3.value; 
		}
	| WORD '(' WORD ')'
		{
		  $$.type = FUNC;
		  strcpy($$.fname,$1.string);
		  strcpy($$.string,$3.string);
		  $$.order = 0.0;
		  $$.value = 1.0;
		}
	| WORD '(' WORD '+' number ')'
                {
                  $$.type = FUNC;
                  strcpy($$.fname,$1.string);
                  strcpy($$.string,$3.string);
                  $$.order = $5.value;
		  $$.value = 1.0;
                }
	| WORD '(' WORD '-' number ')'
                {
                  $$.type = FUNC;
                  strcpy($$.fname,$1.string);
                  strcpy($$.string,$3.string);
                  $$.order = 0.0 - $5.value;
		  $$.value = 1.0;
                }
	;

number:	  NUMBER
		{
		  $$.type = NUMBER;
		  $$.order = 0.0;
		  $$.value = $1.value;
		}
	| '-' NUMBER	%prec UNARYMINUS
		{
		  $$.type = NUMBER;
		  $$.order = 0.0;
		  $$.value = 0.0 - $2.value;
		}
	;

/*
** END OF THE GRAMMAR
*/
%%

/***********************************************************************
*
*  Routine Name: yyerror()
*
*          Date: Wed Aug 15 15:14:53 MDT 1990
*        
*       Purpose: outputs error messages from yacc and lex generated code. 
*
*         Input: char *string - error message.
*
*        Output: nothing
*
*    Written By: Jeremy Worley 
*
* Modifications:
*
***********************************************************************/

extern int linecount;
extern struct polystack *stack;

int yyerror(string)
  char *string;
{
  struct polystack *polypop();

  fprintf(stderr,"error encountered on line %d of polynomial file:",
          linecount+1);
  fprintf(stderr,"\n\n\t%s\n",string);
  while(stack!=NULL){
     (void)polypop();
  }
  return(0);
}

