📄 attribute.cxx
字号:
// Copyright (c) 1994 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif#include "splib.h"#include "Attribute.h"#include "MessageArg.h"#include "macros.h"#include "ParserMessages.h"#include "StringVectorMessageArg.h"#include "Syntax.h"#include "Entity.h"#include "Notation.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifDeclaredValue::DeclaredValue(){}DeclaredValue::~DeclaredValue(){}AttributeValue *DeclaredValue::makeValueFromToken(Text &text, AttributeContext &context, const StringC &name, unsigned &specLength) const{ return makeValue(text, context, name, specLength);}AttributeSemantics *DeclaredValue::makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &, unsigned &) const{ return 0;}Boolean DeclaredValue::containsToken(const StringC &) const{ return 0;}Boolean DeclaredValue::isNotation() const{ return 0;}Boolean DeclaredValue::isEntity() const{ return 0;}Boolean DeclaredValue::isId() const{ return 0;}Boolean DeclaredValue::isIdref() const{ return 0;}const Vector<StringC> *DeclaredValue::getTokens() const{ return 0;}CdataDeclaredValue::CdataDeclaredValue(){}Boolean CdataDeclaredValue::tokenized() const{ return 0;}AttributeValue *CdataDeclaredValue::makeValue(Text &text, AttributeContext &context, const StringC &, unsigned &specLength) const{ const Syntax &syntax = context.attributeSyntax(); size_t normsep = syntax.normsep(); size_t normalizedLength = text.normalizedLength(normsep); specLength += normalizedLength; size_t litlen = syntax.litlen(); // A length error will already have been given if // length > litlen - normsep. if (litlen >= normsep && text.size() <= litlen - normsep && normalizedLength > litlen) context.message(ParserMessages::normalizedAttributeValueLength, NumberMessageArg(litlen), NumberMessageArg(normalizedLength)); return new CdataAttributeValue(text);}void CdataDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const{ desc.declaredValue = AttributeDefinitionDesc::cdata;}DeclaredValue *CdataDeclaredValue::copy() const{ return new CdataDeclaredValue(*this);}TokenizedDeclaredValue::TokenizedDeclaredValue(TokenType type, Boolean isList): type_(type), isList_(isList){ switch (type) { case name: case entityName: initialCategories_ = Syntax::nameStartCategory; subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory | Syntax::otherNameCategory); break; case number: initialCategories_ = Syntax::digitCategory; subsequentCategories_ = Syntax::digitCategory; break; case nameToken: initialCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory | Syntax::otherNameCategory); subsequentCategories_ = initialCategories_; break; case numberToken: initialCategories_ = Syntax::digitCategory; subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory | Syntax::otherNameCategory); break; }}Boolean TokenizedDeclaredValue::tokenized() const{ return 1;}AttributeValue *TokenizedDeclaredValue::makeValue(Text &text, AttributeContext &context, const StringC &str, unsigned &specLength) const{ return makeTokenizedValue(text, context, str, specLength);}TokenizedAttributeValue *TokenizedDeclaredValue::makeTokenizedValue(Text &text, AttributeContext &context, const StringC &name, unsigned &specLength) const{ Vector<size_t> spaceIndex; const Syntax &syntax = context.attributeSyntax(); Char space = syntax.space(); text.subst(*(type_ == entityName ? syntax.entitySubstTable() : syntax.generalSubstTable()), space); const StringC &value = text.string(); size_t i = 0; size_t length = value.size(); for (;;) { if (i >= length) { // ends with a space (which would have to have been entered // via a numeric character reference) if (context.validate()) context.message(ParserMessages::attributeValueSyntax); break; } size_t startIndex = i; if (context.validate()) { if (!(syntax.charCategory(value[i]) & initialCategories_)) { context.Messenger::setNextLocation(text.charLocation(i)); Char c = value[i]; if (!(syntax.charCategory(value[i]) & subsequentCategories_)) context.message(ParserMessages::attributeValueChar, StringMessageArg(StringC(&c, 1)), StringMessageArg(name)); else if (initialCategories_ == Syntax::digitCategory) context.message(ParserMessages::attributeValueNumberToken, StringMessageArg(StringC(&c, 1)), StringMessageArg(name)); else context.message(ParserMessages::attributeValueName, StringMessageArg(StringC(&c, 1)), StringMessageArg(name)); } else { for (++i; i < length && (syntax.charCategory(value[i]) & subsequentCategories_); i++) ; if (i < length && value[i] != space) { Char c = value[i]; // character value[i] is not allowed anywhere in the value context.Messenger::setNextLocation(text.charLocation(i)); context.message(ParserMessages::attributeValueChar, StringMessageArg(StringC(&c, 1)), StringMessageArg(name)); } } } while (i < length && value[i] != space) i++; if (i - startIndex > syntax.namelen()) { context.Messenger::setNextLocation(text.charLocation(i)); context.message(ParserMessages::nameTokenLength, NumberMessageArg(syntax.namelen())); } if (i == length) break; if (!isList_ && context.validate() && spaceIndex.size() == 0) { context.Messenger::setNextLocation(text.charLocation(i)); context.message(ParserMessages::attributeValueMultiple, StringMessageArg(name)); } spaceIndex.push_back(i); i++; } size_t normsep = syntax.normsep(); size_t litlen = syntax.litlen(); size_t normalizedLength = normsep + length; // should we count CDATA and SDATA entities here? if (isList_) { normalizedLength += 1; // length is now the number of characters in each token in the list // + 1 for each token in the list; so add normsep - 1 for each // token in the list. if (normsep > 0) normalizedLength += (normsep - 1)*(spaceIndex.size() + 1); else normalizedLength -= spaceIndex.size() + 1; } specLength += normalizedLength; // A length error will already have been given if // length > litlen - normsep. if (litlen >= normsep && length <= litlen - normsep && normalizedLength > litlen) context.message(ParserMessages::normalizedAttributeValueLength, NumberMessageArg(litlen), NumberMessageArg(normalizedLength)); return new TokenizedAttributeValue(text, spaceIndex);}Boolean TokenizedAttributeValue::recoverUnquoted(const StringC &str, const Location &strLoc, AttributeContext &context, const StringC &name){ TextIter iter(text_); TextItem::Type type; const Char *s; size_t len; const Location *loc; if (iter.next(type, s, len, loc) && type == TextItem::data && len == text_.size() && loc->origin().pointer() == strLoc.origin().pointer() && loc->index() + len == strLoc.index() && !iter.next(type, s, len, loc)) { context.Messenger::setNextLocation(strLoc); context.message(ParserMessages::attributeValueChar, StringMessageArg(StringC(str.data(), 1)), StringMessageArg(name)); return 1; } return 0;}void TokenizedDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const{ desc.declaredValue = AttributeDefinitionDesc::DeclaredValue( type_ - name + (isList_ ? AttributeDefinitionDesc::names : AttributeDefinitionDesc::name));}DeclaredValue *TokenizedDeclaredValue::copy() const{ return new TokenizedDeclaredValue(*this);}GroupDeclaredValue::GroupDeclaredValue(TokenType type, Vector<StringC> &vec): TokenizedDeclaredValue(type, 0){ vec.swap(allowedValues_);}void GroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const{ desc.allowedValues = allowedValues_;}DeclaredValue *GroupDeclaredValue::copy() const{ return new GroupDeclaredValue(*this);}AttributeValue *GroupDeclaredValue::makeValue(Text &text, AttributeContext &context, const StringC &name, unsigned &specLength) const{ TokenizedAttributeValue *val = makeTokenizedValue(text, context, name, specLength); if (!val || !context.validate()) return val; for (size_t i = 0; i < allowedValues_.size(); i++) if (val->string() == allowedValues_[i]) return val; context.message(ParserMessages::attributeValueNotInGroup, StringMessageArg(val->string()), StringMessageArg(name), StringVectorMessageArg(allowedValues_)); return val;}AttributeValue *GroupDeclaredValue::makeValueFromToken(Text &text, AttributeContext &context, const StringC &, unsigned &specLength) const{ const Syntax &syntax = context.attributeSyntax(); size_t litlen = syntax.litlen(); size_t normsep = syntax.normsep(); if (normsep > litlen || text.size() > litlen - normsep) context.message(ParserMessages::normalizedAttributeValueLength, NumberMessageArg(litlen), NumberMessageArg(text.size() + normsep)); specLength += text.size() + normsep; return new TokenizedAttributeValue(text, Vector<size_t>());}Boolean GroupDeclaredValue::containsToken(const StringC &token) const{ for (size_t i = 0; i < allowedValues_.size(); i++) if (allowedValues_[i] == token) return 1; return 0;}const Vector<StringC> *GroupDeclaredValue::getTokens() const{ return &allowedValues_;}NameTokenGroupDeclaredValue::NameTokenGroupDeclaredValue(Vector<StringC> &vec): GroupDeclaredValue(nameToken, vec){}void NameTokenGroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const{ GroupDeclaredValue::buildDesc(desc); desc.declaredValue = AttributeDefinitionDesc::nameTokenGroup;}DeclaredValue *NameTokenGroupDeclaredValue::copy() const{ return new NameTokenGroupDeclaredValue(*this);}NotationDeclaredValue::NotationDeclaredValue(Vector<StringC> &vec): GroupDeclaredValue(name, vec){}Boolean NotationDeclaredValue::isNotation() const{ return 1;}AttributeSemantics *NotationDeclaredValue::makeSemantics(const TokenizedAttributeValue &value, AttributeContext &context, const StringC &, unsigned &, unsigned &) const{ ConstPtr<Notation> notation = context.getAttributeNotation(value.string(), value.tokenLocation(0)); if (notation.isNull()) { if (context.validate()) { context.setNextLocation(value.tokenLocation(0)); context.message(ParserMessages::invalidNotationAttribute, StringMessageArg(value.string())); } return 0; } return new NotationAttributeSemantics(notation);}void NotationDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const{ GroupDeclaredValue::buildDesc(desc); desc.declaredValue = AttributeDefinitionDesc::notation;}DeclaredValue *NotationDeclaredValue::copy() const{ return new NotationDeclaredValue(*this);}EntityDeclaredValue::EntityDeclaredValue(Boolean isList): TokenizedDeclaredValue(entityName, isList){}Boolean EntityDeclaredValue::isEntity() const{ return 1;}AttributeSemantics *EntityDeclaredValue::makeSemantics(const TokenizedAttributeValue &value, AttributeContext &context, const StringC &, unsigned &, unsigned &nEntityNames) const{ Boolean valid = 1; size_t nTokens = value.nTokens(); nEntityNames += nTokens; Vector<ConstPtr<Entity> > entities(nTokens); for (size_t i = 0; i < nTokens; i++) { entities[i] = context.getAttributeEntity(value.token(i), value.tokenLocation(i)); if (entities[i].isNull()) { if (context.validate()) { context.setNextLocation(value.tokenLocation(i)); context.message(ParserMessages::invalidEntityAttribute, StringMessageArg(value.token(i))); } valid = 0; } else if (!entities[i]->isDataOrSubdoc()) { if (context.validate()) { context.Messenger::setNextLocation(value.tokenLocation(i)); context.message(ParserMessages::notDataOrSubdocEntity, StringMessageArg(value.token(i))); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -