%{

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Syslog.h"
#include "Attributes.h"
#include "Item.h"
#include "ItemList.h"  

Boolean debug;

// Function prototypes
int yyerror(char *errorBuf);
int yylex();
int yyparse();
int fileLineNo();

const int eofReturn = -1;
const int errorReturn = 1;
const int okReturn = 0;

Attributes *_attributes;

Item *_curItem;
ItemList *_itemList;

char _errorBuf[512];

void restartLexer();
Boolean isIdentifier( const char *testMe );

%}

%union 
{
  int integer;
  char *string;
}

%token <string> Word
%token Identifier

%%

ConfigFile: Units
{
};

Units: Unit
{
};

Units: Units Unit
{
};


Unit: Item
{
};

Unit: Attribute
{
};

Item: StartItem Attributes '}'
{
     dprintf("Finished parsing item %s", _curItem->name());
     _curItem = NULL;
};

StartItem: Identifier Word '{'
{
     if( _itemList == NULL )
     {
	  Syslog::write("Parser has found inappropriate identifier");
	  return errorReturn;
     }

     dprintf("Parsing new item of type: %s named %s\n",
	     _itemList->identifier(), $2 );
     
     if( (_curItem = _itemList->addItem( $2 )) == NULL ) 
     {
	  dprintf("Something went wrong adding a new item called %s",
		  $2 );
     }

};

Attributes: Attribute
{
};


Attributes: Attributes Attribute
{
};


Attribute : Word '=' Word ';'
{
  dprintf("Parsing attribute %s = %s", $1, $3 );

  Attributes *curAttributes = NULL;

  Attribute::Input *input = new Attribute::Input($1, $3);

  Boolean error = False;

//  dprintf("Parsing attribute %s = %s", $1, $3 );

  if( _curItem != NULL ) {
       dprintf("Using the current item %s",
	       _curItem->name() );
       curAttributes = _curItem->attributes();

       dprintf("Using the attribute set %s from item  %s\n",
	       curAttributes->objectName(),
	       _curItem->name() );
  }
  else if( _attributes != NULL ) {
       dprintf("No current item .. using the provided attributes %s",
	       _attributes->objectName() );
       curAttributes = _attributes;
  }
  else
  {
       Syslog::write("complexParser -- Found ungrouped attributes in the "
		     "wrong place.");
       return errorReturn;
  }

  if (curAttributes->parse(input) == -1) {

      // Invalid worksite attribute
//      sprintf(_errorBuf, "Invalid attribute: %s = %s",
//	      $1, $3);

      error = True;
  }

  delete input;

  if (error)
    return errorReturn;
}



%%

extern char *yytext;

int yyerror(char *errorMsg)
{
  sprintf(_errorBuf, 
	  "Line %d: %s\noffending text: \"%s\"", 
	  fileLineNo(), errorMsg, yytext);
  
  return 0;
}

void resetComplex()
{
     _curItem = NULL;
     _attributes = NULL;
     _itemList = NULL;
}

// Used in the Lexer
Boolean isIdentifier( const char *testMe )
{
//     Boolean debug = False;

     dprintf("isIdentifier -- I've been asked to test the word %s",
	     testMe );
   
     if( _itemList != NULL )
     {
//	  return  _itemList->isIdentifier( testMe );
	  if( _itemList->isIdentifier( testMe ) )
	  {
	       dprintf("isidentifier -- %s matches",
		       _itemList->identifier() );
	       return True;
	  }
	  else
	  {
	       dprintf("isIdentifier -- %s doesn't match",
		       _itemList->identifier() );
	       return False;
	  }
	       
     }

     return False;
}

void parseComplex(FILE *fp, 
		  Attributes *attributes,
		  ItemList *itemList,
		  Boolean *error, char *errorMsg,
		  Boolean debugIn)
{
  int ret;
  extern FILE *yyin;
  
  restartLexer();

  _attributes = attributes;
  _itemList = itemList;

  *error = False;
  yyin = fp;

  debug = debugIn;

  if ((ret = yyparse()) != okReturn)
  {
    /* Error or end-of-file */
    if (ret == errorReturn)
    {
      *error = True;
      strcpy(errorMsg, _errorBuf);
    }
    return;
  }

  return;
}

