/**
   * Note - caller should reset {@link #_pointer} upon <code>null</code> result
   *
   * @return The sheet name as an identifier <code>null</code> if '!' is not found in the right
   *     place
   */
  private SheetIdentifier parseSheetName() {

    String bookName;
    if (look == '[') {
      StringBuilder sb = new StringBuilder();
      GetChar();
      while (look != ']') {
        sb.append(look);
        GetChar();
      }
      GetChar();
      bookName = sb.toString();
    } else {
      bookName = null;
    }

    if (look == '\'') {
      StringBuffer sb = new StringBuffer();

      Match('\'');
      boolean done = look == '\'';
      while (!done) {
        sb.append(look);
        GetChar();
        if (look == '\'') {
          Match('\'');
          done = look != '\'';
        }
      }

      Identifier iden = new Identifier(sb.toString(), true);
      // quoted identifier - can't concatenate anything more
      SkipWhite();
      if (look == '!') {
        GetChar();
        return new SheetIdentifier(bookName, iden, _book);
      }
      return null;
    }

    // unquoted sheet names must start with underscore or a letter
    if (look == '_' || Character.isLetter(look)) {
      StringBuilder sb = new StringBuilder();
      // can concatenate idens with dots
      while (isUnquotedSheetNameChar(look)) {
        sb.append(look);
        GetChar();
      }
      SkipWhite();
      if (look == '!') {
        GetChar();
        return new SheetIdentifier(bookName, new Identifier(sb.toString(), false), _book);
      }
      return null;
    }
    return null;
  }
  /** Get a Number */
  private String GetNum() {
    StringBuffer value = new StringBuffer();

    while (IsDigit(this.look)) {
      value.append(this.look);
      GetChar();
    }
    return value.length() == 0 ? null : value.toString();
  }
  private String parseStringLiteral() {
    Match('"');

    StringBuffer token = new StringBuffer();
    while (true) {
      if (look == '"') {
        GetChar();
        if (look != '"') {
          break;
        }
      }
      token.append(look);
      GetChar();
    }
    return token.toString();
  }
 public String toString() {
   StringBuffer sb = new StringBuffer(64);
   sb.append(getClass().getName());
   sb.append(" [");
   if (_bookName != null) {
     sb.append(" [").append(_sheetIdentifier.getName()).append("]");
   }
   if (_sheetIdentifier.isQuoted()) {
     sb.append("'").append(_sheetIdentifier.getName()).append("'");
   } else {
     sb.append(_sheetIdentifier.getName());
   }
   sb.append("]");
   return sb.toString();
 }
 public String toString() {
   StringBuffer sb = new StringBuffer(64);
   sb.append(getClass().getName());
   sb.append(" [");
   if (_isQuoted) {
     sb.append("'").append(_name).append("'");
   } else {
     sb.append(_name);
   }
   sb.append("]");
   return sb.toString();
 }
  /**
   * Get a PTG for an integer from its string representation. return Int or Number Ptg based on size
   * of input
   */
  private static Ptg getNumberPtgFromString(String number1, String number2, String exponent) {
    StringBuffer number = new StringBuffer();

    if (number2 == null) {
      number.append(number1);

      if (exponent != null) {
        number.append('E');
        number.append(exponent);
      }

      String numberStr = number.toString();
      int intVal;
      try {
        intVal = Integer.parseInt(numberStr);
      } catch (NumberFormatException e) {
        return new NumberPtg(numberStr);
      }
      if (IntPtg.isInRange(intVal)) {
        return new IntPtg(intVal);
      }
      return new NumberPtg(numberStr);
    }

    if (number1 != null) {
      number.append(number1);
    }

    number.append('.');
    number.append(number2);

    if (exponent != null) {
      number.append('E');
      number.append(exponent);
    }

    return new NumberPtg(number.toString());
  }