%x comment
%{
/************************************************
  Team: Jon Gregory, Gor Nishanov
  Project #2 Part 2
    for RPI course 66-648 Compiler Design Theory

  java.l:

    to do: parseFloat properly and all kinds of Ints

 **/

int lineno = 1;
#define lex yylval

%}

OctalDigit        [0-7]
DecimalDigit      [0-9]
HexDigit          [0-9a-fA-F]
NonzeroDigit      [1-9]

HexPrefix         0[xX]
Sign              [\+\-]
ExponentLetter    [eE]
IntegerSuffix     [lL]
FloatSuffix       [fFdD]

DecimalLiteral    {NonzeroDigit}{DecimalDigit}*
HexLiteral        {HexPrefix}{HexDigit}+
OctalLiteral      0{OctalDigit}*
Digits            {DecimalDigit}+
Exponent          {ExponentLetter}({Sign}?{DecimalDigit}+)?

CrazyFloat        "."{Digits}{Exponent}?{FloatSuffix}?
NormalFloat       {Digits}"."{Digits}?{Exponent}?{FloatSuffix}?
NominalFloat      {Digits}{FloatSuffix}
NoDotFloat        {Digits}{Exponent}{FloatSuffix}?

FloatingPointLiteral ({NormalFloat}|{NominalFloat}|{NoDotFloat}|{CrazyFloat})
IntegerLiteral       ({DecimalLiteral}|{HexLiteral}|{OctalLiteral}){IntegerSuffix}?

%%
{FloatingPointLiteral}  { 
  lex.expr = new DoubleExpression(3.1415); return (Literal ); }
{IntegerLiteral}        { long l = 0; //!!! all systems
  for(int i = 0; i < yyleng; ++i) l = l * 10 + (yytext[i]-'0');
  lex.expr = new IntExpression(l); return (Literal ); }

"abstract"       { lex.modifier = ACC_ABSTRACT;     return (Modifier1); }
"final"          { lex.modifier = ACC_FINAL;        return (Modifier1); }
"native"         { lex.modifier = ACC_NATIVE;       return (Modifier1); }
"private"        { lex.modifier = ACC_PRIVATE;      return (Modifier1); }
"protected"      { lex.modifier = ACC_PROTECTED;    return (Modifier1); }
"public"         { lex.modifier = ACC_PUBLIC;       return (Modifier1); }
"static"         { lex.modifier = ACC_STATIC;       return (_static_); }
"synchronized"   { lex.modifier = ACC_SYNCHRONIZED; return (_synchronized_); }
"transient"      { lex.modifier = ACC_TRANSIENT;    return (Modifier1); }
"volatile"       { lex.modifier = ACC_VOLATILE;     return (Modifier1); }

"boolean"        { lex.type = Type::Bool;    return (PrimitiveType); }
"byte"           { lex.type = Type::Byte;    return (PrimitiveType); }
"char"           { lex.type = Type::Char;    return (PrimitiveType); }
"double"         { lex.type = Type::Double;  return (PrimitiveType); }
"float"          { lex.type = Type::Float;   return (PrimitiveType); }
"int"            { lex.type = Type::Int;     return (PrimitiveType); }
"long"           { lex.type = Type::Long;    return (PrimitiveType); }
"short"          { lex.type = Type::Short;   return (PrimitiveType); }
"void"           { lex.type = Type::Void;    return (_void_); }

"break"          { return (_break_); }
"case"           { return (_case_); }
"catch"          { return (_catch_); }
"class"          { return (_class_); }
"const"          { /* Just a keyword */; }
"continue"       { return (_continue_); }
"default"        { return (_default_); }
"do"             { return (_do_); }
"else"           { return (_else_); }
"extends"        { return (_extends_); }
"finally"        { return (_finally_); }
"for"            { return (_for_); }
"goto"           { /* just a keyword */; }
"if"             { return (_if_); }
"implements"     { return (_implements_); }
"import"         { return (_import_); }
"instanceof"     { return (_instanceof_); }
"interface"      { return (_interface_); }

"new"            { return (_new_); }
"package"        { return (_package_); }
"return"         { return (_return_); }
"switch"         { return (_switch_); }
"super"          { lex.expr = new SuperExpression(); return (_super_); }
"this"           { lex.expr = new ThisExpression(); return (_this_); }
"throw"          { return (_throw_); }
"throws"         { return (_throws_); }
"try"            { return (_try_); }
"while"          { return (_while_); }

"="        { lex.opval = ASSIGN; return (AssOp); }
"*="       { lex.opval = ASGMUL; return (AssOp); }
"/="       { lex.opval = ASGDIV; return (AssOp); }
"%="       { lex.opval = ASGREM; return (AssOp); }
"+="       { lex.opval = ASGADD; return (AssOp); }
"-="       { lex.opval = ASGSUB; return (AssOp); }
"<<="      { lex.opval = ASGLSHIFT; return (AssOp); }
">>="      { lex.opval = ASGRSHIFT; return (AssOp); }
">>>="     { lex.opval = ASGURSHIFT; return (AssOp); }
"&="       { lex.opval = ASGBITAND; return (AssOp); }
"|="       { lex.opval = ASGBITOR; return (AssOp); }
"^="       { lex.opval = ASGBITXOR; return (AssOp); }

"++"       { lex.opval = PREINC; return (IncDec); }
"--"       { lex.opval = PREDEC; return (IncDec); }

"=="       { lex.opval = EQ; return (EqualOp); }
"!="       { lex.opval = NE; return (EqualOp); }

"<="       { lex.opval = LE; return (RelOp); }
">="       { lex.opval = GE; return (RelOp); }
">"        { lex.opval = GT; return (RelOp); }
"<"        { lex.opval = LT; return (RelOp); }

"||"       { return (_oror_); }
"&&"       { return (_andand_); }

">>"       { lex.opval = RSHIFT; return (ShiftOp); }
"<<"       { lex.opval = LSHIFT; return (ShiftOp); }
">>>"      { lex.opval = URSHIFT; return (ShiftOp); }

"("       {return ('('); }
")"       {return (')'); }
"{"       {return ('{'); }
"}"       {return ('}'); }
"["       {return ('['); }
"]"       {return (']'); }
";"       {return (';'); }
","       {return (','); }
"."       {return ('.'); }
"?"       {return ('?'); }
":"       {return (':'); }

"^"       {return ('^'); }

"&"       {return ('&'); }
"|"       {return ('|'); }

"+"       {lex.opval = ADD; return (AddOp);}
"-"       {lex.opval = SUB; return (AddOp);}

"/"       {lex.opval = DIV; return (MulOp);}
"*"       {lex.opval = MUL; return (MulOp);}
"%"       {lex.opval = REM; return (MulOp);}

"~"       {lex.opval = BITNOT; return (NegNot);}
"!"       {lex.opval = NOT;    return (NegNot);}

"null"   { lex.expr = new NullExpression(); return (Literal ); }
"true"   { lex.expr = new BoolExpression(true); return (Literal ); }
"false"  { lex.expr = new BoolExpression(false); return (Literal ); }

\"[^"\n]*\"  { yytext[yyleng-1] = 0;
               lex.expr = new StringExpression(yytext+1);
               return (Literal ); } /* StringLiteral*/

\'[^\'\n]+\' { lex.expr = new CharExpression(yytext[1]);
               return (Literal ); } /* CharLiteral */

[a-zA-Z_][a-zA-Z0-9_]*  { 
  yytext[yyleng] = 0; //cout << "LEX(" << yytext << ':' << yyleng << '=' ;
  Identifier a(yytext); 
  lex.id = a;
//  cout << lex.id.str_ << ')' << endl;
  return (ident); }

"/*"         BEGIN comment;
     
<comment>[^*\n]*        /* eat anything that's not a '*' */
<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
<comment>\n             ++lineno;
<comment>"*"+"/"        BEGIN INITIAL;

"//"[^\n]*\n  { ++lineno; }


[ \t\r]+    ;

"\n"    ++lineno;

.      {printf("Bad Symbol <<%s>> lineno:%d \n",yytext,lineno);exit(1);}

%%
int yywrap() { return 1; }



