📄 parseinstance.cxx
字号:
if (included) end->setIncluded(); noteEndElement(included); eventHandler().endElement(end);}void Parser::pushElementCheck(const ElementType *e, StartElementEvent *event, IList<Undo> &undoList, IList<Event> &eventList){ if (tagLevel() == syntax().taglvl()) message(ParserMessages::taglvlOpenElements, NumberMessageArg(syntax().taglvl())); eventList.insert(event); if (event->mustOmitEnd()) { EndElementEvent *end = new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), event->location(), 0); if (event->included()) end->setIncluded(); eventList.insert(end); } else { undoList.insert(new (internalAllocator()) UndoStartTag); const ShortReferenceMap *map = e->map(); if (!map) map = currentElement().map(); pushElement(new (internalAllocator()) OpenElement(e, 0, event->included(), map, event->location())); }}EndElementEvent *Parser::parseEndTag(){ Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); currentInput()->discardInitial(); extendNameToken(syntax().namelen(), ParserMessages::nameLength); if (markup) { markup->addDelim(Syntax::dETAGO); markup->addName(currentInput()); } StringC &name = nameBuffer(); getCurrentToken(syntax().generalSubstTable(), name); const ElementType *e = currentDtd().lookupElementType(name); if (sd().rank()) { if (!e) e = completeRankStem(name); } if (!e) e = lookupCreateUndefinedElement(name, currentLocation(), currentDtdNonConst()); parseEndTagClose(); return new (eventAllocator()) EndElementEvent(e, currentDtdPointer(), markupLocation(), markup);}void Parser::parseEndTagClose(){ for (;;) { Token token = getToken(tagMode); switch (token) { case tokenUnrecognized: if (!reportNonSgmlCharacter()) message(ParserMessages::endTagCharacter, StringMessageArg(currentToken())); return; case tokenEe: message(ParserMessages::endTagEntityEnd); return; case tokenEtago: case tokenStago: if (!sd().endTagUnclosed()) message(ParserMessages::unclosedEndTagShorttag); currentInput()->ungetToken(); return; case tokenTagc: if (currentMarkup()) currentMarkup()->addDelim(Syntax::dTAGC); return; case tokenS: if (currentMarkup()) currentMarkup()->addS(currentChar()); break; default: message(ParserMessages::endTagInvalidToken, TokenMessageArg(token, tagMode, syntaxPointer(), sdPointer())); return; } }}void Parser::parseEmptyEndTag(){ if (options().warnEmptyTag) message(ParserMessages::emptyEndTag); // FIXME what to do if not in base if (tagLevel() == 0) message(ParserMessages::emptyEndTagNoOpenElements); else { Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); if (markup) { markup->addDelim(Syntax::dETAGO); markup->addDelim(Syntax::dTAGC); } acceptEndTag(new (eventAllocator()) EndElementEvent(currentElement().type(), currentDtdPointer(), currentLocation(), markup)); }}void Parser::parseNullEndTag(){ // If a null end tag was recognized, then there must be a net enabling // element on the stack. for (;;) { ASSERT(tagLevel() > 0); if (currentElement().netEnabling()) break; if (!currentElement().isFinished() && validate()) message(ParserMessages::elementNotFinished, StringMessageArg(currentElement().type()->name())); implyCurrentElementEnd(currentLocation()); } if (!currentElement().isFinished() && validate()) message(ParserMessages::elementEndTagNotFinished, StringMessageArg(currentElement().type()->name())); Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation()); if (markup) markup->addDelim(Syntax::dNET); acceptEndTag(new (eventAllocator()) EndElementEvent(currentElement().type(), currentDtdPointer(), currentLocation(), markup));}void Parser::endAllElements(){ while (tagLevel() > 0) { if (!currentElement().isFinished()) message(ParserMessages::elementNotFinishedDocumentEnd, StringMessageArg(currentElement().type()->name())); implyCurrentElementEnd(currentLocation()); } if (!currentElement().isFinished() && validate()) message(ParserMessages::noDocumentElement);}void Parser::acceptEndTag(EndElementEvent *event){ const ElementType *e = event->elementType(); if (!elementIsOpen(e)) { message(ParserMessages::elementNotOpen, StringMessageArg(e->name())); delete event; return; } for (;;){ if (currentElement().type() == e) break; if (!currentElement().isFinished() && validate()) message(ParserMessages::elementNotFinished, StringMessageArg(currentElement().type()->name())); implyCurrentElementEnd(event->location()); } if (!currentElement().isFinished() && validate()) message(ParserMessages::elementEndTagNotFinished, StringMessageArg(currentElement().type()->name())); if (currentElement().included()) event->setIncluded(); noteEndElement(event->included()); eventHandler().endElement(event); popElement();}void Parser::implyCurrentElementEnd(const Location &loc){ if (!sd().omittag()) message(ParserMessages::omitEndTagOmittag, StringMessageArg(currentElement().type()->name()), currentElement().startLocation()); else { const ElementDefinition *def = currentElement().type()->definition(); if (def && !def->canOmitEndTag()) message(ParserMessages::omitEndTagDeclare, StringMessageArg(currentElement().type()->name()), currentElement().startLocation()); } EndElementEvent *event = new (eventAllocator()) EndElementEvent(currentElement().type(), currentDtdPointer(), loc, 0); if (currentElement().included()) event->setIncluded(); noteEndElement(event->included()); eventHandler().endElement(event); popElement();}void Parser::extendData(){ XcharMap<PackedBoolean> isNormal(normalMap()); InputSource *in = currentInput(); size_t length = in->currentTokenLength(); // This is one of the parser's inner loops, so it needs to be fast. while (isNormal[in->tokenCharInBuffer(messenger())]) length++; in->endToken(length);}void Parser::extendContentS(){ InputSource *in = currentInput(); size_t length = in->currentTokenLength(); XcharMap<PackedBoolean> isNormal(normalMap()); for (;;) { Xchar ch = in->tokenChar(messenger()); if (!syntax().isS(ch) || !isNormal[ch]) break; length++; } in->endToken(length);}void Parser::handleBadStartTag(const ElementType *e, StartElementEvent *event, Boolean netEnabling){ IList<Undo> undoList; IList<Event> eventList; keepMessages(); for (;;) { Vector<const ElementType *> missing; findMissingTag(e, missing); if (missing.size() == 1) { queueElementEvents(eventList); const ElementType *m = missing[0]; message(ParserMessages::missingElementInferred, StringMessageArg(e->name()), StringMessageArg(m->name())); AttributeList *attributes = allocAttributeList(m->attributeDef(), 1); // this will give an error if the element has a required attribute attributes->finish(*this); StartElementEvent *inferEvent = new (eventAllocator()) StartElementEvent(m, currentDtdPointer(), attributes, event->location(), 0); if (!currentElement().tryTransition(m)) inferEvent->setIncluded(); pushElementCheck(m, inferEvent, 0); if (!currentElement().tryTransition(e)) event->setIncluded(); pushElementCheck(e, event, netEnabling); return; } if (missing.size() > 0) { queueElementEvents(eventList); Vector<StringC> missingNames; for (size_t i = 0; i < missing.size(); i++) missingNames.push_back(missing[i]->name()); message(ParserMessages::missingElementMultiple, StringMessageArg(e->name()), StringVectorMessageArg(missingNames)); pushElementCheck(e, event, netEnabling); return; } if (!sd().omittag() || !currentElement().isFinished() || tagLevel() == 0 || !currentElement().type()->definition()->canOmitEndTag()) break; EndElementEvent *endEvent = new (eventAllocator()) EndElementEvent(currentElement().type(), currentDtdPointer(), event->location(), 0); eventList.insert(endEvent); undoList.insert(new (internalAllocator()) UndoEndTag(popSaveElement())); } discardKeptMessages(); undo(undoList); 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::findMissingTag(const ElementType *e, Vector<const ElementType *> &v){ if (!currentElement().currentPosition()) { if (!e) v.push_back((const ElementType *)0); return; } if (elementIsExcluded(e)) return; size_t newSize = 0; currentElement().matchState().possibleTransitions(v); // FIXME also get currentInclusions for (size_t i = 0; i < v.size(); i++) { if (v[i] && !elementIsExcluded(v[i])) { Boolean success = 0; switch (v[i]->definition()->declaredContent()) { case ElementDefinition::modelGroup: { const CompiledModelGroup *grp = v[i]->definition()->compiledModelGroup(); MatchState state(grp); if (!e) { if (state.tryTransitionPcdata()) success = 1; } else { if (state.tryTransition(e)) success = 1; if (!success) { for (size_t j = 0; j < v[i]->definition()->nInclusions(); j++) if (v[i]->definition()->inclusion(j) == e) { success = 1; break; } } if (success) { for (size_t j = 0; j < v[i]->definition()->nExclusions(); j++) if (v[i]->definition()->exclusion(j) == e) { success = 0; break; } } } } break;#if 0 case ElementDefinition::any: success = 1; break;#endif case ElementDefinition::cdata: case ElementDefinition::rcdata: if (e == 0) success = 1; break; default: break; } if (success) v[newSize++] = v[i]; } } v.resize(newSize); // Sort them according to the order of their occurrence in the DTD. // Do an insertion sort. for (size_t i = 1; i < v.size(); i++) { const ElementType *tem = v[i]; size_t j; for (j = i; j > 0 && v[j - 1]->index() > tem->index(); j--) v[j] = v[j - 1]; v[j] = tem; }}#if 0// This produces messages that are too verbose// This doesn't try to be very efficient.// 0 for #pcdatavoid Parser::getAllowedElementTypes(Vector<const ElementType *> &v){ v.clear(); // FIXME get a list of all inclusions first // getCurrentInclusions(v); // x says whether each element of v was excluded Vector<PackedBoolean> x(v.size(), 0); unsigned startImpliedCount = 0; IList<Undo> undoList; for (;;) { if (currentElement().currentPosition()) { // have a model group size_t i = v.size(); currentElement().matchState().possibleTransitions(v); x.resize(v.size()); for (size_t j = i; j < v.size(); j++) x[j] = (v[j] && elementIsExcluded(v[j])); if (!sd().omittag()) break; // Try to imply a tag if (currentElement().isFinished()) { if (tagLevel() == 0) break; if (startImpliedCount) break; const ElementDefinition *def = currentElement().type()->definition(); if (def && def->canOmitEndTag()) undoList.insert(new (internalAllocator()) UndoEndTag(popSaveElement())); else break; } else { const LeafContentToken *token = currentElement().impliedStartTag(); if (!token) break; const ElementType *e = token->elementType(); if (elementIsExcluded(e)) break; const ElementDefinition *def = e->definition(); if (!def || def->undefined() || (def->declaredContent() != ElementDefinition::modelGroup && def->declaredContent() != ElementDefinition::any) || !def->canOmitStartTag()) break; undoList.insert(new (internalAllocator()) UndoStartTag); startImpliedCount++; pushElement(new (internalAllocator()) OpenElement(e, 0, 0, 0, Location())); if (checkImplyLoop(startImpliedCount)) break; for (size_t i = 0; i < def->nInclusions(); i++) if (!elementIsExcluded(def->inclusion(i))) { v.push_back(def->inclusion(i)); x.push_back(0); } } } else { // must be allowed #pcdata v.push_back((const ElementType *)0); x.push_back((PackedBoolean)0); break; } } undo(undoList); // Remove exclusions and duplicates and undefined size_t newSize = 0; for (size_t i = 0; i < v.size(); i++) if (!x[i] && (!v[i] || !v[i]->definition()->undefined())) { Boolean dup = 0; for (size_t j = 0; j < newSize; j++) if (v[i] == v[j]) { dup = 1; break; } if (!dup) v[newSize++] = v[i]; } v.resize(newSize);}#endif#ifdef SP_NAMESPACE}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -