📄 parseparam.cxx
字号:
// Copyright (c) 1994 James Clark// See the file COPYING for copying permission.#include "splib.h"#include "Parser.h"#include "Param.h"#include "Group.h"#include "Markup.h"#include "ParserMessages.h"#include "MessageArg.h"#include "TokenMessageArg.h"#include "token.h"#include "macros.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifBoolean Parser::parseParam(const AllowedParams &allow, unsigned declInputLevel, Param &parm){ for (;;) { Token token = getToken(allow.mainMode()); switch (token) { case tokenUnrecognized: if (reportNonSgmlCharacter()) break; { message(ParserMessages::markupDeclarationCharacter, StringMessageArg(currentToken()), AllowedParamsMessageArg(allow, syntaxPointer())); } return 0; case tokenEe: if (inputLevel() <= declInputLevel) { message(ParserMessages::declarationLevel); return 0; } if (currentMarkup()) currentMarkup()->addEntityEnd(); popInputStack(); break; case tokenCom: if (!parseComment(comMode)) return 0; if (options().warnPsComment) message(ParserMessages::psComment); break; case tokenDso: if (!allow.dso()) { paramInvalidToken(tokenDso, allow); return 0; } if (currentMarkup()) currentMarkup()->addDelim(Syntax::dDSO); parm.type = Param::dso; return 1; case tokenGrpo: if (currentMarkup()) currentMarkup()->addDelim(Syntax::dGRPO); switch (allow.group()) { case Param::invalid: paramInvalidToken(tokenGrpo, allow); return 0; case Param::modelGroup: { ModelGroup *group; if (!parseModelGroup(1, declInputLevel, group, grpsufMode)) return 0; parm.type = Param::modelGroup; parm.modelGroupPtr = group; } break; case Param::nameGroup: if (!parseNameGroup(declInputLevel, parm)) return 0; break; case Param::nameTokenGroup: if (!parseNameTokenGroup(declInputLevel, parm)) return 0; break; default: CANNOT_HAPPEN(); } parm.type = allow.group(); return 1; case tokenLita: case tokenLit: parm.type = allow.literal(); parm.lita = token == tokenLita; switch (allow.literal()) { case Param::invalid: paramInvalidToken(token, allow); return 0; case Param::minimumLiteral: if (!parseMinimumLiteral(parm.lita, parm.literalText)) return 0; break; case Param::attributeValueLiteral: if (!parseAttributeValueLiteral(parm.lita, parm.literalText)) return 0; break; case Param::tokenizedAttributeValueLiteral: if (!parseTokenizedAttributeValueLiteral(parm.lita, parm.literalText)) return 0; break; case Param::systemIdentifier: if (!parseSystemIdentifier(parm.lita, parm.literalText)) return 0; break; case Param::paramLiteral: if (!parseParameterLiteral(parm.lita, parm.literalText)) return 0; break; } if (currentMarkup()) currentMarkup()->addLiteral(parm.literalText); return 1; case tokenMdc: if (!allow.mdc()) { paramInvalidToken(tokenMdc, allow); return 0; } if (inputLevel() > declInputLevel) message(ParserMessages::parameterEntityNotEnded); if (currentMarkup()) currentMarkup()->addDelim(Syntax::dMDC); parm.type = Param::mdc; return 1; case tokenMinus: parm.type = Param::minus; if (currentMarkup()) currentMarkup()->addDelim(Syntax::dMINUS); return 1; case tokenMinusGrpo: if (!allow.exclusions()) { paramInvalidToken(tokenMinusGrpo, allow); return 0; } if (currentMarkup()) { currentMarkup()->addDelim(Syntax::dMINUS); currentMarkup()->addDelim(Syntax::dGRPO); } parm.type = Param::exclusions; return parseElementNameGroup(declInputLevel, parm); case tokenPero: parm.type = Param::pero; if (currentMarkup()) currentMarkup()->addDelim(Syntax::dPERO); return 1; case tokenPeroGrpo: if (!inInstance()) message(ParserMessages::peroGrpoProlog); // fall through case tokenPeroNameStart: { if (inInstance()) { if (options().warnInstanceParamEntityRef) message(ParserMessages::instanceParamEntityRef); } else { if (options().warnInternalSubsetPsParamEntityRef && inputLevel() == 1) message(ParserMessages::internalSubsetPsParamEntityRef); } ConstPtr<Entity> entity; Ptr<EntityOrigin> origin; if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) return 0; if (!entity.isNull()) entity->declReference(*this, origin); } break; case tokenPlusGrpo: if (!allow.inclusions()) { paramInvalidToken(tokenPlusGrpo, allow); return 0; } if (currentMarkup()) { currentMarkup()->addDelim(Syntax::dPLUS); currentMarkup()->addDelim(Syntax::dGRPO); } parm.type = Param::inclusions; return parseElementNameGroup(declInputLevel, parm); case tokenRni: if (!allow.rni()) { paramInvalidToken(tokenRni, allow); return 0; } return parseIndicatedReservedName(allow, parm); case tokenS: if (currentMarkup()) currentMarkup()->addS(currentChar()); break; case tokenNameStart: switch (allow.nameStart()) { case Param::invalid: paramInvalidToken(tokenNameStart, allow); return 0; case Param::reservedName: return parseReservedName(allow, parm); case Param::name: extendNameToken(syntax().namelen(), ParserMessages::nameLength); parm.type = Param::name; getCurrentToken(syntax().generalSubstTable(), parm.token); if (currentMarkup()) currentMarkup()->addName(currentInput()); return 1; case Param::entityName: extendNameToken(syntax().namelen(), ParserMessages::nameLength); parm.type = Param::entityName; getCurrentToken(syntax().entitySubstTable(), parm.token); if (currentMarkup()) currentMarkup()->addName(currentInput()); return 1; case Param::paramEntityName: extendNameToken(syntax().penamelen(), ParserMessages::parameterEntityNameLength); parm.type = Param::paramEntityName; getCurrentToken(syntax().entitySubstTable(), parm.token); if (currentMarkup()) currentMarkup()->addName(currentInput()); return 1; case Param::attributeValue: return parseAttributeValueParam(parm); } break; case tokenDigit: switch (allow.digit()) { case Param::invalid: paramInvalidToken(tokenDigit, allow); return 0; case Param::number: extendNumber(syntax().namelen(), ParserMessages::numberLength); parm.type = Param::number; getCurrentToken(parm.token); if (currentMarkup()) currentMarkup()->addNumber(currentInput()); return 1; case Param::attributeValue: return parseAttributeValueParam(parm); } break; case tokenLcUcNmchar: switch (allow.nmchar()) { case Param::invalid: paramInvalidToken(tokenLcUcNmchar, allow); return 0; case Param::attributeValue: return parseAttributeValueParam(parm); } break; default: CANNOT_HAPPEN(); } }}void Parser::paramInvalidToken(Token token, const AllowedParams &allow){ message(ParserMessages::paramInvalidToken, TokenMessageArg(token, allow.mainMode(), syntaxPointer(), sdPointer()), AllowedParamsMessageArg(allow, syntaxPointer()));}Boolean Parser::parseGroupToken(const AllowedGroupTokens &allow, unsigned nestingLevel, unsigned declInputLevel, unsigned groupInputLevel, GroupToken >){ for (;;) { Token token = getToken(grpMode); switch (token) { case tokenEe: if (inputLevel() <= groupInputLevel) { message(ParserMessages::groupLevel); if (inputLevel() <= declInputLevel) return 0; } else if (!sd().www()) message(ParserMessages::groupEntityEnd); if (currentMarkup()) currentMarkup()->addEntityEnd(); popInputStack(); break; case tokenPeroGrpo: if (!inInstance()) message(ParserMessages::peroGrpoProlog); // fall through case tokenPeroNameStart: { if (options().warnInternalSubsetTsParamEntityRef && inputLevel() == 1) message(ParserMessages::internalSubsetTsParamEntityRef); ConstPtr<Entity> entity; Ptr<EntityOrigin> origin; if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) return 0; if (!entity.isNull()) entity->declReference(*this, origin); } break; case tokenUnrecognized: if (reportNonSgmlCharacter()) break; { message(ParserMessages::groupCharacter, StringMessageArg(currentToken()), AllowedGroupTokensMessageArg(allow, syntaxPointer())); } return 0; case tokenDtgo: if (!allow.groupToken(GroupToken::dataTagGroup)) { groupTokenInvalidToken(tokenDtgo, allow); return 0; } if (sd().datatag()) message(ParserMessages::datatagNotImplemented); if (currentMarkup()) currentMarkup()->addDelim(Syntax::dDTGO); return parseDataTagGroup(nestingLevel + 1, declInputLevel, gt); case tokenGrpo: if (currentMarkup()) currentMarkup()->addDelim(Syntax::dGRPO); switch (allow.group()) { case GroupToken::modelGroup: { ModelGroup *modelGroup; if (!parseModelGroup(nestingLevel + 1, declInputLevel, modelGroup, grpMode)) return 0; gt.model = modelGroup; gt.type = GroupToken::modelGroup; return 1; } case GroupToken::dataTagTemplateGroup: return parseDataTagTemplateGroup(nestingLevel + 1, declInputLevel, gt); default: groupTokenInvalidToken(tokenGrpo, allow); return 0; } break; case tokenRni: if (!allow.groupToken(GroupToken::pcdata)) { groupTokenInvalidToken(tokenRni, allow); return 0; } Syntax::ReservedName rn; if (!getIndicatedReservedName(&rn)) return 0; if (rn != Syntax::rPCDATA) { StringC token(syntax().delimGeneral(Syntax::dRNI)); token += syntax().reservedName(Syntax::rPCDATA); message(ParserMessages::invalidToken, StringMessageArg(token)); return 0; } gt.type = GroupToken::pcdata; gt.contentToken = new PcdataToken; return 1; case tokenS: if (currentMarkup()) { extendS(); currentMarkup()->addS(currentInput()); } break; case tokenNameStart: switch (allow.nameStart()) { case GroupToken::elementToken: { extendNameToken(syntax().namelen(), ParserMessages::nameLength); gt.type = GroupToken::elementToken; StringC &buffer = nameBuffer(); getCurrentToken(syntax().generalSubstTable(), buffer); if (currentMarkup()) currentMarkup()->addName(currentInput()); const ElementType *e = lookupCreateElement(buffer); ContentToken::OccurrenceIndicator oi = getOccurrenceIndicator(grpMode); gt.contentToken = new ElementToken(e, oi); return 1; } case GroupToken::name: case GroupToken::nameToken: extendNameToken(syntax().namelen(), token == GroupToken::name ? ParserMessages::nameLength : ParserMessages::nameTokenLength); getCurrentToken(syntax().generalSubstTable(), gt.token); gt.type = allow.nameStart(); if (currentMarkup()) { if (gt.type == GroupToken::nameToken) currentMarkup()->addNameToken(currentInput()); else currentMarkup()->addName(currentInput()); } return 1; default: groupTokenInvalidToken(tokenNameStart, allow); return 0; } case tokenDigit: case tokenLcUcNmchar: if (!allow.groupToken(GroupToken::nameToken)) { groupTokenInvalidToken(token, allow); return 0; } extendNameToken(syntax().namelen(), ParserMessages::nameTokenLength); getCurrentToken(syntax().generalSubstTable(), gt.token); gt.type = GroupToken::nameToken; if (currentMarkup()) currentMarkup()->addNameToken(currentInput()); return 1; case tokenLit: case tokenLita: // parameter literal in data tag pattern if (!allow.groupToken(GroupToken::dataTagLiteral)) { groupTokenInvalidToken(token, allow); return 0; } if (!parseDataTagParameterLiteral(token == tokenLita, gt.text)) return 0; gt.type = GroupToken::dataTagLiteral; if (currentMarkup()) currentMarkup()->addLiteral(gt.text); return 1; case tokenAnd: case tokenSeq: case tokenOr: case tokenDtgc: case tokenGrpc: case tokenOpt: case tokenPlus: case tokenRep: groupTokenInvalidToken(token, allow); return 0; } }}void Parser::groupTokenInvalidToken(Token token, const AllowedGroupTokens &allow){ message(ParserMessages::groupTokenInvalidToken, TokenMessageArg(token, grpMode, syntaxPointer(), sdPointer()), AllowedGroupTokensMessageArg(allow, syntaxPointer()));}Boolean Parser::parseGroupConnector(const AllowedGroupConnectors &allow, unsigned declInputLevel, unsigned groupInputLevel, GroupConnector &gc){ for (;;) { Token token = getToken(grpMode); switch (token) { case tokenEe: if (inputLevel() <= groupInputLevel) { message(ParserMessages::groupLevel); if (inputLevel() <= declInputLevel) return 0; } if (currentMarkup()) currentMarkup()->addEntityEnd(); popInputStack(); break; case tokenS: if (currentMarkup()) { extendS(); currentMarkup()->addS(currentInput()); } break; case tokenPeroGrpo: if (inInstance()) { message(ParserMessages::peroGrpoProlog); break; } // fall through case tokenPeroNameStart: if (!sd().www()) message(ParserMessages::groupEntityReference); else { ConstPtr<Entity> entity; Ptr<EntityOrigin> origin; if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin)) return 0; if (!entity.isNull()) entity->declReference(*this, origin); } break; case tokenUnrecognized: if (reportNonSgmlCharacter()) break; { message(ParserMessages::groupCharacter, StringMessageArg(currentToken()), AllowedGroupConnectorsMessageArg(allow, syntaxPointer())); } return 0; case tokenAnd: if (!allow.groupConnector(GroupConnector::andGC)) { groupConnectorInvalidToken(tokenAnd, allow); return 0; } gc.type = GroupConnector::andGC; if (currentMarkup()) currentMarkup()->addDelim(Syntax::dAND); return 1; case tokenSeq: if (!allow.groupConnector(GroupConnector::seqGC)) { groupConnectorInvalidToken(tokenSeq, allow);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -