 /*
  * Khoros: $Id: expr_lex.l,v 1.3 1992/03/20 23:41:55 dkhoros Exp $
  */

 /*
  * $Log: expr_lex.l,v $
 * Revision 1.3  1992/03/20  23:41:55  dkhoros
 * VirtualPatch5
 *
  */ 


 /*
  *----------------------------------------------------------------------
  *
  * 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 */

/**************************************************************
*
*   Written by:   Mark Young
*
**************************************************************/

%{

#include "expr.h"
#include "y.tab.h"

#undef output
#define output(c) (printf("unrecognized character: %c\n",(c)))

#undef input
#define input() (*sptr++)

#undef unput
#define unput(c) ((*--sptr)=(char)(c))

double atof();
static void _xve_get_constant(), _xve_get_function(), _xve_get_variable();

extern YYSTYPE yylval;
%}

%o 5000
%a 3000

S	[ \t\n]*
B	[a-zA-Z][a-zA-Z0-9"_"]*
D	[0-9]
E	[Ee][-+]?{D}+

%START vrules srules

%%

<srules>"=" {
           return('=');
        }

<srules>"printf"/{S}"(" {
	   return(PRINTF);
	}

<srules>.  {
	   char     token[512];
	   register int c, i = 0;

	   if (yytext[0] == '$')
	   {
	      for (;;)
	      {
	         c = input();
	         if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' &&
		     c <= '9' || c == '_')
	         {
		    token[i++] = c;
	         }
	         else
	         {
		    token[i] = '\0';
		    unput(c); break;
	         }
	      }
	      _xve_get_constant(token);
	      if (yylval.symbol->type == UNDEFINED ||
	          yylval.symbol->type == EXPRESSION ||
	          yylval.symbol->type == VARIABLE)
	      {
	         return(EXPRESSION);
	      }
	      else
	         return(yylval.symbol->type);
	   }
	   else
	   {
	      token[i++] = yytext[0];
	      for (;;)
	      {
	         c = input();
	         if (c != '\0' && c != '$')
	         {
		    token[i++] = c;
	         }
	         else
	         {
		    token[i] = '\0';
		    unput(c); break;
	         }
	      }
	      yylval.string = VStrcpy(token);
	      return(STRING);
	   }
	}

<vrules>"#".*		 { ; }  /* skip everything after a csh style comment */
<vrules>"/*"	{	        /* skip everything inside a C style comment */
	   register int c;
	   for (;;)
	   {
	      while ((c = input()) != '*' && c != EOF && c != '\0')
				;
	      if (c == '*')
	      {
	         if ((c = input()) == '/')
		    break;
	      }
	      else
		 break;
	   }
	}

"++"	{ return(INCREMENT); }
"--"	{ return(DECREMENT); }
"<<"	{ return(SL); }
">>"	{ return(SR); }
"=="	{ return(EQ); }
"!="	{ return(NE); }
"<="	{ return(LE); }
">="	{ return(GE); }
".GT."	{ return(GT); }
".LT."	{ return(LT); }
".EQ."	{ return(EQ); }
".LE."	{ return(LE); }
".GE."	{ return(GE); }
".NE."	{ return(NE); }
"**"	{ return(POW); }
"<"	{ return(LT); }
">"	{ return(GT); }
"("	{ return('('); }
")"	{ return(')'); }
","	{ return(','); }
";"	{ return(';'); }
"="	{ return('='); }
"+"	{ return('+'); }
"-"	{ return('-'); }
"*"	{ return('*'); }
"/"	{ return('/'); }
"~"	{ return('~'); }
"!"	{ return('!'); }
"%"	{ return('%'); }
"&"	{ return('&'); }
"^"	{ return('^'); }
"|"	{ return('|'); }
"&&"	{ return(AND); }
".AND."	{ return(AND); }
"||"	{ return(OR); }
".OR."	{ return(OR); }
"+="	{ return(AADD); }
"-="	{ return(ASUB); }
"*="	{ return(AMUL); }
"/="	{ return(ADIV); }
"|="	{ return(AOR); }
"&="	{ return(AAND); }
"^="	{ return(AXOR); }
"<<="	{ return(ASL); }
">>="	{ return(ASR); }
":"	{ return(':'); }
"?"	{ return('?'); }
"IF"	{ return(IF); }
"if"	{ return(IF); }
"THEN"	{ return(THEN); }
"then"	{ return(THEN); }
"ELSE"	{ return(ELSE); }
"else"	{ return(ELSE); }
""	{ return('\0'); }


<vrules>{S}		 { ; }	/* skip blanks and tabs */

<vrules>{D}+		  |
<vrules>{D}+"."{D}*({E})? |
<vrules>{D}*"."{D}+({E})? |
<vrules>{D}+{E} {
	   yylval.value = atof(yytext);
	   return(NUMBER);
	}

<vrules>{B}/{S}"=" {
	   _xve_get_variable(yytext, FALSE);
	   return(VARIABLE);
	}

<vrules>"eval"/{S}"(" {
	   return(EVALUATE);
	}

<vrules>{B}/"(" {
	   _xve_get_function(yytext);
	   return(FUNCTION);
	}


<vrules>{B} {
	   _xve_get_constant(yytext);
	   if (yylval.symbol->type == UNDEFINED ||
	       yylval.symbol->type == EXPRESSION)
	   {
	      return(VARIABLE);
	   }
	   else
	      return(yylval.symbol->type);
	}
<vrules>"("{S}"int"{S}")" {
	   return(CINT);
	}

<vrules>"("{S}"float"{S}")" {
	   return(CFLOAT);
	}
<vrules>"("{S}"string"{S}")" {
	   return(CSTRING);
	}

%%

_xve_set_value()
{
	BEGIN vrules;
}

_xve_set_string()
{
	BEGIN srules;
}

static void _xve_get_constant(string)

char *string;
{
	Symbol  *symbol;
	Varlist *varlist;


	/*
	 * Check for constant value first then check to see if it is
	 * a constant
	 */
	if ((varlist = _xve_get_varlist(CONSTANT_ID)) != NULL)
	{
	   if ((symbol = _xve_get_symbol(varlist, string, TRUE)) == NULL)
	      _xve_get_variable(string, TRUE);
	   else
	      yylval.symbol = symbol;
	}
}

static void _xve_get_function(string)

char	*string;
{
	Symbol  *symbol;
	Varlist *varlist;


	/*
	 * Check check to see if it is a defined function
	 */
	if ((varlist = _xve_get_varlist(FUNCTION_ID)) != NULL)
	{
	   if ((symbol = _xve_get_symbol(varlist, string, TRUE)) != NULL)
	   {
	      yylval.symbol = symbol;
	      return;
	   }
	}

	/*
	 * Check to see if it is in the current varlist list.
	 */
	if ((varlist = _xve_get_varlist(CURRENT_ID)) != NULL)
	{
	   if ((symbol = _xve_get_symbol(varlist, string, TRUE)) == NULL)
	   {
	      symbol = _xve_add_symbol(varlist, string, UNDEFINED, 0.0);
	      yylval.symbol = symbol;
	      return;
	   }
	}
	yylval.symbol = symbol;
}

static void _xve_get_variable(string, parent)

char *string;
int  parent;
{
	Symbol  *symbol;
	Varlist *varlist, *currlist;


	/*
	 * Check to see if it is a current variable list.
	 */
	if ((currlist = _xve_get_varlist(CURRENT_ID)) != NULL)
	{
	   if ((symbol = _xve_get_symbol(currlist, string, parent)) != NULL)
	   {
	      yylval.symbol = symbol;
	      return;
	   }
	}

	/*
	 * Check to see if it is in the global variable list.
	 */
	if ((varlist = _xve_get_varlist(GLOBAL_ID)) != NULL)
	{
	   if ((symbol = _xve_get_symbol(varlist, string, parent)) == NULL)
	   {
	      symbol = _xve_add_symbol(currlist, string, UNDEFINED, 0.0);
	      yylval.symbol = symbol;
	      return;
	   }
	}
	yylval.symbol = symbol;
}
