/****h* CalcFLex.flex [1.0] *****************************************
*    CALC.FLEX   The lexical analyzer for the calculator program.
*
*    MAKE:       Flex  -d -s -p -v -L Calc.flex
*
*    LAST CHANGED:  01-May-2002
*
*********************************************************************
*
*/


/* -------------------- Definitions section: --------------------- */

%option noyywrap

/* %START CURLY NORM */

DOLLARDEF  "$"

WHTDEF     ([ \t]*)

INTDEF     ([1-9][0-9]*)

HEXDEF     ({DOLLARDEF}[0-9A-Fa-f]*)

OCTALDEF   ([0-7][0-7][0-7])

FLTDEF     ([0-9]*\.[0-9]*)

NUMBERDEF  ({INT}|{OCTAL}|{HEX}|{FLT})

NLDEF      \n

PERCENTDEF "%"

EQUALDEF   "="

ANDDEF     "&"

NOTDEF     "~"

ORDEF      "|"

XORDEF     "^"

LPARENDEF  \(

RPARENDEF  \)

LSHIFTDEF  "<<"

RSHIFTDEF  ">>"

DOTDEF     "."

STARDEF    "*"

SLASHDEF   "/"

PLUSDEF    "+"

MINUSDEF   "-"

EOFDEF     0

%{

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "y.tab.h"

/*
PRIVATE FILE *InputFP  = stdin;
PRIVATE FILE *OutputFP = stdout;
*/

#ifdef   FLEX_DEBUG        /* for debugging the yylex() function: */

extern int yylex( void );

YYSTYPE  yylval;

char     NIL[256], *storage = &NIL[0];

void  main( int argc, char **argv )
{
   /* extern YY_CHAR    *yytext; */
   int               tokval = 0;
   
   yylval.y_str = storage;
   tokval       = yylex();

   while (tokval != 0)    
      {
      switch( tokval )  
         {
         case  EOL:         fprintf( stderr, "\n" );
                            break;

         case  EQUAL:       fprintf( stderr, "%s", yytext );
                            break;

         case  PLUS:        fprintf( stderr, "%s", yytext );
                            break;

         case  MINUS:       fprintf( stderr, "%s", yytext );
                            break;

         case  STAR:        fprintf( stderr, "%s", yytext );
                            break;

         case  SLASH:       fprintf( stderr, "%s", yytext );
                            break;

         case  PERCENT:     fprintf( stderr, "%%" );
                            break;

         case  DOLLAR:      fprintf( stderr, "$" );
                            break;

         case  OR:          fprintf( stderr, "%s", yytext );
                            break;

         case  AND:         fprintf( stderr, "&" );
                            break;

         case  BITINVERT:   fprintf( stderr, "~" );
                            break;

         case  XOR:         fprintf( stderr, "^" );
                            break;

         case  LSHIFT:      fprintf( stderr, "<<" );
                            break;

         case  RSHIFT:      fprintf( stderr, ">>" );
                            break;

         case  LPAREN:      fprintf( stderr, "(" );
                            break;

         case  RPAREN:      fprintf( stderr, ")" );
                            break;

         case  HEXSTRING:   fprintf( stderr, "%s", yytext );
                            break;

         case  NUMBER:      fprintf( stderr, "%d", yylval.y_num );
                            break;

         case  EXIT:        fprintf( stderr, "<EXIT!>\n" );
                            break;
                            
         default:           fprintf( stderr, "\ntokval = %d; ", tokval );
                            /* fprintf( stderr, "yylval: %s; ", yylval.y_str ); */
                            fprintf( stderr, "yytext: %s\n", yytext );
                            break;
         }

      fflush( stderr );

      tokval = yylex();
      }

   if (tokval == 0)
      fprintf( stderr, "<EOF!!>\n" );

   return;
}

#endif      /* FLEX_DEBUG */

%}

/* ------------------------- Rules Section: ---------------------- */

/*
** Real programmers do not use floating point numbers!

[0-9]+"."[0-9]+         { sscanf( yytext, "%f", &yylval.y_float );
                          return FLOAT;    
                        }

*/

%%

{EOFDEF}     { return( YYEOF ); }

{EQUALDEF}   { return( EQUAL ); }

[0-9]+       { sscanf( yytext, "%d", &yylval.y_num );

               return( NUMBER ); 
             }

{HEXDEF}     { 
               yylval.y_num = ConvHexStr( &yytext[1] );
               
               /* sscanf( &yytext[1], "%d", &yylval.y_num ); Strip off Dollar sign! */
             
               return( HEXSTRING ); 
             }
    
[qQ]         { return( EXIT ); /* For DEBUG targets only */ }

{PLUSDEF}    { return( PLUS ); }

{MINUSDEF}   { return( MINUS ); }

{STARDEF}    { return( STAR ); }

{SLASHDEF}   { return( SLASH ); }

{PERCENTDEF} { return( PERCENT ); }

{ORDEF}      { return( OR ); }

{ANDDEF}     { return( AND ); }

{NLDEF}      { return( EOL ); }

{LPARENDEF}  { return( LPAREN ); }

{RPARENDEF}  { return( RPAREN ); }
   
{WHTDEF}     { ;                 }

{NOTDEF}     { return( BITINVERT ); }

{XORDEF}     { return( XOR );    }

{LSHIFTDEF}  { return( LSHIFT ); }

{RSHIFTDEF}  { return( RSHIFT ); }

.            ;

%%

/* ---------------------------- User Code Section: ---------------- */

int ConvHexChar( char chr )
{
   if (chr >= '0' && chr <= '9')
      return( chr - '0' );
   else if (toupper( chr ) >= 'A' && toupper( chr ) <= 'F')
      return( toupper( chr ) - 'A' + 10 );
   else 
      return( 0 );
}

int ConvHexStr( char *str )
{
   int i = 0, rval = 0, index = strlen( str ) - 1;
   
   while ((*(str + i) != '\0') && (i < 8) && (index >= 0))
      {
      rval += (ConvHexChar( *(str + i) ) << (index * 4));  
        
      index--;
      i++;
      }
   
   return( rval );
}
