📄 parseinstance.cxx
字号:
const RankStem *rankStem = currentDtd().lookupRankStem(name); if (rankStem) { StringC name(rankStem->name()); if (!appendCurrentRank(name, rankStem)) message(ParserMessages::noCurrentRank, StringMessageArg(name)); else return currentDtdNonConst().lookupElementType(name); } return 0;}void Parser::handleRankedElement(const ElementType *e){ StringC rankSuffix(e->definition()->rankSuffix()); const RankStem *rankStem = e->rankedElementRankStem(); for (size_t i = 0; i < rankStem->nDefinitions(); i++) { const ElementDefinition *def = rankStem->definition(i); for (size_t j = 0; j < def->nRankStems(); j++) setCurrentRank(def->rankStem(j), rankSuffix); }}void Parser::checkTaglen(Index tagStartIndex){ const InputSourceOrigin *origin = currentLocation().origin()->asInputSourceOrigin(); ASSERT(origin != 0); if (origin->startOffset(currentLocation().index()) - origin->startOffset(tagStartIndex + syntax().delimGeneral(Syntax::dSTAGO).size()) > syntax().taglen()) message(ParserMessages::taglen, NumberMessageArg(syntax().taglen()));}void Parser::parseEmptyStartTag(){ if (options().warnEmptyTag) message(ParserMessages::emptyStartTag); // FIXME error if not in base. const ElementType *e = 0; if (!sd().omittag()) e = lastEndedElementType(); else if (tagLevel() > 0) e = currentElement().type(); if (!e) e = currentDtd().documentElementType(); AttributeList *attributes = allocAttributeList(e->attributeDef(), 0); attributes->finish(*this); Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); if (markup) { markup->addDelim(Syntax::dSTAGO); markup->addDelim(Syntax::dTAGC); } acceptStartTag(e, new (eventAllocator()) StartElementEvent(e, currentDtdPointer(), attributes, markupLocation(), markup), 0);}void Parser::parseGroupStartTag(){ if (startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation())) { currentMarkup()->addDelim(Syntax::dSTAGO); currentMarkup()->addDelim(Syntax::dGRPO); } Boolean active; if (!parseTagNameGroup(active)) return; InputSource *in = currentInput(); // Location startLocation = in->currentLocation(); in->startToken(); Xchar c = in->tokenChar(messenger()); if (!syntax().isNameStartCharacter(c)) { message(ParserMessages::startTagMissingName); return; } in->discardInitial(); extendNameToken(syntax().namelen(), ParserMessages::nameLength); if (currentMarkup()) currentMarkup()->addName(currentInput()); skipAttributeSpec(); if (currentMarkup()) eventHandler().ignoredMarkup(new (eventAllocator()) IgnoredMarkupEvent(markupLocation(), currentMarkup())); noteMarkup();}void Parser::parseGroupEndTag(){ if (startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation())) { currentMarkup()->addDelim(Syntax::dSTAGO); currentMarkup()->addDelim(Syntax::dGRPO); } Boolean active; if (!parseTagNameGroup(active)) return; InputSource *in = currentInput(); // Location startLocation = in->currentLocation(); in->startToken(); Xchar c = in->tokenChar(messenger()); if (!syntax().isNameStartCharacter(c)) { message(ParserMessages::endTagMissingName); return; } in->discardInitial(); extendNameToken(syntax().namelen(), ParserMessages::nameLength); if (currentMarkup()) currentMarkup()->addName(currentInput()); parseEndTagClose(); if (currentMarkup()) eventHandler().ignoredMarkup(new (eventAllocator()) IgnoredMarkupEvent(markupLocation(), currentMarkup())); noteMarkup();}void Parser::acceptPcdata(const Location &startLocation){ if (currentElement().tryTransitionPcdata()) return; // Need to test here since implying tags may turn off pcdataRecovering. if (pcdataRecovering()) return; IList<Undo> undoList; IList<Event> eventList; unsigned startImpliedCount = 0; unsigned attributeListIndex = 0; keepMessages(); while (tryImplyTag(startLocation, startImpliedCount, attributeListIndex, undoList, eventList)) if (currentElement().tryTransitionPcdata()) { queueElementEvents(eventList); return; } discardKeptMessages(); undo(undoList); if (validate() || afterDocumentElement()) message(ParserMessages::pcdataNotAllowed); pcdataRecover();}void Parser::acceptStartTag(const ElementType *e, StartElementEvent *event, Boolean netEnabling){ if (e->definition()->undefined() && !implydefElement()) message(ParserMessages::undefinedElement, StringMessageArg(e->name())); if (elementIsExcluded(e)) { keepMessages(); if (validate()) checkExclusion(e); } else { if (currentElement().tryTransition(e)) { pushElementCheck(e, event, netEnabling); return; } if (elementIsIncluded(e)) { event->setIncluded(); pushElementCheck(e, event, netEnabling); return; } keepMessages(); } IList<Undo> undoList; IList<Event> eventList; unsigned startImpliedCount = 0; unsigned attributeListIndex = 1; while (tryImplyTag(event->location(), startImpliedCount, attributeListIndex, undoList, eventList)) if (tryStartTag(e, event, netEnabling, eventList)) return; discardKeptMessages(); undo(undoList); if (validate() && !e->definition()->undefined()) handleBadStartTag(e, event, netEnabling); else { if (validate() ? implydefElement() : afterDocumentElement()) message(ParserMessages::elementNotAllowed, StringMessageArg(e->name())); // If element couldn't occur because it was excluded, then // do the transition here. (void)currentElement().tryTransition(e); pushElementCheck(e, event, netEnabling); }}void Parser::undo(IList<Undo> &undoList){ while (!undoList.empty()) { Undo *p = undoList.get(); p->undo(this); delete p; }}void Parser::queueElementEvents(IList<Event> &events){ releaseKeptMessages(); // FIXME provide IList<T>::reverse function // reverse it IList<Event> tem; while (!events.empty()) tem.insert(events.get()); while (!tem.empty()) { Event *e = tem.get(); if (e->type() == Event::startElement) { noteStartElement(((StartElementEvent *)e)->included()); eventHandler().startElement((StartElementEvent *)e); } else { noteEndElement(((EndElementEvent *)e)->included()); eventHandler().endElement((EndElementEvent *)e); } }}void Parser::checkExclusion(const ElementType *e){ const LeafContentToken *token = currentElement().invalidExclusion(e); if (token) message(ParserMessages::invalidExclusion, OrdinalMessageArg(token->typeIndex() + 1), StringMessageArg(token->elementType()->name()), StringMessageArg(currentElement().type()->name()));}Boolean Parser::tryStartTag(const ElementType *e, StartElementEvent *event, Boolean netEnabling, IList<Event> &impliedEvents){ if (elementIsExcluded(e)) { checkExclusion(e); return 0; } if (currentElement().tryTransition(e)) { queueElementEvents(impliedEvents); pushElementCheck(e, event, netEnabling); return 1; } if (elementIsIncluded(e)) { queueElementEvents(impliedEvents); event->setIncluded(); pushElementCheck(e, event, netEnabling); return 1; } return 0;}Boolean Parser::tryImplyTag(const Location &loc, unsigned &startImpliedCount, unsigned &attributeListIndex, IList<Undo> &undo, IList<Event> &eventList){ if (!sd().omittag()) return 0; if (currentElement().isFinished()) { if (tagLevel() == 0) return 0;#if 1 const ElementDefinition *def = currentElement().type()->definition(); if (def && !def->canOmitEndTag()) return 0;#endif // imply an end tag if (startImpliedCount > 0) { message(ParserMessages::startTagEmptyElement, StringMessageArg(currentElement().type()->name())); startImpliedCount--; }#if 0 const ElementDefinition *def = currentElement().type()->definition(); if (def && !def->canOmitEndTag()) message(ParserMessages::omitEndTagDeclare, StringMessageArg(currentElement().type()->name()), currentElement().startLocation());#endif EndElementEvent *event = new (eventAllocator()) EndElementEvent(currentElement().type(), currentDtdPointer(), loc, 0); eventList.insert(event); undo.insert(new (internalAllocator()) UndoEndTag(popSaveElement())); return 1; } const LeafContentToken *token = currentElement().impliedStartTag(); if (!token) return 0; const ElementType *e = token->elementType(); if (elementIsExcluded(e)) message(ParserMessages::requiredElementExcluded, OrdinalMessageArg(token->typeIndex() + 1), StringMessageArg(e->name()), StringMessageArg(currentElement().type()->name())); if (tagLevel() != 0) undo.insert(new (internalAllocator()) UndoTransition(currentElement().matchState())); currentElement().doRequiredTransition(); const ElementDefinition *def = e->definition(); if (def->declaredContent() != ElementDefinition::modelGroup && def->declaredContent() != ElementDefinition::any) message(ParserMessages::omitStartTagDeclaredContent, StringMessageArg(e->name())); if (def->undefined()) message(ParserMessages::undefinedElement, StringMessageArg(e->name())); else if (!def->canOmitStartTag()) message(ParserMessages::omitStartTagDeclare, StringMessageArg(e->name())); AttributeList *attributes = allocAttributeList(e->attributeDef(), attributeListIndex++); // this will give an error if the element has a required attribute attributes->finish(*this); startImpliedCount++; StartElementEvent *event = new (eventAllocator()) StartElementEvent(e, currentDtdPointer(), attributes, loc, 0); pushElementCheck(e, event, undo, eventList); const int implyCheckLimit = 30; // this is fairly arbitrary if (startImpliedCount > implyCheckLimit && !checkImplyLoop(startImpliedCount)) return 0; return 1;}void Parser::pushElementCheck(const ElementType *e, StartElementEvent *event, Boolean netEnabling){ if (tagLevel() == syntax().taglvl()) message(ParserMessages::taglvlOpenElements, NumberMessageArg(syntax().taglvl())); noteStartElement(event->included()); if (event->mustOmitEnd()) { if (sd().emptyElementNormal()) { Boolean included = event->included(); Location loc(event->location()); eventHandler().startElement(event); endTagEmptyElement(e, netEnabling, included, loc); } else { EndElementEvent *end = new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), event->location(), 0); if (event->included()) { end->setIncluded(); noteEndElement(1); } else noteEndElement(0); eventHandler().startElement(event); eventHandler().endElement(end); } } else { const ShortReferenceMap *map = e->map(); if (!map) map = currentElement().map(); pushElement(new (internalAllocator()) OpenElement(e, netEnabling, event->included(), map, event->location())); // Can't access event after it's passed to the event handler. eventHandler().startElement(event); }}void Parser::endTagEmptyElement(const ElementType *e, Boolean netEnabling, Boolean included, const Location &startLoc){ Token token = getToken(netEnabling ? econnetMode : econMode); switch (token) { case tokenNet: if (netEnabling) { Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); if (markup) markup->addDelim(Syntax::dNET); EndElementEvent *end = new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), currentLocation(), markup); if (included) end->setIncluded(); eventHandler().endElement(end); noteEndElement(included); return; } break; case tokenEtagoTagc: { if (options().warnEmptyTag) message(ParserMessages::emptyEndTag); Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); if (markup) { markup->addDelim(Syntax::dETAGO); markup->addDelim(Syntax::dTAGC); } EndElementEvent *end = new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), currentLocation(), markup); if (included) end->setIncluded(); eventHandler().endElement(end); noteEndElement(included); return; } case tokenEtagoNameStart: { EndElementEvent *end = parseEndTag(); if (end->elementType() == e) { if (included) end->setIncluded(); eventHandler().endElement(end); noteEndElement(included); return; } if (!elementIsOpen(end->elementType())) { message(ParserMessages::elementNotOpen, StringMessageArg(end->elementType()->name())); delete end; break; } implyEmptyElementEnd(e, included, startLoc); acceptEndTag(end); return; } default: break; } implyEmptyElementEnd(e, included, startLoc); currentInput()->ungetToken();}void Parser::implyEmptyElementEnd(const ElementType *e, Boolean included, const Location &startLoc){ if (!sd().omittag()) message(ParserMessages::omitEndTagOmittag, StringMessageArg(e->name()), startLoc); else { const ElementDefinition *def = e->definition(); if (def && !def->canOmitEndTag()) message(ParserMessages::omitEndTagDeclare, StringMessageArg(e->name()), startLoc); } EndElementEvent *end = new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), currentLocation(), 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -