%{
#include "tokentable.h"
#include "value.h"
#include "parser.h"
#include "command.h"

#undef yywrap()
#define yywrap() ((parse_pointer < parsestring->length()) ? 0 : 1)

#undef YY_INPUT
#define YY_INPUT(buf, result, max_size)\
       {result = ((parse_pointer >= parsestring->length()) ? YY_NULL : \
		  ((max_size > (parsestring->length() - parse_pointer)) ? \
		   (parsestring->length() - parse_pointer) : max_size)); \
        parse_pointer += result;  \
        memcpy ((buf), parsestring->chars(), result);}

Value* yylval;
String* tempstring;
static StringValHash *reseved_words;
float tempfloat;
int tempcount;
int lex_line;
int open_parens;
Value method_const (METHOD, RESERVED);
%}

LETTER [a-zA-Z]
DIGIT  [0-9]
HEXDIGIT [0-9A-F]
OCTALDIGIT [0-7]
HEXINTEGER ("-"?{DIGIT}{HEXDIGIT}*"H")
DECINTEGER ("-"?{DIGIT}+)
OCTINTEGER ("-"?{OCTALDIGIT}+("B"|"C"))
SCALEFACTOR ("E"("+"|"-")?{DIGIT}+)
REAL_NUM  ("-"?{DIGIT}+"."{DIGIT}*{SCALEFACTOR}?)
NONQUOTES ([^"\\]|(\\[^\t\n]))
STRING    (\"{NONQUOTES}*\")
ID        ([^ \"\t\n()':\]\}\{]*)

%%
";"[^\n]*           ;  /* ignore all comments */
[ \t]               ;  /* ignore whitespace   */
[\n]                {lex_line++;}
[(]                 {yylval = NULL;  open_parens++;  return (L_PARENS);}
[)]                 {yylval = NULL;
                     open_parens = ((open_parens) ? open_parens-1 :
				    open_parens);
                     return (R_PARENS);}
"]"                 {yylval = NULL;
                     if (open_parens)
                       {open_parens--;
                        unput (yytext[0]);
                        return (R_PARENS);}}
"\{"                {yylval = NULL;  return (L_BRACKET);}
"\}"                {yylval = NULL;  return (R_BRACKET);}
[']                 {yylval = NULL;  return (APOSTROPHE);}
"#"{DECINTEGER}     {yylval = new Value ((int)strtol(yytext+1, NULL, 10), OBJ);
                     return OBJ;}
"#"{DECINTEGER}" "*: {yytext[yyleng-1] = '\0';
                      yylval= new Value ((int)strtol(yytext+1, NULL, 10), OBJ);
                      return OBJ_COLON;}
{DECINTEGER}        {yylval = new Value((int)strtol(yytext, NULL, 10));
                     return NUM;}
{OCTINTEGER}        {yytext[yyleng-1]='\0';
                     yylval=new Value((int)strtol(yytext, NULL, 8));
                      return NUM;}
{HEXINTEGER}        {yytext[yyleng-1]='\0';
                     yylval = new Value((int)strtol(yytext, NULL, 16));
                     return NUM;}
{REAL_NUM}          {sscanf(yytext, "%f", &tempfloat);
                     yylval = new Value (tempfloat);
                     return REAL;}
"!"{DECINTEGER}     {yylval = new Value((int)strtol(yytext+1, NULL, 10), ERR);
                     return ERR;}
{STRING}            {yytext[yyleng-1] = '\0';
                     yylval = new Value (yytext+1);
		     sub_special (*(yylval->str));
                     return STR;}
{ID}" "*:           {for (tempcount=1 ;
                          yyleng > tempcount &&
                           (yytext[yyleng-tempcount] == ':' ||
                            yytext[yyleng-tempcount] == ' ') ;
                          tempcount++)
                       yytext[yyleng-tempcount] = '\0';
                    tempstring = new String (yytext);
                    tempstring -> downcase();
                    if (yylval = reseved_words->lookup (tempstring))
                      {delete tempstring;
                       yylval = yylval->copy();
                       return RESERVED;}
                    else
                      {delete tempstring;
                       yylval = new Value (yytext, SYM);
                       return (SYM_COLON);}}
{ID}              {tempstring = new String (yytext);
                   tempstring->downcase();
                   if (yylval = reseved_words->lookup (tempstring))
                      {delete tempstring;
                       if (! (method_const.compare(yylval)))
                           {yylval = NULL;
                            return MTHD;}
                       else
                           {yylval = yylval->copy();
                            return RESERVED;}}
                   else
                      {delete tempstring;
                       yylval = new Value (yytext, SYM);
                       return SYM;}}
.                {fprintf(stderr, "BAD INPUT CHAR '%c'\n", yytext[0]);}
%%

void lexinit(){
  reseved_words = init_token_table();
}
                
void start_lex(void){
  lex_line = 1;
  open_parens = 0;
}