%{
// ////////////////////////////////////////////////////////
// Copyright (1994) Columbia University
// Department of Biochemistry and Molecular Biophysics
//
// Author: Weider Chang, Ph.D
// ///////////////////////////////////////////////////////
  
// #include "linebuff.h"
// #include "starasso.h"
// #include "listofiv.h"

#include <string.h>
#include <objc/Object.h>
#include "parser.h"
  
/* For error report facility */
extern lineno;

/* To determine wether current state is in loop_ name */ 
int loopnamestate=0;
int inloop=0;

extern char * progName;
extern int lexer_debug;

%}

%s LOOP
%s LINES

a              [aA]
b              [bB]
d              [dD]
e              [eE]
f              [fF]
g              [gG]
i              [iI]
l              [lL]
o              [oO]
p              [pP]
s              [sS]
t              [tT]
v              [vV]

File_           {f}{i}{l}{e}_
Global_         {g}{l}{o}{b}{a}{l}_
Data_           {d}{a}{t}{a}_
Loop_           {l}{o}{o}{p}_
Stop_           {s}{t}{o}{p}_
Save_           {s}{a}{v}{e}_
SemiC           ;

CR              [\n]
Char            [^\n]
Chars           .*{Char}
Blank           [ \t]
Blanks          {Blank}*
NonBlank        [^ \n\t]
NoSQuote       	[^'\n]*
NoDQuote	[^"\n]*
SQSQuote	\'{NoSQuote}\'
DQDQuote	\"{NoDQuote}\"
DQString        \"{NoDQuote}
SQString        \'{NoSQuote}
PTS		[^ \t\n'";]+
/* DataName     (_{PTS}|\'_{NoSQuote}\'|\"_{NoDQuote}\") */
DataName        _{PTS}
/* Value		({PTS}|{DQDQuote}|{SQSQuote}|{DQString}|{SQString}) */
Value		({PTS}|{SQSQuote}|{DQDQuote})
Comment		#.*

%%

<LINES>^{CR} {
  yytext="";
  return token_found(LINE, "BLANK_LINE");
}

<LINES>^{SemiC}{Blanks} {
  /*
	used to be <LINES>^{SemiC}{Blanks}
     I don't like this rule, however, this is the only way I can make it work.
     */

  if (inloop)
    BEGIN LOOP;
  else
    BEGIN INITIAL;
  return token_found(LINE, "END_OF_LINE");
}

<LINES>{Chars} { 
  return token_found(LINE, "LINE_OF_TEXT");
}

{CR} {
  lineno++;
  if (lexer_debug)
    printf("CR: %s\n", yytext);
}

{Comment} { 
  if (lexer_debug)
    printf("comment: %s\n", yytext);
}

{Blanks} {
  if (lexer_debug)
    printf("blank: %s\n", yytext);
}

{File_}{Value} {
  return token_found(STARFILENAME, "STARFILENAME");
}

{Global_} {
  /* begining of a global data block */
  return token_found(GLOBALNAME, "GLOBALNAME"); /* temporary */
}

{Data_}{Value} {
  /* a data block name */
  BEGIN INITIAL;
  return token_found(DATABLOCKNAME, "DATABLOCKNAME");
}

{Save_}{Value} {
  /* a save frame name */
  return token_found(SAVENAME, "SAVENAME");
}

{Save_} {
  /* end of save frame */
  BEGIN INITIAL;
  return token_found(SAVEEND, "SAVEEND");
}

<INITIAL>{DataName} {
  /* an data name */
  return token_found(ITEMNAME, "ITEMNAME");
}

<INITIAL>{Loop_} {
  /* begining of a looped items */
  BEGIN LOOP;
  loopnamestate=inloop=1;
  return token_found(LOOPMARK, "LOOPMARK");
}

<LOOP>{Loop_} {
  //  loopnamestate=1;
  if (loopnamestate)
    return token_found(INTERNALLOOP, "INTERNALLOOP");
  else
    {

      // no loop_ statement after loop_value.

      loopnamestate=1;
      return token_found(LOOPMARK, "LOOPMARK");
    }
}

<LOOP>{DataName} {
  int token;
  if (loopnamestate)

    /* loopnamestate can only be changed to 0 by starting a looped value.
       and it can only be changed to 1 by a loop_ statement.
       */

    token=LOOPITEMNAME;
  else {

    /* so if the data name is not after a loop_ statement. */

    BEGIN INITIAL;
    inloop=0;
    token=ITEMNAME;
  }
  return token_found(token, "ITEMNAME or LOOPITEMNAME");
}

<LOOP>{Stop_} {
  /* a stop_ statement in loop_ structure */
  return token_found(LOOPEND, "LOOPEND");
}

<LOOP>{Value} {
  /* a data value in loop_ structure */
  loopnamestate=0;
  return token_found(LOOPITEMVALUE, "LOOPITEMVALUE");
}

^{SemiC}{Blanks} { 

  /* following rules descrip a multi-lined string value. */

     BEGIN LINES;
     loopnamestate=0;
     return token_found(LINESBEGIN, "BEGINING_OF_LINE");
}

<INITIAL>{Value} {
  /* a data value */
  return token_found(STRING, "STRING");
}
 

-h |
-help 
{
  printf("Usage: %s [-help | -h | -?]"
	 "[filename]\n", progName);
}

. {
  if ((lexer_debug) && yytext[0]!=' ')
    printf("No token matched: %s\n", yytext);
}
  

%%

extern void * malloc();

int token_found(int token, char* token_symbol)
{
  yylval.char_ptr=(char*)malloc(strlen(yytext)+1);
  strcpy(yylval.char_ptr, yytext);
  if (lexer_debug)
    printf("Lexer: %s as %s\n",yytext, token_symbol);
  return token;
}

int yyerror(char* msg)
{
    fprintf(stderr, "line %d: %s at %s\n", lineno, msg, yytext);
}

void myYYCleanUpCurrentBuffer()
{
  YY_BUFFER_STATE new_buff;
  if (YY_CURRENT_BUFFER)
    {
      // printf("Cleaning current buffer\n ");
      /*
	 yy_delete_buffer(YY_CURRENT_BUFFER);
	 YY_CURRENT_BUFFER=new_buff=yy_create_buffer(yyin, YY_BUF_SIZE);
	 yy_switch_to_buffer(new_buff);
	 */
      yyrestart(yyin);
    }
}
    
/* ************************************************

<LINES>.*[^\n\"] { 
  return token_found(LINE, "LINE");
}

<LINES>.*\" {
  if (inloop)
    BEGIN LOOP;
  else
    BEGIN INITIAL;
  return token_found(LINE, "END_OF_LINE_1");
}

^\".*[^\n\"] { 
  
  // following rules descrip a multi-lined string value.
  
  BEGIN LINES;
  loopnamestate=0;
  return token_found(LINESBEGIN, "BEGINING_OF_LINE_1");
}

**************************************************** */ 








