* @param punctuationchars
   * @param quotechars
   * @param escapechars
   * @return Cons
   */
  public static Cons tokenizeString(String string, String punctuationchars, String quotechars, String escapechars) {
    { MemoizationTable memoTable000 = null;
      Cons memoizedEntry000 = null;
      Stella_Object memoizedValue000 = null;

      if (Stella.$MEMOIZATION_ENABLEDp$) {
        memoTable000 = ((MemoizationTable)(Stella.SGT_STELLA_F_TOKENIZE_STRING_MEMO_TABLE_000.surrogateValue));
        if (memoTable000 == null) {
          Surrogate.initializeMemoizationTable(Stella.SGT_STELLA_F_TOKENIZE_STRING_MEMO_TABLE_000, "(:MAX-VALUES 10)");
          memoTable000 = ((MemoizationTable)(Stella.SGT_STELLA_F_TOKENIZE_STRING_MEMO_TABLE_000.surrogateValue));
        }
        memoizedEntry000 = MruMemoizationTable.lookupMruMemoizedValue(((MruMemoizationTable)(memoTable000)), StringWrapper.wrapString(punctuationchars), StringWrapper.wrapString(quotechars), StringWrapper.wrapString(escapechars), Stella.MEMOIZED_NULL_VALUE, 0);
        memoizedValue000 = memoizedEntry000.value;
      }
      if (memoizedValue000 != null) {
        if (memoizedValue000 == Stella.MEMOIZED_NULL_VALUE) {
          memoizedValue000 = null;
        }
      }
      else {
        memoizedValue000 = Stella.createTokenizeStringTable(punctuationchars, quotechars, escapechars);
        if (Stella.$MEMOIZATION_ENABLEDp$) {
          memoizedEntry000.value = ((memoizedValue000 == null) ? Stella.MEMOIZED_NULL_VALUE : memoizedValue000);
        }
      }
      { Vector chartypetable = ((Vector)(memoizedValue000));
        int i = 0;
        char ch = Stella.NULL_CHARACTER;
        int start = 0;
        int end = string.length();
        Keyword state = Stella.KWD_TEXT;
        Keyword newstate = Stella.KWD_TEXT;
        boolean quotedtokenP = false;
        char quotechar = Stella.NULL_CHARACTER;
        boolean endoftokenP = false;
        Cons escapepositions = Stella.NIL;
        String token = null;
        Cons result = Stella.NIL;

        loop000 : for (;;) {
          endoftokenP = false;
          if (i < end) {
            ch = string.charAt(i);
            newstate = ((Keyword)((chartypetable.theArray)[((int) ch)]));
            if (newstate == Stella.KWD_TEXT) {
              if ((state == Stella.KWD_PUNCTUATION) ||
                  ((state == Stella.KWD_WHITE_SPACE) ||
                   (state == Stella.KWD_QUOTE))) {
                endoftokenP = true;
              }
              else {
              }
            }
            else if (newstate == Stella.KWD_ESCAPE) {
              if ((state == Stella.KWD_PUNCTUATION) ||
                  ((state == Stella.KWD_WHITE_SPACE) ||
                   (state == Stella.KWD_QUOTE))) {
                endoftokenP = true;
              }
              else {
              }
              escapepositions = Cons.cons(IntegerWrapper.wrapInteger(i), escapepositions);
              i = i + 2;
              continue loop000;
            }
            else if (newstate == Stella.KWD_QUOTE) {
              if (quotedtokenP &&
                  (ch == quotechar)) {
                endoftokenP = true;
                quotedtokenP = false;
              }
              else if (quotedtokenP) {
                newstate = Stella.KWD_TEXT;
              }
              else {
                endoftokenP = true;
                quotedtokenP = true;
                quotechar = ch;
              }
            }
            else if (newstate == Stella.KWD_PUNCTUATION) {
              if (state == Stella.KWD_TEXT) {
                if (quotedtokenP) {
                  newstate = Stella.KWD_TEXT;
                }
                else {
                  endoftokenP = true;
                }
              }
              else if ((state == Stella.KWD_WHITE_SPACE) ||
                  (state == Stella.KWD_QUOTE)) {
                endoftokenP = true;
              }
              else {
              }
            }
            else if (newstate == Stella.KWD_WHITE_SPACE) {
              if (state == Stella.KWD_TEXT) {
                if (quotedtokenP) {
                  newstate = Stella.KWD_TEXT;
                }
                else {
                  endoftokenP = true;
                }
              }
              else if ((state == Stella.KWD_PUNCTUATION) ||
                  (state == Stella.KWD_QUOTE)) {
                endoftokenP = true;
              }
              else {
              }
            }
            else {
              { OutputStringStream stream000 = OutputStringStream.newOutputStringStream();

                stream000.nativeStream.print("`" + newstate + "' is not a valid case option");
                throw ((StellaException)(StellaException.newStellaException(stream000.theStringReader()).fillInStackTrace()));
              }
            }
          }
          if ((endoftokenP &&
              (i > 0)) ||
              (i >= end)) {
            if (!(state == Stella.KWD_WHITE_SPACE)) {
              if (!(escapepositions == Stella.NIL)) {
                { Cons parts = Stella.NIL;
                  int s = start;

                  { IntegerWrapper e = null;
                    Cons iter000 = escapepositions.reverse();

                    for (;!(iter000 == Stella.NIL); iter000 = iter000.rest) {
                      e = ((IntegerWrapper)(iter000.value));
                      parts = Cons.cons(StringWrapper.wrapString(Native.string_subsequence(string, s, e.wrapperValue)), parts);
                      s = e.wrapperValue + 1;
                    }
                  }
                  parts = Cons.cons(StringWrapper.wrapString(Native.string_subsequence(string, Stella.integer_min(s, end), Stella.integer_min(i, end))), parts);
                  parts = parts.reverse();
                  token = Native.stringConcatenate(((StringWrapper)(parts.value)).wrapperValue, ((StringWrapper)(parts.rest.value)).wrapperValue);
                  { StringWrapper part = null;
                    Cons iter001 = parts.rest.rest;

                    for (;!(iter001 == Stella.NIL); iter001 = iter001.rest) {
                      part = ((StringWrapper)(iter001.value));
                      token = Native.stringConcatenate(token, part.wrapperValue);
                    }
                  }
                }
                escapepositions = Stella.NIL;
              }
              else {
                token = Native.string_subsequence(string, start, i);
              }
              result = Cons.cons(Cons.cons(StringWrapper.wrapString(token), Cons.cons(state, Stella.NIL)), result);
            }
            if (i >= end) {
              break loop000;
            }
            start = i;
          }
          state = newstate;
          i = i + 1;
        }
        return (result.reverse());
      }
    }
  }