📄 parseinstance.cxx
字号:
// Copyright (c) 1994 James Clark// See the file COPYING for copying permission.#include "splib.h"#include "Parser.h"#include "ParserMessages.h"#include "MessageArg.h"#include "TokenMessageArg.h"#include "StringVectorMessageArg.h"#include "token.h"#include "macros.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifvoid Parser::doInstanceStart(){ if (cancelled()) { allDone(); return; } // FIXME check here that we have a valid dtd compileInstanceModes(); setPhase(contentPhase); Token token = getToken(currentMode()); switch (token) { case tokenEe: case tokenStagoNameStart: case tokenStagoTagc: case tokenStagoGrpo: case tokenEtagoNameStart: case tokenEtagoTagc: case tokenEtagoGrpo: break; default: if (sd().omittag()) { unsigned startImpliedCount = 0; unsigned attributeListIndex = 0; IList<Undo> undoList; IList<Event> eventList; if (!tryImplyTag(currentLocation(), startImpliedCount, attributeListIndex, undoList, eventList)) CANNOT_HAPPEN(); queueElementEvents(eventList); } else message(ParserMessages::instanceStartOmittag); } currentInput()->ungetToken();}void Parser::endInstance(){ // Do checking before popping entity stack so that there's a // current location for error messages. endAllElements(); while (markedSectionLevel() > 0) { message(ParserMessages::unclosedMarkedSection, currentMarkedSectionStartLocation()); endMarkedSection(); } checkIdrefs(); popInputStack(); allDone();}void Parser::checkIdrefs(){ IdTableIter iter(idTableIter()); Id *id; while ((id = iter.next()) != 0) { for (size_t i = 0; i < id->pendingRefs().size(); i++) { Messenger::setNextLocation(id->pendingRefs()[i]); message(ParserMessages::missingId, StringMessageArg(id->name())); } }}void Parser::doContent(){ do { if (cancelled()) { allDone(); return; } Token token = getToken(currentMode()); switch (token) { case tokenEe: if (inputLevel() == 1) { endInstance(); return; } if (inputLevel() == specialParseInputLevel()) { // FIXME have separate messages for each type of special parse // perhaps force end of marked section or element message(ParserMessages::specialParseEntityEnd); } if (eventsWanted().wantInstanceMarkup()) eventHandler().entityEnd(new (eventAllocator()) EntityEndEvent(currentLocation())); if (afterDocumentElement()) message(ParserMessages::afterDocumentElementEntityEnd); if (sd().integrallyStored() && tagLevel() && currentElement().index() != currentInputElementIndex()) message(ParserMessages::contentAsyncEntityRef); popInputStack(); break; case tokenCroDigit: case tokenHcroHexDigit: { if (afterDocumentElement()) message(ParserMessages::characterReferenceAfterDocumentElement); Char ch; Location loc; if (parseNumericCharRef(token == tokenHcroHexDigit, ch, loc)) { acceptPcdata(loc); noteData(); Boolean isSgmlChar; if (!translateNumericCharRef(ch, isSgmlChar)) break; if (!isSgmlChar) { eventHandler().nonSgmlChar(new (eventAllocator()) NonSgmlCharEvent(ch, loc)); break; } eventHandler().data(new (eventAllocator()) ImmediateDataEvent(Event::characterData, &ch, 1, loc, 1)); break; } } break; case tokenCroNameStart: if (afterDocumentElement()) message(ParserMessages::characterReferenceAfterDocumentElement); parseNamedCharRef(); break; case tokenEroGrpo: case tokenEroNameStart: { if (afterDocumentElement()) message(ParserMessages::entityReferenceAfterDocumentElement); ConstPtr<Entity> entity; Ptr<EntityOrigin> origin; if (parseEntityReference(0, token == tokenEroGrpo, entity, origin)) { if (!entity.isNull()) { if (entity->isCharacterData()) acceptPcdata(Location(origin.pointer(), 0)); if (inputLevel() == specialParseInputLevel()) entity->rcdataReference(*this, origin); else entity->contentReference(*this, origin); } } } break; case tokenEtagoNameStart: acceptEndTag(parseEndTag()); break; case tokenEtagoTagc: parseEmptyEndTag(); break; case tokenEtagoGrpo: parseGroupEndTag(); break; case tokenMdoNameStart: if (startMarkup(eventsWanted().wantInstanceMarkup(), currentLocation())) currentMarkup()->addDelim(Syntax::dMDO); Syntax::ReservedName name; Boolean result; unsigned startLevel; startLevel = inputLevel(); if (parseDeclarationName(&name)) { switch (name) { case Syntax::rUSEMAP: if (afterDocumentElement()) message(ParserMessages::declarationAfterDocumentElement, StringMessageArg(syntax().reservedName(name))); result = parseUsemapDecl(); break; case Syntax::rUSELINK: if (afterDocumentElement()) message(ParserMessages::declarationAfterDocumentElement, StringMessageArg(syntax().reservedName(name))); result = parseUselinkDecl(); break; case Syntax::rDOCTYPE: case Syntax::rLINKTYPE: case Syntax::rELEMENT: case Syntax::rATTLIST: case Syntax::rENTITY: case Syntax::rNOTATION: case Syntax::rSHORTREF: case Syntax::rLINK: case Syntax::rIDLINK: message(ParserMessages::instanceDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; break; default: message(ParserMessages::noSuchDeclarationType, StringMessageArg(syntax().reservedName(name))); result = 0; break; } } else result = 0; if (!result) skipDeclaration(startLevel); noteMarkup(); break; case tokenMdoMdc: // empty comment emptyCommentDecl(); noteMarkup(); break; case tokenMdoCom: parseCommentDecl(); noteMarkup(); break; case tokenMdoDso: if (afterDocumentElement()) message(ParserMessages::markedSectionAfterDocumentElement); parseMarkedSectionDeclStart(); noteMarkup(); break; case tokenMscMdc: handleMarkedSectionEnd(); noteMarkup(); break; case tokenNet: parseNullEndTag(); break; case tokenPio: parseProcessingInstruction(); break; case tokenStagoNameStart: parseStartTag(); break; case tokenStagoTagc: parseEmptyStartTag(); break; case tokenStagoGrpo: parseGroupStartTag(); break; case tokenRe: acceptPcdata(currentLocation()); queueRe(currentLocation()); break; case tokenRs: acceptPcdata(currentLocation()); noteRs(); if (eventsWanted().wantInstanceMarkup()) eventHandler().ignoredRs(new (eventAllocator()) IgnoredRsEvent(currentChar(), currentLocation())); break; case tokenS: extendContentS(); if (eventsWanted().wantInstanceMarkup()) eventHandler().sSep(new (eventAllocator()) SSepEvent(currentInput()->currentTokenStart(), currentInput()->currentTokenLength(), currentLocation(), 0)); break; case tokenIgnoredChar: extendData(); if (eventsWanted().wantMarkedSections()) eventHandler().ignoredChars(new (eventAllocator()) IgnoredCharsEvent(currentInput()->currentTokenStart(), currentInput()->currentTokenLength(), currentLocation(), 0)); break; case tokenUnrecognized: reportNonSgmlCharacter(); parsePcdata(); break; case tokenCharDelim: message(ParserMessages::dataCharDelim, StringMessageArg(StringC(currentInput()->currentTokenStart(), currentInput()->currentTokenLength()))); // fall through case tokenChar: parsePcdata(); break; default: ASSERT(token >= tokenFirstShortref); handleShortref(token - tokenFirstShortref); break; } } while (eventQueueEmpty());}void Parser::skipDeclaration(unsigned startLevel){ const unsigned skipMax = 250; unsigned skipCount = 0; for (;;) { Token token = getToken(mdMode); if (inputLevel() == startLevel) skipCount++; switch (token) { case tokenUnrecognized: (void)getChar(); break; case tokenEe: if (inputLevel() <= startLevel) return; popInputStack(); return; case tokenMdc: if (inputLevel() == startLevel) return; break; case tokenS: if (inputLevel() == startLevel && skipCount >= skipMax && currentChar() == syntax().standardFunction(Syntax::fRE)) return; break; default: break; } }}void Parser::handleShortref(int index){ const ConstPtr<Entity> &entity = currentElement().map()->entity(index); if (!entity.isNull()) { Owner<Markup> markupPtr; if (eventsWanted().wantInstanceMarkup()) { markupPtr = new Markup; markupPtr->addShortref(currentInput()); } Ptr<EntityOrigin> origin = EntityOrigin::make(internalAllocator(), entity, currentLocation(), currentInput()->currentTokenLength(), markupPtr); entity->contentReference(*this, origin); return; } InputSource *in = currentInput(); size_t length = in->currentTokenLength(); const Char *s = in->currentTokenStart(); size_t i = 0; if (currentMode() == econMode || currentMode() == econnetMode) { // FIXME do this in advance (what about B sequence?) for (i = 0; i < length && syntax().isS(s[i]); i++) ; if (i > 0 && eventsWanted().wantInstanceMarkup()) eventHandler().sSep(new (eventAllocator()) SSepEvent(s, i, currentLocation(), 0)); } if (i < length) { Location location(currentLocation()); location += i; s += i; length -= i; acceptPcdata(location); if (sd().keeprsre()) { noteData(); eventHandler().data(new (eventAllocator()) ImmediateDataEvent(Event::characterData, s, length, location, 0)); return; } // FIXME speed this up for (; length > 0; location += 1, length--, s++) { if (*s == syntax().standardFunction(Syntax::fRS)) { noteRs(); if (eventsWanted().wantInstanceMarkup()) eventHandler().ignoredRs(new (eventAllocator()) IgnoredRsEvent(*s, location)); } else if (*s == syntax().standardFunction(Syntax::fRE)) queueRe(location); else { noteData(); eventHandler().data(new (eventAllocator()) ImmediateDataEvent(Event::characterData, s, 1, location, 0)); } } }}void Parser::parsePcdata(){ extendData(); acceptPcdata(currentLocation()); noteData(); eventHandler().data(new (eventAllocator()) ImmediateDataEvent(Event::characterData, currentInput()->currentTokenStart(), currentInput()->currentTokenLength(), currentLocation(), 0));}void Parser::parseStartTag(){ InputSource *in = currentInput(); Markup *markup = startMarkup(eventsWanted().wantInstanceMarkup(), in->currentLocation()); in->discardInitial(); extendNameToken(syntax().namelen(), ParserMessages::nameLength); if (markup) { markup->addDelim(Syntax::dSTAGO); markup->addName(in); } StringC &name = nameBuffer(); getCurrentToken(syntax().generalSubstTable(), name); ElementType *e = currentDtdNonConst().lookupElementType(name); if (sd().rank()) { if (!e) e = completeRankStem(name); else if (e->isRankedElement()) handleRankedElement(e); } if (!e) e = lookupCreateUndefinedElement(name, currentLocation(), currentDtdNonConst()); Boolean netEnabling; AttributeList *attributes = allocAttributeList(e->attributeDef(), 0); Token closeToken = getToken(tagMode); if (closeToken == tokenTagc) { if (name.size() > syntax().taglen()) checkTaglen(markupLocation().index()); attributes->finish(*this); netEnabling = 0; if (markup) markup->addDelim(Syntax::dTAGC); } else { in->ungetToken(); Ptr<AttributeDefinitionList> newAttDef; if (parseAttributeSpec(0, *attributes, netEnabling, newAttDef)) { // The difference between the indices will be the difference // in offsets plus 1 for each named character reference. if (in->currentLocation().index() - markupLocation().index() > syntax().taglen()) checkTaglen(markupLocation().index()); } else netEnabling = 0; if (!newAttDef.isNull()) { newAttDef->setIndex(currentDtdNonConst().allocAttributeDefinitionListIndex()); e->setAttributeDef(newAttDef); } } acceptStartTag(e, new (eventAllocator()) StartElementEvent(e, currentDtdPointer(), attributes, markupLocation(), markup), netEnabling);}ElementType *Parser::completeRankStem(const StringC &name){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -