/******************************************************************************
** Copyright (C) 2001, University of Alabama in Huntsville. All rights 
** reserved.
**
** File   : CGIFLexicalAnalyzer.cpp
**
** Author : Saranyu Tantipongsakul, Da Sun
**
** Description:
**    This file provides the implementation for CCGIFLexicalAnalyzer class.
**
** History:
** 01-Dec-01 Saranyu Tantipongsakul, Da Sun
**     File Created.  Copied major portions from parser written in C by Da.
******************************************************************************/

#pragma warning(disable: 4786)  // Disable debug information warning

#include "CGIFLexicalAnalyzer.h"

CCGIFLexicalAnalyzer::CCGIFLexicalAnalyzer()
{
	CCGIFLexicalAnalyzer::tokenNumber = 0;
}

CCGIFLexicalAnalyzer::~CCGIFLexicalAnalyzer()
{
}

bool CCGIFLexicalAnalyzer::readCGIF(std::string sourcefile)
{
	// open input stream
	ifstream cgif_file(sourcefile.c_str());
	if(cgif_file == NULL)
	{
		return false;
	}
	    
    char line[MAX_LINE_CHAR];

	do
	{   
		cgif_file.getline(line, MAX_LINE_CHAR);

		if(strcmp(line,".") )  // str does not contain only "."
		{
			tokenNumber += tokenAnalyzer(tokens, line);
		} 
		
	} while (!cgif_file.eof());

	return true;

}

bool CCGIFLexicalAnalyzer::convertTokens()
{
    simpleTokenList = new simpleTokenType[tokenNumber];

    seg[0] = 6;

	string_vector_type::iterator iter;
    iter = tokens.begin();

    int j=0;
	
    while(iter != tokens.end()) 
    {   
        if( !strcmp( (*iter).value.c_str(),"RelationHierarchy") )
		{
			seg[1]= j-3;
			seg[2]= j+2;
		}
        if( !strcmp( (*iter).value.c_str(),"CatalogOfIndividuals"))
		{
			seg[3]= j-3;
			seg[4]= j+2;
		}

		if( !strcmp( (*iter).value.c_str(),"Assertion"))
		{
			seg[5]= j-3;
			seg[6]= j+2;
		}

	    //if( !strcmp( (*iter).value.c_str(),"LambdaExpression") )
		if( !strcmp( (*iter).value.c_str(),"def") )
		{
	        int left=1,right=0;
		    do
			{
			    if( !strcmp( (*iter).value.c_str() ,"(") ) left++;
			    if( !strcmp( (*iter).value.c_str() ,")") ) right++;
			    iter++;
			} while (left != right);
		  
		    j--;
		}
      
        strcpy( (simpleTokenList[j]).value, (*iter).value.c_str() );
        (simpleTokenList[j]).kind = (*iter).kind;
      
	    j++;
	    iter++;
	}

    m_nNewTokenNumber = j;
	seg[7]= j-2;
	//for (int h=0; h<8; h++) printf(" the seg: %4d\n", seg[h]);

	return true;
}

void CCGIFLexicalAnalyzer::getOneToken(tokenType *token, char *line, int *next, int *pstate)
{
	static char *whitesp=" \t\r\"'";	// blank and tab 
	static char *singlech="[]()<>{};:~,*?#@%|&!";
	
	char ch;
	int tokenFound=0;
	int tokpos=0;

	while((ch=line[*next]) && (!tokenFound))      
	{
	    tokenFound =0;
		if(sindex(ch,singlech)>=0)
		{
			switch(*pstate)
			{
			    case IN_WHITE: 
			    case IN_STOKN:  token->value += ch;
					            tokenFound =1;
								token->kind = identifyTokenType(ch);

                                *pstate = IN_STOKN;
					   		    break;
			     case IN_RTOKN: tokenFound =1;
					            token->kind = identifier;
							    (*next)--;
							    *pstate = IN_STOKN;
							    break;
			}
		}

	     else
		 {
		     if (sindex(ch,whitesp)>=0)   // white 
			 {
		        switch(*pstate)
				{
			       case IN_WHITE: *pstate = IN_WHITE;
					              tokenFound=0;
					              break;
			       case IN_STOKN: break;
			       case IN_RTOKN: tokenFound =1;
					              token->kind = identifier;
                                  *pstate = IN_WHITE;
							      break;
				}
			 }
		     else  /* anything else is just a real character */
			 {
			    token->value += ch;
				*pstate = IN_RTOKN;
			 }
		 }
		 (*next)++;
	} 
}

enum token_kind_type CCGIFLexicalAnalyzer::identifyTokenType(char ch)
{
   static int comment=0;
   token_kind_type type = unknown;

   switch (ch)
   {
	   case '[': type = beginConcept;
		   break;
	   case ']': type = endConcept;
		   break;
	   case '(': type = beginRelation;
		   break;
	   case ')': type = endRelation;
		   break;
	   case '<': type = beginActor;
		   break;
	   case '>': type = endActor;
		   break;
	   case '{': type = beginSet;
		   break;
	   case '}': type = endSet;
		   break;
	   case '%': type = beginStructure;
		   break;
	   case ';': if(comment ==0)
				 {
					 type = beginComment;
		             comment=1;
				 } else 
				 {
					 type = endComment;
					 comment =0;
				 }
				 break;
	   case '~': type = negation;
		   break;
	   case '@': type = beginQuantifier;
		   break;
	   case '#': type = beginIndexical;
		   break;
	   case '&': type = conjunctSeparator;
		   break;
	   case '|': type = disjunctSeparator;
		   break;
	   case '!': type = whyExclamation;
		   break;
	   case ':': type = beginReferent;
		   break;
	   case '*': type =defLabel;
		   break;
	   case '?': type = boundLabel;
		   break;
	   default: type =unknown;
		        break;
   }
   return type;
}

bool CCGIFLexicalAnalyzer::printTokens(char *outputFile)
{
	FILE *fp;
    //create a new file for output
    if( (fp = fopen( outputFile, "w" )) == NULL )
	{
	    /*printf("Can't create output file %s\n",outputFile);
	    exit(0);*/
		return false;
	}

	string_vector_type::iterator iter;
    iter = tokens.begin();

    int j=0;
    while(iter != tokens.end()) 
    {   

      fprintf(fp," Token: %3d, Kind: %2d, Value: %s\n",++j,(*iter).kind,
		      (*iter).value.c_str());

	  iter++;
   }
   fclose(fp);

   return true;
}

int CCGIFLexicalAnalyzer::sindex(char ch, char *string)
{
  char *cp;
  for(cp=string;*cp;++cp)
  if(ch==*cp) return (int)(cp-string); //return postion of character
  return -1;             //no match found 
}

int CCGIFLexicalAnalyzer::tokenAnalyzer(string_vector_type &tmp_vect,char *line)
{
    int next=0;
	int pstate=IN_WHITE;
	int i=0;
	
	while (line[next])
	{
		tokenType token;
		token.kind = unknown;
        		
        tokenType oneToken;
		oneToken.value="";

		getOneToken(&oneToken, line, &next, &pstate);
		
		if(strcmp(oneToken.value.c_str(), "") )
		{
			token.value = oneToken.value;
		    token.kind  = oneToken.kind;
	        tmp_vect.push_back(token);
  		    i++;
		}
	}
	return i;
}


