protected void parseTag(boolean multipleRootTagError) {
    assert token() == XML_START_TAG_START : "Tag start expected";
    final PsiBuilder.Marker tag = mark();

    final String tagName = parseTagHeader(multipleRootTagError, tag);
    if (tagName == null) return;

    final PsiBuilder.Marker content = mark();
    parseTagContent();

    if (token() == XML_END_TAG_START) {
      final PsiBuilder.Marker footer = mark();
      advance();

      if (token() == XML_NAME) {
        String endName = myBuilder.getTokenText();
        if (!tagName.equals(endName) && myTagNamesStack.contains(endName)) {
          footer.rollbackTo();
          myTagNamesStack.pop();
          tag.doneBefore(XML_TAG, content, XmlPsiBundle.message("xml.parsing.named.element.is.not.closed", tagName));
          content.drop();
          return;
        }

        advance();
      }
      else {
        error(XmlPsiBundle.message("xml.parsing.closing.tag.name.missing"));
      }
      footer.drop();

      while (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START && token() != XmlTokenType.XML_END_TAG_START && !eof()) {
        error(XmlPsiBundle.message("xml.parsing.unexpected.token"));
        advance();
      }

      if (token() == XML_TAG_END) {
        advance();
      }
      else {
        error(XmlPsiBundle.message("xml.parsing.closing.tag.is.not.done"));
      }
    }
    else {
      error(XmlPsiBundle.message("xml.parsing.unexpected.end.of.file"));
    }

    content.drop();
    myTagNamesStack.pop();
    tag.done(XML_TAG);
  }
protected void parseTag(boolean multipleRootTagError)