/* **********************************************
 * Duale Hochschule Baden-Württemberg Karlsruhe
 * Prof. Dr. Jörn Eisenbiegler
 * 
 * Vorlesung Übersetzerbau
 * Praxis AS-Scanner mit JFlex 4 
 * 
 * **********************************************
 */

package de.dhbw.compiler.jflexasscanner;

%% 

%class JFlexASScanner
%function nextToken
%type  Token 

%unicode
%line
%column
%public
%final

%xstate FRAC, EXP, STR, NULL, ID, NUM, TO

%{
    String idValue = "";
    int intValue = 0;
    double fracValue = 0.0;
    String numberString = "";
    int decimalPlace = 0;
    int exponent = 0;
    String toRangeString = "";

    private Token numToken(String numberString, int value) {
        //return new Token(Token.NUM, String.valueOf(intValue), yyline+1, yycolumn+1-String.valueOf(intValue).length());
        return new NumToken(numberString, yyline + 1, yycolumn + 1 - numberString.length(), intValue);
    }
%}

WhiteSpace     = [ \t\b\r\n]+
SmallChars     = [a-z]
CapitalChars   = [A-Z]
Numbers        = [0-9]
AllChars       = [a-zA-Z0-9]
Dot            = [\.]
//To             = \d\s*[\.]*\s*\d
Power          = \^{Numbers}

%eofval{
    return new Token(Token.EOF, "", yyline+1, yycolumn+1);
%eofval}

%%
//[^]			{ return new Token(Token.INVALID, yytext(), yyline+1, yycolumn+1); }
{WhiteSpace}             { /* Ignore */ }
<YYINITIAL> {
    "null"                       { return new Token(Token.NULL, yytext(), yyline+1, yycolumn+1); }
    {Numbers}                    { yybegin(NUM);
                                   intValue = yycharat(0)-'0';
                                   numberString = yytext(); }
    {Dot}                        { yybegin(TO); toRangeString = yytext(); }
    {AllChars}                   { yybegin(ID); System.out.println("BEGIN ID <"+yytext()+">");
                                   idValue = yytext(); }
    [\[]                         { return new Token(Token.LSBR, yytext(), yyline+1, yycolumn+1); }
    [\]]                         { return new Token(Token.RSBR, yytext(), yyline+1, yycolumn+1); }
    [,]                          { return new Token(Token.COMMA, yytext(), yyline+1, yycolumn+1); }
}

<NUM> {
    {Numbers}                      { intValue = intValue * 10 + yycharat(0) - '0'; numberString += yytext(); }
    {SmallChars} | {CapitalChars}  { yybegin(ID); idValue = numberString; yypushback(1); }
    <<EOF>>                        { yybegin(YYINITIAL);
                                     return numToken(numberString, intValue); }
    {Dot}                          { yybegin(FRAC);
                                     fracValue = intValue;
                                     System.out.println("BEGIN FRAC <"+yytext()+">");
                                     numberString += yytext(); }
    [^]                            { yybegin(YYINITIAL);
                                     yypushback(1);
                                     return numToken(numberString, intValue); }
}

<ID> {
    {AllChars}                      { idValue += yytext(); }
    <<EOF>>                         { yybegin(YYINITIAL);
                                      return new Token(Token.ID, idValue, yyline+1, yycolumn+1-idValue.length()); }
    [^]                             { yybegin(YYINITIAL);
                                      yypushback(1);
                                      return new Token(Token.ID, idValue, yyline+1, yycolumn+1-idValue.length()); }
}

<FRAC> {
    {Numbers}                       { fracValue += (yycharat(0) - '0') * Math.pow(10, -++decimalPlace); numberString += yytext(); }
    {Dot}                           { yybegin(TO); toRangeString = yytext(); }
    <<EOF>>                         { yybegin(YYINITIAL);
                                      return new FracToken(Token.FRAC, numberString, yyline+1, yycolumn+1-numberString.length(), fracValue); }
    \^{Numbers}                     { yybegin(EXP); numberString += yytext(); exponent = yycharat(1) - '0'; System.out.println("BEGIN EXP <"+yytext()+"> / exponent: " + exponent); }
    [^]                             { yybegin(YYINITIAL);
                                      yypushback(1);
                                      return new FracToken(Token.FRAC, numberString, yyline+1, yycolumn+1-numberString.length(), fracValue); }
}

<EXP> {
    {Numbers}                       { numberString += yytext(); exponent = exponent * 10 + yycharat(0) - '0'; }
    <<EOF>>                         { yybegin(YYINITIAL);
                                      return new FracToken(Token.FRAC, numberString, yyline+1, yycolumn+1-numberString.length(), fracValue * Math.pow(10, exponent)); }
    [^]                             { yybegin(YYINITIAL);
                                      yypushback(1);
                                      System.out.println("numberString: " + numberString);
                                      System.out.println("fracValue: " + fracValue + " / exponent: " + exponent);
                                      return new FracToken(Token.FRAC, numberString, yyline+1, yycolumn+1-numberString.length(), fracValue * Math.pow(10, exponent)); }
}

<TO> {
    {Dot}                           { toRangeString += yytext(); System.out.println("TO DOT <"+toRangeString+"> / " + yyline + " - " + yycolumn);
                                      if (toRangeString.length() % 2 == 0) {
                                          String result = toRangeString;
                                          toRangeString = "";
                                          return new Token(Token.TO, result, yyline+1, yycolumn+1-1);
                                      }}
    {Numbers}                       { yybegin(NUM); yypushback(1);
                                      if (toRangeString.length() % 2 == 0) {
                                          toRangeString = "";
                                          return new Token(Token.TO, "..", yyline+1, yycolumn+1-2);
                                      } else {
                                          return new Token(Token.INVALID, toRangeString, yyline+1, yycolumn+1-toRangeString.length());
                                      }}
    <<EOF>>                         { yybegin(YYINITIAL);
                                      if (toRangeString.length() % 2 == 0) {
                                          toRangeString = "";
                                          return new Token(Token.TO, "..", yyline+1, yycolumn+1-2);
                                      } else {
                                          return new Token(Token.INVALID, toRangeString, yyline+1, yycolumn+1-toRangeString.length());
                                      }}
    [^]                             { yybegin(YYINITIAL); yypushback(1);
                                      if (toRangeString.length() % 2 == 0) {
                                          toRangeString = "";
                                          return new Token(Token.TO, "..", yyline+1, yycolumn+1-2);
                                      } else {
                                          return new Token(Token.INVALID, toRangeString, yyline+1, yycolumn+1-toRangeString.length());
                                      }}
}

[^]                      { System.out.println("Illegal character <" + yytext() + ">");
                           return new Token(Token.INVALID, yytext(), yyline+1, yycolumn+1); }



