private static ArrayList<Token> tokenize(String typeInfoString) {
      ArrayList<Token> tokens = new ArrayList<Token>(0);
      int begin = 0;
      int end = 1;
      while (end <= typeInfoString.length()) {
        // last character ends a token?
        // if there are quotes, all the text between the quotes
        // is considered a single token (this can happen for
        // timestamp with local time-zone)
        if (begin > 0 &&
            typeInfoString.charAt(begin - 1) == '(' &&
            typeInfoString.charAt(begin) == '\'') {
          // Ignore starting quote
          begin++;
          do {
            end++;
          } while (typeInfoString.charAt(end) != '\'');
        } else if (typeInfoString.charAt(begin) == '\'' &&
            typeInfoString.charAt(begin + 1) == ')') {
          // Ignore closing quote
          begin++;
          end++;
        }
        if (end == typeInfoString.length()
            || !isTypeChar(typeInfoString.charAt(end - 1))
            || !isTypeChar(typeInfoString.charAt(end))) {
          Token t = new Token();
          t.position = begin;
          t.text = typeInfoString.substring(begin, end).trim();
          t.isType = isTypeChar(typeInfoString.charAt(begin));
          tokens.add(t);
          begin = end;
        }
        end++;
      }
      return tokens;
    }
Tokenize the typeInfoString. The rule is simple: all consecutive
alphadigits and '_', '.' are in one token, and all other characters are
one character per token.

tokenize("map<int,string>") should return
["map","<","int",",","string",">"]

Note that we add '$' in new Calcite return path. As '$' will not appear
in any type in Hive, it is safe to do so.
serde/src/java/org/apache/hadoop/hive/serde2/typeinfo/TypeInfoUtils.java