📄 parsedecl.cxx
字号:
// Copyright (c) 1994, 1995 James Clark// See the file COPYING for copying permission.// Prolog, dtd and declaration parsing.#include "splib.h"#include "Parser.h"#include "Param.h"#include "Markup.h"#include "ParserMessages.h"#include "MessageArg.h"#include "TokenMessageArg.h"#include "token.h"#include "macros.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifstatic const AllowedParams allowMdc(Param::mdc);static const AllowedParams allowName(Param::name);static const AllowedParams allowParamLiteral(Param::paramLiteral);static const AllowedParams allowNameNameGroup(Param::name, Param::nameGroup);static const AllowedParams allowDsoMdc(Param::dso, Param::mdc);static AllowedParams allowNameMdc(Param::name, Param::mdc);static AllowedParams allowExplicitLinkRuleMdc(Param::mdc, Param::name, Param::nameGroup, Param::indicatedReservedName + Syntax::rIMPLIED);static AllowedParams allowNameNameGroupMdc(Param::name, Param::nameGroup, Param::mdc);static const AllowedParams allowLinkSetSpec(Param::name, Param::indicatedReservedName + Syntax::rINITIAL, Param::indicatedReservedName + Syntax::rEMPTY, Param::indicatedReservedName + Syntax::rRESTORE);void Parser::doProlog(){ const unsigned maxTries = 10; unsigned tries = 0; do { if (cancelled()) { allDone(); return; } Token token = getToken(proMode); switch (token) { case tokenUnrecognized: if (reportNonSgmlCharacter()) break; if (hadDtd()) { currentInput()->ungetToken(); endProlog(); return; } { StringC gi; if (lookingAtStartTag(gi)) { currentInput()->ungetToken(); implyDtd(gi); return; } } if (++tries >= maxTries) { message(ParserMessages::notSgml); giveUp(); return; } message(ParserMessages::prologCharacter, StringMessageArg(currentToken())); prologRecover(); break; case tokenEe: if (hadDtd()) { endProlog(); return; } message(ParserMessages::documentEndProlog); allDone(); return; case tokenMdoMdc: // empty comment emptyCommentDecl(); break; case tokenMdoCom: if (!parseCommentDecl()) prologRecover(); break; case tokenMdoNameStart: setPass2Start(); if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation())) currentMarkup()->addDelim(Syntax::dMDO); Syntax::ReservedName name; if (parseDeclarationName(&name)) { switch (name) { case Syntax::rDOCTYPE: if (!parseDoctypeDeclStart()) giveUp(); return; case Syntax::rLINKTYPE: if (!parseLinktypeDeclStart()) giveUp(); return; case Syntax::rELEMENT: case Syntax::rATTLIST: case Syntax::rENTITY: case Syntax::rNOTATION: case Syntax::rSHORTREF: case Syntax::rUSEMAP: case Syntax::rUSELINK: case Syntax::rLINK: case Syntax::rIDLINK: message(ParserMessages::prologDeclaration, StringMessageArg(syntax().reservedName(name))); if (!hadDtd()) tries++; prologRecover(); break; default: message(ParserMessages::noSuchDeclarationType, StringMessageArg(syntax().reservedName(name))); prologRecover(); break; } } else prologRecover(); break; case tokenPio: if (!parseProcessingInstruction()) prologRecover(); break; case tokenS: if (eventsWanted().wantPrologMarkup()) { extendS(); eventHandler().sSep(new (eventAllocator()) SSepEvent(currentInput()->currentTokenStart(), currentInput()->currentTokenLength(), currentLocation(), 1)); } break; default: CANNOT_HAPPEN(); } } while (eventQueueEmpty());}void Parser::endProlog(){ if (baseDtd().isNull()#if 0 || baseDtd()->documentElementType()->definition()->undefined()#endif ) { // We could continue, but there's not a lot of point. giveUp(); return; } if (maybeStartPass2()) setPhase(prologPhase); else { if (inputLevel() == 0) { allDone(); return; } if (pass2()) checkEntityStability(); setPhase(instanceStartPhase); startInstance(); ConstPtr<ComplexLpd> lpd; Vector<AttributeList> simpleLinkAtts; Vector<StringC> simpleLinkNames; for (size_t i = 0; i < nActiveLink(); i++) if (activeLpd(i).type() == Lpd::simpleLink) { const SimpleLpd &lpd = (SimpleLpd &)activeLpd(i); simpleLinkNames.push_back(lpd.name()); simpleLinkAtts.resize(simpleLinkAtts.size() + 1); simpleLinkAtts.back().init(lpd.attributeDef()); simpleLinkAtts.back().finish(*this); } else lpd = (ComplexLpd *)&activeLpd(i); eventHandler().endProlog(new (eventAllocator()) EndPrologEvent(baseDtd(), lpd, simpleLinkNames, simpleLinkAtts, currentLocation())); }}void Parser::prologRecover(){ unsigned skipCount = 0; const unsigned skipMax = 250; for (;;) { Token token = getToken(proMode); skipCount++; if (token == tokenUnrecognized) { token = getToken(mdMode); if (token == tokenMdc) { token = getToken(proMode); if (token == tokenS) return; } } switch (token) { case tokenUnrecognized: (void)getChar(); break; case tokenEe: return; case tokenMdoMdc: case tokenMdoCom: case tokenMdoNameStart: case tokenPio: currentInput()->ungetToken(); return; case tokenS: if (currentChar() == syntax().standardFunction(Syntax::fRE) && skipCount >= skipMax) return; default: break; } }}void Parser::doDeclSubset(){ do { if (cancelled()) { allDone(); return; } Token token = getToken(currentMode()); unsigned startLevel = inputLevel(); Boolean inDtd = !haveDefLpd(); switch (token) { case tokenUnrecognized: if (reportNonSgmlCharacter()) break; message(ParserMessages::declSubsetCharacter, StringMessageArg(currentToken())); declSubsetRecover(startLevel); break; case tokenEe: if (inputLevel() == specialParseInputLevel()) { // FIXME have separate messages for each type of special parse message(ParserMessages::specialParseEntityEnd); } if (eventsWanted().wantPrologMarkup()) eventHandler().entityEnd(new (eventAllocator()) EntityEndEvent(currentLocation())); if (inputLevel() == 2) { const EntityDecl *e = currentLocation().origin()->entityDecl(); if (e && (e->declType() == EntityDecl::doctype || e->declType() == EntityDecl::linktype)) { // popInputStack may destroy e Boolean fake = e->defLocation().origin().isNull(); popInputStack(); if (!(inDtd ? parseDoctypeDeclEnd(fake) : parseLinktypeDeclEnd())) ; // FIXME recover setPhase(prologPhase); return; } } if (inputLevel() == 1) { if (finalPhase() == declSubsetPhase) { checkDtd(defDtd()); endDtd(); } else // Give message before popping stack. message(inDtd ? ParserMessages::documentEndDtdSubset : ParserMessages::documentEndLpdSubset); popInputStack(); allDone(); } else popInputStack(); return; case tokenDsc: // end of declaration subset // FIXME what's the right location? if (!referenceDsEntity(currentLocation())) { if (!(inDtd ? parseDoctypeDeclEnd() : parseLinktypeDeclEnd())) ; // FIXME recover setPhase(prologPhase); } return; case tokenMdoNameStart: // named markup declaration if (startMarkup(eventsWanted().wantPrologMarkup(), currentLocation())) currentMarkup()->addDelim(Syntax::dMDO); Syntax::ReservedName name; Boolean result; if (parseDeclarationName(&name, inDtd && !options().errorAfdr)) { switch (name) { case Syntax::rANY: // used for <!AFDR result = parseAfdrDecl(); break; case Syntax::rELEMENT: if (inDtd) result = parseElementDecl(); else { message(ParserMessages::lpdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; } break; case Syntax::rATTLIST: result = parseAttlistDecl(); break; case Syntax::rENTITY: result = parseEntityDecl(); break; case Syntax::rNOTATION: result = parseNotationDecl(); if (!inDtd && !sd().www()) message(ParserMessages::lpdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); break; case Syntax::rSHORTREF: if (inDtd) result = parseShortrefDecl(); else { message(ParserMessages::lpdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; } break; case Syntax::rUSEMAP: if (inDtd) result = parseUsemapDecl(); else { message(ParserMessages::lpdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; } break; case Syntax::rLINK: if (inDtd) { message(ParserMessages::dtdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; } else result = parseLinkDecl(); break; case Syntax::rIDLINK: if (inDtd) { message(ParserMessages::dtdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); result = 0; } else result = parseIdlinkDecl(); break; case Syntax::rDOCTYPE: case Syntax::rLINKTYPE: case Syntax::rUSELINK: result = 0; message(inDtd ? ParserMessages::dtdSubsetDeclaration : ParserMessages::lpdSubsetDeclaration, StringMessageArg(syntax().reservedName(name))); break; default: result = 0; message(ParserMessages::noSuchDeclarationType, StringMessageArg(syntax().reservedName(name))); break; } } else result = 0; if (!result) declSubsetRecover(startLevel); break; case tokenMdoMdc: // empty comment declaration // empty comment emptyCommentDecl(); break; case tokenMdoCom: // comment declaration if (!parseCommentDecl()) declSubsetRecover(startLevel); break; case tokenMdoDso: // marked section declaration if (!parseMarkedSectionDeclStart()) declSubsetRecover(startLevel); break; case tokenMscMdc: handleMarkedSectionEnd(); break; case tokenPeroGrpo: // parameter entity reference with name group message(ParserMessages::peroGrpoProlog); // fall through case tokenPeroNameStart: // parameter entity reference { ConstPtr<Entity> entity; Ptr<EntityOrigin> origin; if (parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) { if (!entity.isNull()) entity->dsReference(*this, origin); } else declSubsetRecover(startLevel); } break; case tokenPio: // processing instruction if (!parseProcessingInstruction()) declSubsetRecover(startLevel); break; case tokenS: // white space if (eventsWanted().wantPrologMarkup()) { extendS();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -