private static void addGroupType(Tokenizer st, Repetition r, GroupBuilder<?> builder) {
    GroupBuilder<?> childBuilder = builder.group(r);
    String t;
    String name = st.nextToken();

    // Read annotation, if any.
    t = st.nextToken();
    OriginalType originalType = null;
    if (t.equalsIgnoreCase("(")) {
      originalType = OriginalType.valueOf(st.nextToken());
      childBuilder.as(originalType);
      check(st.nextToken(), ")", "original type ended by )", st);
      t = st.nextToken();
    }
    if (t.equals("=")) {
      childBuilder.id(Integer.parseInt(st.nextToken()));
      t = st.nextToken();
    }
    try {
      addGroupTypeFields(t, st, childBuilder);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException(
          "problem reading type: type = group, name = "
              + name
              + ", original type = "
              + originalType,
          e);
    }

    childBuilder.named(name);
  }
  private static void addPrimitiveType(
      Tokenizer st, PrimitiveTypeName type, Repetition r, Types.GroupBuilder<?> builder) {
    PrimitiveBuilder<?> childBuilder = builder.primitive(type, r);
    String t;

    if (type == PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY) {
      t = st.nextToken();
      // Read type length if the type is fixed_len_byte_array.
      if (!t.equalsIgnoreCase("(")) {
        throw new IllegalArgumentException(
            "expecting (length) for field of type fixed_len_byte_array");
      }
      childBuilder.length(Integer.parseInt(st.nextToken()));
      check(st.nextToken(), ")", "type length ended by )", st);
    }

    String name = st.nextToken();

    // Read annotation, if any.
    t = st.nextToken();
    OriginalType originalType = null;
    if (t.equalsIgnoreCase("(")) {
      originalType = OriginalType.valueOf(st.nextToken());
      childBuilder.as(originalType);
      if (OriginalType.DECIMAL == originalType) {
        t = st.nextToken();
        // parse precision and scale
        if (t.equalsIgnoreCase("(")) {
          childBuilder.precision(Integer.parseInt(st.nextToken()));
          t = st.nextToken();
          if (t.equalsIgnoreCase(",")) {
            childBuilder.scale(Integer.parseInt(st.nextToken()));
            t = st.nextToken();
          }
          check(t, ")", "decimal type ended by )", st);
          t = st.nextToken();
        }
      } else {
        t = st.nextToken();
      }
      check(t, ")", "original type ended by )", st);
      t = st.nextToken();
    }
    if (t.equals("=")) {
      childBuilder.id(Integer.parseInt(st.nextToken()));
      t = st.nextToken();
    }
    check(t, ";", "field ended by ';'", st);

    try {
      childBuilder.named(name);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException(
          "problem reading type: type = "
              + type
              + ", name = "
              + name
              + ", original type = "
              + originalType,
          e);
    }
  }