/*
 * Units of Measurement Implementation for Java SE
 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/* Generated By:JavaCC: Do not edit this line. UnitTokenManager.java */
package tec.uom.se.internal.format;

/** Token Manager. */
final class UnitTokenManager {

  /** Debug output. */
  public java.io.PrintStream debugStream = System.out;

  /** Set debug output. */
  public void setDebugStream(java.io.PrintStream ds) {
    debugStream = ds;
  }

  private int jjStopStringLiteralDfa_0(int pos) {
    switch (pos) {
      default:
        return -1;
    }
  }

  private int jjStartNfa_0(int pos, long active0) {
    return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos), pos + 1);
  }

  private int jjStopAtPos(int pos, int kind) {
    jjmatchedKind = kind;
    jjmatchedPos = pos;
    return pos + 1;
  }

  private int jjMoveStringLiteralDfa0_0() {
    switch (curChar) {
      case 40:
        return jjStopAtPos(0, 12);
      case 41:
        return jjStopAtPos(0, 13);
      case 42:
        return jjStopAtPos(0, 7);
      case 43:
        return jjStopAtPos(0, 5);
      case 45:
        return jjStopAtPos(0, 6);
      case 47:
        return jjStopAtPos(0, 9);
      case 58:
        return jjStopAtPos(0, 11);
      case 94:
        return jjStopAtPos(0, 10);
      case 101:
        return jjStartNfaWithStates_0(0, 19, 7);
      case 183:
        return jjStopAtPos(0, 8);
      default:
        return jjMoveNfa_0(6, 0);
    }
  }

  private int jjStartNfaWithStates_0(int pos, int kind, int state) {
    jjmatchedKind = kind;
    jjmatchedPos = pos;
    try {
      curChar = input_stream.readChar();
    } catch (java.io.IOException e) {
      return pos + 1;
    }
    return jjMoveNfa_0(state, pos + 1);
  }

  static final long[] jjbitVec0 = { 0x0L, 0x0L, 0x20c000000000000L, 0x0L };
  static final long[] jjbitVec1 = { 0x0L, 0x3f1000000000000L, 0x0L, 0x0L };
  static final long[] jjbitVec2 = { 0xfffffffefffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL };
  static final long[] jjbitVec4 = { 0x0L, 0x0L, 0xfd73ffffffffffffL, 0xffffffffffffffffL };
  static final long[] jjbitVec5 = { 0xffffffffffffffffL, 0xfc0effffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL };

  private int jjMoveNfa_0(int startState, int curPos) {
    int startsAt = 0;
    jjnewStateCnt = 15;
    int i = 1;
    jjstateSet[0] = startState;
    int kind = 0x7fffffff;
    for (;;) {
      if (++jjround == 0x7fffffff)
        ReInitRounds();
      if (curChar < 64) {
        long l = 1L << curChar;
        do {
          switch (jjstateSet[--i]) {
            case 6:
              if ((0xf80010fe00000000L & l) != 0L) {
                if (kind > 20)
                  kind = 20;
                jjCheckNAdd(7);
              } else if ((0x3ff000000000000L & l) != 0L) {
                if (kind > 14)
                  kind = 14;
                jjCheckNAddStates(0, 4);
              } else if (curChar == 46)
                jjCheckNAdd(2);
              break;
            case 1:
              if (curChar == 46)
                jjCheckNAdd(2);
              break;
            case 2:
              if ((0x3ff000000000000L & l) == 0L)
                break;
              if (kind > 16)
                kind = 16;
              jjCheckNAddTwoStates(2, 3);
              break;
            case 4:
              if ((0x280000000000L & l) != 0L)
                jjCheckNAdd(5);
              break;
            case 5:
              if ((0x3ff000000000000L & l) == 0L)
                break;
              if (kind > 16)
                kind = 16;
              jjCheckNAdd(5);
              break;
            case 7:
              if ((0xfbff10fe00000000L & l) == 0L)
                break;
              if (kind > 20)
                kind = 20;
              jjCheckNAdd(7);
              break;
            case 8:
              if ((0x3ff000000000000L & l) == 0L)
                break;
              if (kind > 14)
                kind = 14;
              jjCheckNAddStates(0, 4);
              break;
            case 9:
              if ((0x3ff000000000000L & l) == 0L)
                break;
              if (kind > 14)
                kind = 14;
              jjCheckNAdd(9);
              break;
            case 10:
              if ((0x3ff000000000000L & l) == 0L)
                break;
              if (kind > 16)
                kind = 16;
              jjCheckNAddStates(5, 8);
              break;
            default:
              break;
          }
        } while (i != startsAt);
      } else if (curChar < 128) {
        long l = 1L << (curChar & 63);
        do {
          switch (jjstateSet[--i]) {
            case 6:
              if ((0xffffffffbfffffffL & l) != 0L) {
                if (kind > 20)
                  kind = 20;
                jjCheckNAdd(7);
              }
              if (curChar == 108)
                jjAddStates(9, 10);
              break;
            case 3:
              if ((0x2000000020L & l) != 0L)
                jjAddStates(11, 12);
              break;
            case 7:
              if ((0xffffffffbfffffffL & l) == 0L)
                break;
              if (kind > 20)
                kind = 20;
              jjCheckNAdd(7);
              break;
            case 11:
              if (curChar == 108)
                jjAddStates(9, 10);
              break;
            case 12:
              if (curChar == 111)
                jjstateSet[jjnewStateCnt++] = 13;
              break;
            case 13:
              if (curChar == 103 && kind > 17)
                kind = 17;
              break;
            case 14:
              if (curChar == 110 && kind > 18)
                kind = 18;
              break;
            default:
              break;
          }
        } while (i != startsAt);
      } else {
        int hiByte = curChar >> 8;
        int i1 = hiByte >> 6;
        long l1 = 1L << (hiByte & 63);
        int i2 = (curChar & 0xff) >> 6;
        long l2 = 1L << (curChar & 63);
        do {
          switch (jjstateSet[--i]) {
            case 6:
              if (jjCanMove_0(hiByte, i2, l2)) {
                if (kind > 15)
                  kind = 15;
                jjCheckNAdd(0);
              }
              if (jjCanMove_1(hiByte, i1, i2, l1, l2)) {
                if (kind > 20)
                  kind = 20;
                jjCheckNAdd(7);
              }
              break;
            case 0:
              if (!jjCanMove_0(hiByte, i2, l2))
                break;
              if (kind > 15)
                kind = 15;
              jjCheckNAdd(0);
              break;
            case 7:
              if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                break;
              if (kind > 20)
                kind = 20;
              jjCheckNAdd(7);
              break;
            default:
              break;
          }
        } while (i != startsAt);
      }
      if (kind != 0x7fffffff) {
        jjmatchedKind = kind;
        jjmatchedPos = curPos;
        kind = 0x7fffffff;
      }
      ++curPos;
      if ((i = jjnewStateCnt) == (startsAt = 15 - (jjnewStateCnt = startsAt)))
        return curPos;
      try {
        curChar = input_stream.readChar();
      } catch (java.io.IOException e) {
        return curPos;
      }
    }
  }

  static final int[] jjnextStates = { 9, 1, 2, 3, 10, 1, 2, 3, 10, 12, 14, 4, 5, };

  private static boolean jjCanMove_0(int hiByte, int i2, long l2) {
    switch (hiByte) {
      case 0:
        return ((jjbitVec0[i2] & l2) != 0L);
      case 32:
        return ((jjbitVec1[i2] & l2) != 0L);
      default:
        return false;
    }
  }

  private static boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) {
    switch (hiByte) {
      case 0:
        return ((jjbitVec4[i2] & l2) != 0L);
      case 32:
        return ((jjbitVec5[i2] & l2) != 0L);
      default:
        return (jjbitVec2[i1] & l1) != 0L;
    }
  }

  /** Token literal values. */
  public static final String[] jjstrLiteralImages = { "", null, null, null, null, "\53", "\55", "\52", "\267", "\57", "\136", "\72", "\50", "\51",
      null, null, null, null, null, "\145", null, };

  /** Lexer state names. */
  public static final String[] lexStateNames = { "DEFAULT", };
  protected DefaultCharStream input_stream;
  private final int[] jjrounds = new int[15];
  private final int[] jjstateSet = new int[30];
  protected char curChar;

  /** Constructor. */
  public UnitTokenManager(DefaultCharStream stream) {
    if (DefaultCharStream.staticFlag)
      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
    input_stream = stream;
  }

  /** Constructor. */
  public UnitTokenManager(DefaultCharStream stream, int lexState) {
    this(stream);
    SwitchTo(lexState);
  }

  /** Reinitialise parser. */
  public void ReInit(DefaultCharStream stream) {
    jjmatchedPos = jjnewStateCnt = 0;
    curLexState = defaultLexState;
    input_stream = stream;
    ReInitRounds();
  }

  private void ReInitRounds() {
    int i;
    jjround = 0x80000001;
    for (i = 15; i-- > 0;)
      jjrounds[i] = 0x80000000;
  }

  /** Reinitialise parser. */
  public void ReInit(DefaultCharStream stream, int lexState) {
    ReInit(stream);
    SwitchTo(lexState);
  }

  /** Switch to specified lex state. */
  public void SwitchTo(int lexState) {
    if (lexState >= 1 || lexState < 0)
      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
    else
      curLexState = lexState;
  }

  protected Token jjFillToken() {
    final Token t;
    final String curTokenImage;
    final int beginLine;
    final int endLine;
    final int beginColumn;
    final int endColumn;
    String im = jjstrLiteralImages[jjmatchedKind];
    curTokenImage = (im == null) ? input_stream.GetImage() : im;
    beginLine = input_stream.getBeginLine();
    beginColumn = input_stream.getBeginColumn();
    endLine = input_stream.getEndLine();
    endColumn = input_stream.getEndColumn();
    t = Token.newToken(jjmatchedKind, curTokenImage);

    t.beginLine = beginLine;
    t.endLine = endLine;
    t.beginColumn = beginColumn;
    t.endColumn = endColumn;

    return t;
  }

  int curLexState = 0;
  final int defaultLexState = 0;
  int jjnewStateCnt;
  int jjround;
  int jjmatchedPos;
  int jjmatchedKind;

  /** Get the next Token. */
  public Token getNextToken() {
    Token matchedToken;
    int curPos = 0;

    EOFLoop: for (;;) {
      try {
        curChar = input_stream.BeginToken();
      } catch (java.io.IOException e) {
        jjmatchedKind = 0;
        matchedToken = jjFillToken();
        return matchedToken;
      }

      jjmatchedKind = 0x7fffffff;
      jjmatchedPos = 0;
      curPos = jjMoveStringLiteralDfa0_0();
      if (jjmatchedKind != 0x7fffffff) {
        if (jjmatchedPos + 1 < curPos)
          input_stream.backup(curPos - jjmatchedPos - 1);
        matchedToken = jjFillToken();
        return matchedToken;
      }
      int error_line = input_stream.getEndLine();
      int error_column = input_stream.getEndColumn();
      String error_after = null;
      boolean EOFSeen = false;
      try {
        input_stream.readChar();
        input_stream.backup(1);
      } catch (java.io.IOException e1) {
        EOFSeen = true;
        error_after = curPos <= 1 ? "" : input_stream.GetImage();
        if (curChar == '\n' || curChar == '\r') {
          error_line++;
          error_column = 0;
        } else
          error_column++;
      }
      if (!EOFSeen) {
        input_stream.backup(1);
        error_after = curPos <= 1 ? "" : input_stream.GetImage();
      }
      throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
    }
  }

  private void jjCheckNAdd(int state) {
    if (jjrounds[state] != jjround) {
      jjstateSet[jjnewStateCnt++] = state;
      jjrounds[state] = jjround;
    }
  }

  private void jjAddStates(int start, int end) {
    do {
      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
    } while (start++ != end);
  }

  private void jjCheckNAddTwoStates(int state1, int state2) {
    jjCheckNAdd(state1);
    jjCheckNAdd(state2);
  }

  private void jjCheckNAddStates(int start, int end) {
    do {
      jjCheckNAdd(jjnextStates[start]);
    } while (start++ != end);
  }

}
