protected void handleTagEnd(
      List<BBCodeItem> bbCodeItems, Stack<String> tags, BBCodeToken bbCodeToken) {

    int size = 0;

    if (bbCodeToken != null) {
      String endTag = bbCodeToken.getEndTag();

      for (size = tags.size() - 1; size >= 0; size--) {
        if (endTag.equals(tags.elementAt(size))) {
          break;
        }
      }
    }

    if (size >= 0) {
      for (int i = tags.size() - 1; i >= size; i--) {
        BBCodeItem bbCodeItem = new BBCodeItem(TYPE_TAG_END, null, tags.elementAt(i));

        bbCodeItems.add(bbCodeItem);
      }

      tags.setSize(size);
    }
  }
  public List<BBCodeItem> parse(String text) {
    List<BBCodeItem> bbCodeItems = new ArrayList<>();

    BBCodeLexer bbCodeLexer = new BBCodeLexer(text);
    Stack<String> tags = new Stack<>();
    IntegerWrapper marker = new IntegerWrapper();

    BBCodeToken bbCodeToken = null;

    while ((bbCodeToken = bbCodeLexer.getNextBBCodeToken()) != null) {
      handleData(bbCodeItems, bbCodeLexer, marker, bbCodeToken, text);

      if (bbCodeToken.getStartTag() == null) {
        handleTagEnd(bbCodeItems, tags, bbCodeToken);

        continue;
      }

      handleTagStart(bbCodeItems, tags, bbCodeToken);

      String startTag = bbCodeToken.getStartTag();

      if (!startTag.equals("code")) {
        continue;
      }

      while (true) {
        bbCodeToken = bbCodeLexer.getNextBBCodeToken();

        if (bbCodeToken == null) {
          break;
        }

        String endTag = GetterUtil.getString(bbCodeToken.getEndTag());

        if (endTag.equals("code")) {
          break;
        }
      }

      handleData(bbCodeItems, bbCodeLexer, marker, bbCodeToken, text);

      if (bbCodeToken != null) {
        handleTagEnd(bbCodeItems, tags, bbCodeToken);
      } else {
        break;
      }
    }

    handleData(bbCodeItems, bbCodeLexer, marker, null, text);
    handleTagEnd(bbCodeItems, tags, null);

    return bbCodeItems;
  }