/* A grammar file for parsing of a DDL2 file; incomplete, designed simply
to extract cifnames and variables.  Differs from DDL1 file parsing in that
the item name information is in save frames */
%{
#include <stdio.h>
#include <math.h>
/* #define YYDEBUG */ 

/* external function for printing errors */

extern int yylex(void);
int yyerror(char *errmes);

/* local variables */

int saveflag = 0;
int nullflag = 0; 
int i,j,valuecount,assocs,itemcount,wantitemcount;
const int tag[4] = {'N','A','T','V'};  /* this is the order of output keys */
%}

/* Bison declarations */
%union{
int length;         /* for length of loop blocks */
char item[80];         /* for single items */
char str[400][80];      /* for lists of items */
}

%token <item> ITEMNAME     /* a cif item */
%token <item> LOOP         /* start looping */
%token <item> ITEMVALUE    /* the value for the item */
%token <item> DICDEF      /* data block name */
%token <item> VARNAME      /* variable name in final program */
%token <item> VARTYPE      /* type of variable */
%token <item> NAME         /* name of cif item follows*/ 
%token <item> DICGLOBAL    /* Initial Dic Info */
%token <item> UNKATTR      /* an unknown attribute name */
%token <item> DATASTRING   /* a string of data */
%token <item> CHAR STRING NUMB NOTHING /* types of variables */
%token <item> ENDSAVE BEGINSAVE    /* beginning and ending of save block */
%token <item> NAMEALIAS                /* another name */

/* define the non--terminal types as all str */

%type <str> attributelist 
%type <str> datavalues dataitems attributeassoc 
%type <item> anattribute vartype avalue input
%type <item> blockelement saveframe
%%

/* Grammar rules */
input:  DICDEF 
        | input blockelement      /* file is sequence of datablock elements */
        ;    

blockelement: attributeassoc {/* do nothing */ }
        | saveframe {/* also do nothing */}
        ;

saveframe: BEGINSAVE attributelist ENDSAVE
/* do all the work here */
           {
	       if(saveflag == 1 & nullflag == 0)  /* have a variable name */
		   {
		       for(j=0;j<4;j++) /* loop over initial letters */
			   {
			       for(i=0;i<assocs;i++)
				   {
				       if($2[i][0]==tag[j])
					   {
					       printf("%s\n",$2[i]);
					       $2[i][0]='\0';
					   }
				   }
			   }
		       printf("ENDITEM : %s\n",$1); 
		   }
	       saveflag = 0; nullflag = 1; assocs = 0;
	   } /* save this info */      
           ;

attributelist: attributeassoc         /* a list of associations */
               {
		   for(i=0;i<wantitemcount;i++)
		       {
			   strncpy($$[i],$1[i],80);
		       }
		   assocs = wantitemcount;/* start at the beginning */
                   wantitemcount = 0;     /* back to zero */
	       }
               | attributelist attributeassoc
               {
		   for(i=0;i<wantitemcount;i++)
		       {
			   strncpy($$[i+assocs],$2[i],80);
		       }
		   assocs += wantitemcount;
                   wantitemcount = 0;       /* back to zero */
	       }
	       ;

attributeassoc: dataitems datavalues  /* a generic loop */
               {
/*		   printf("Associating:\n"); 
		   for(i=0;i<valuecount;i++)
		       {
			   printf("items = %s\n", $1[i]);
			   printf("values = %s\n", $2[i]);
		       } */
		   wantitemcount = 0;
		   if(valuecount%itemcount!=0) 
		       printf("Loop mismatch near %s\n",$2[0]);
                   for(i=0;i<valuecount;i++)
		       {
			   if(strlen($1[i%itemcount])>0)
			       {
				   strncpy($$[wantitemcount],$1[i%itemcount],80);
				   strncat($$[wantitemcount],$2[i],80);
				   wantitemcount++;
			       }
		       }
	       }
               ;

dataitems: anattribute
           {
       	       strncpy($$[0],$1,80);
	       itemcount = 1;
	   } 
           | dataitems anattribute
           {
	       strncpy($$[itemcount],$2,80);
	       itemcount++;
	   }
           ;

datavalues: avalue
           {
	       strncpy($$[0],$1,80);
	       valuecount = 1;
	   }
           | datavalues avalue
           {
	       strncpy($$[valuecount],$2,80);
               valuecount++;
	   }
           ;

anattribute:     VARNAME 
               {
		   strncpy($$,"VAR ",5);
		   saveflag = 1; /* we should check this out */
               }
	       | VARTYPE 
               {
		   strncpy($$,"TYPE ",6);
               }
               | NAME
               { 
		   strncpy($$,"NAME ",6);
	       } 
               | NAMEALIAS
               {
                   strncpy($$,"ALIAS ",7);
               }
               | UNKATTR
               {
		   $$[0] = '\0';
	       }
               ;

avalue : vartype
         {
	     strncpy($$,$1,80);
	 }
         | ITEMNAME
	 {
	     strncpy($$,$1,80);
	 }
	 | DATASTRING
	 {
	     strncpy($$,$1,80);
	 }
	 ;

vartype:       CHAR 
               {strncpy($$,"cifstring CHARACTER*84",23); nullflag = 0;}
               | NUMB
               {strncpy($$,"double REAL*8",14); nullflag = 0;}
               | NOTHING
               {
                   $$[0]='\0';
		   nullflag = 1;
	       }
               ;
               
%%

/* Extra C code */
int yyerror(char *arg)
{
char errmes[80];
int i;
printf("Error! %s\n",arg);
return(0);
}
