📄 contenttoken.cxx
字号:
// Copyright (c) 1994 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif#include "splib.h"#include <stdlib.h>#include "ContentToken.h"#include "macros.h"#include "ElementType.h"#include "Vector.h"#include "Dtd.h"#include "MessageArg.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifAndModelGroup::AndModelGroup(NCVector<Owner<ContentToken> > &v, ContentToken::OccurrenceIndicator oi): ModelGroup(v, oi){}ModelGroup::Connector AndModelGroup::connector() const{ return andConnector;}OrModelGroup::OrModelGroup(NCVector<Owner<ContentToken> > &v, ContentToken::OccurrenceIndicator oi): ModelGroup(v, oi){ setOrGroup();}ModelGroup::Connector OrModelGroup::connector() const{ return orConnector;}SeqModelGroup::SeqModelGroup(NCVector<Owner<ContentToken> > &v, ContentToken::OccurrenceIndicator oi): ModelGroup(v, oi){}ModelGroup::Connector SeqModelGroup::connector() const{ return seqConnector;}ModelGroup::ModelGroup(NCVector<Owner<ContentToken> > &v, OccurrenceIndicator oi): ContentToken(oi){ members_.swap(v);}unsigned long ModelGroup::grpgtcnt() const{ unsigned long cnt = 1; for (size_t i = 0; i < members_.size(); i++) cnt += members_[i]->grpgtcnt(); return cnt;}void ModelGroup::setOrGroup(){ for (size_t i = 0; i < members_.size(); i++) members_[i]->setOrGroupMember();}const ModelGroup *ModelGroup::asModelGroup() const{ return this;}ElementToken::ElementToken(const ElementType *element, OccurrenceIndicator oi): LeafContentToken(element, oi){}ContentToken::ContentToken(OccurrenceIndicator oi): occurrenceIndicator_(oi){}unsigned long ContentToken::grpgtcnt() const{ return 1;}void ContentToken::setOrGroupMember(){}const ModelGroup *ContentToken::asModelGroup() const{ return 0;}const LeafContentToken *ContentToken::asLeafContentToken() const{ return 0;}LeafContentToken::LeafContentToken(const ElementType *element, OccurrenceIndicator oi): element_(element), ContentToken(oi), isFinal_(0), orGroupMember_(0), requiredIndex_(size_t(-1)){}Boolean LeafContentToken::isInitial() const{ return 0;}void LeafContentToken::setOrGroupMember(){ orGroupMember_ = 1;}const LeafContentToken *LeafContentToken::asLeafContentToken() const{ return this;}PcdataToken::PcdataToken(): LeafContentToken(0, rep){}InitialPseudoToken::InitialPseudoToken(): LeafContentToken(0, none){}Boolean InitialPseudoToken::isInitial() const{ return 1;}DataTagGroup::DataTagGroup(NCVector<Owner<ContentToken> > &vec, OccurrenceIndicator oi): SeqModelGroup(vec, oi){}DataTagElementToken::DataTagElementToken(const ElementType *element, Vector<Text> &templates, Text &paddingTemplate): ElementToken(element, ContentToken::none), havePaddingTemplate_(1){ templates.swap(templates_); paddingTemplate.swap(paddingTemplate_);}DataTagElementToken::DataTagElementToken(const ElementType *element, Vector<Text> &templates): ElementToken(element, ContentToken::none), havePaddingTemplate_(0){ templates.swap(templates_);}ContentToken::~ContentToken(){}struct GroupInfo { unsigned nextLeafIndex; PackedBoolean containsPcdata; unsigned andStateSize; Vector<unsigned> nextTypeIndex; GroupInfo(size_t);};GroupInfo::GroupInfo(size_t nType): nextTypeIndex(nType, 0), nextLeafIndex(0), containsPcdata(0), andStateSize(0){}CompiledModelGroup::CompiledModelGroup(Owner<ModelGroup> &modelGroup): modelGroup_(modelGroup.extract()){}void CompiledModelGroup::compile(size_t nElementTypeIndex, Vector<ContentModelAmbiguity> &ambiguities, Boolean &pcdataUnreachable){ FirstSet first; LastSet last; GroupInfo info(nElementTypeIndex); modelGroup_->analyze(info, 0, 0, first, last); for (unsigned i = 0; i < last.size(); i++) last[i]->setFinal(); andStateSize_ = info.andStateSize; containsPcdata_ = info.containsPcdata; initial_ = new InitialPseudoToken; LastSet initialSet(1); initialSet[0] = initial_.pointer(); ContentToken::addTransitions(initialSet, first, 1, 0, 0); if (modelGroup_->inherentlyOptional()) initial_->setFinal(); pcdataUnreachable = 0; Vector<unsigned> minAndDepth(info.nextLeafIndex); Vector<size_t> elementTransition(nElementTypeIndex); initial_->finish(minAndDepth, elementTransition, ambiguities, pcdataUnreachable); modelGroup_->finish(minAndDepth, elementTransition, ambiguities, pcdataUnreachable); if (!containsPcdata_) pcdataUnreachable = 0;}void ModelGroup::finish(Vector<unsigned> &minAndDepth, Vector<size_t> &elementTransition, Vector<ContentModelAmbiguity> &ambiguities, Boolean &pcdataUnreachable){ for (unsigned i = 0; i < nMembers(); i++) member(i).finish(minAndDepth, elementTransition, ambiguities, pcdataUnreachable);}void LeafContentToken::finish(Vector<unsigned> &minAndDepthVec, Vector<size_t> &elementTransitionVec, Vector<ContentModelAmbiguity> &ambiguities, Boolean &pcdataUnreachable){ if (andInfo_) { andFinish(minAndDepthVec, elementTransitionVec, ambiguities, pcdataUnreachable); return; } Vector<size_t>::iterator elementTransition = elementTransitionVec.begin(); Vector<unsigned>::iterator minAndDepth = minAndDepthVec.begin(); minAndDepthVec.assign(minAndDepthVec.size(), unsigned(-1)); elementTransitionVec.assign(elementTransitionVec.size(), size_t(-1)); pcdataTransitionType_ = 0; simplePcdataTransition_ = 0; // follow_ is in decreasing order of andDepth because of how it's // constructed. size_t n = follow_.size(); Vector<LeafContentToken *>::iterator follow = follow_.begin(); size_t j = 0; for (size_t i = 0; i < n; i++) { unsigned &minDepth = minAndDepth[follow[i]->index()]; if (minDepth) { minDepth = 0; if (j != i) follow[j] = follow[i]; if (i == requiredIndex_) requiredIndex_ = j; const ElementType *e = follow[i]->elementType(); unsigned ei; if (e == 0) { if (follow[i]->andInfo_ == 0) { simplePcdataTransition_ = follow[i]; pcdataTransitionType_ = 1; } else pcdataTransitionType_ = 2; ei = 0; } else ei = e->index(); if (elementTransition[ei] != size_t(-1)) { const LeafContentToken *prev = follow[elementTransition[ei]]; // This might not be true: consider (a & b?)*; after the // a there are two different ways to get to the same b, // with the same and depth. if (follow[i] != prev) { ambiguities.resize(ambiguities.size() + 1); ContentModelAmbiguity &a = ambiguities.back(); a.from = this; a.to1 = prev; a.to2 = follow[i]; a.andDepth = 0; } } elementTransition[ei] = j; j++; } } if (pcdataTransitionType_ == 0) pcdataUnreachable = 1; follow_.resize(j);}void LeafContentToken::andFinish(Vector<unsigned> &minAndDepthVec, Vector<size_t> &elementTransitionVec, Vector<ContentModelAmbiguity> &ambiguities, Boolean &pcdataUnreachable){ // Vector mapping element type index to index of leaf content token // of that type to which there is a transition, which is the "worst" // from the point of view of ambiguity. Vector<size_t>::iterator elementTransition = elementTransitionVec.begin(); // Vector mapping index of leaf content token // to minimum AND depth of transition to that token. Vector<unsigned>::iterator minAndDepth = minAndDepthVec.begin(); minAndDepthVec.assign(minAndDepthVec.size(), unsigned(-1)); elementTransitionVec.assign(elementTransitionVec.size(), size_t(-1)); pcdataTransitionType_ = 0; simplePcdataTransition_ = 0; unsigned pcdataMinCovered = 0; // follow_ is in decreasing order of andDepth because of how it's // constructed. size_t n = follow_.size(); size_t j = 0; Vector<Transition>::iterator andFollow = andInfo_->follow.begin(); for (size_t i = 0; i < n; i++) { unsigned &minDepth = minAndDepth[follow_[i]->index()]; // ignore transitions to the same token with the same and depth. if (andFollow[i].andDepth < minDepth) { minDepth = andFollow[i].andDepth; if (j != i) { follow_[j] = follow_[i]; andFollow[j] = andFollow[i]; } if (i == requiredIndex_) requiredIndex_ = j; const ElementType *e = follow_[i]->elementType(); unsigned ei; if (e == 0) { if (pcdataTransitionType_ == 0) { const AndModelGroup *andAncestor = andInfo_->andAncestor; unsigned groupIndex = andInfo_->andGroupIndex; do { Boolean hasNonNull = 0; for (unsigned k = 0; k < andAncestor->nMembers(); k++) if (k != groupIndex && !andAncestor->member(k).inherentlyOptional()) { hasNonNull = 1; break; } if (hasNonNull) { if (minDepth <= andAncestor->andDepth()) pcdataUnreachable = 1; break; } groupIndex = andAncestor->andGroupIndex(); andAncestor = andAncestor->andAncestor(); } while (andAncestor); if (andFollow[i].isolated) pcdataMinCovered = minDepth; pcdataTransitionType_ = 2; } else { if (pcdataMinCovered > minDepth + 1) pcdataUnreachable = 1; pcdataMinCovered = andFollow[i].isolated ? minDepth : 0; } ei = 0; } else ei = e->index(); // If we have transitions t1, t2, ... tN to tokens having // the same element type, with // and-depths d1, d2, ... dN, where d1 >= d2 >= ... >= dN, // then there is an ambiguity unless // d1 > d2 > ... > dN and t1, t2, ... , tN-1 are all isolated. size_t previ = elementTransition[ei]; if (previ != size_t(-1)) { const LeafContentToken *prev = follow_[previ]; // This might not be true: consider (a & b?)*; after the // a there are two different ways to get to the same b, // with the same and depth. if (follow_[i] != prev && (andFollow[previ].andDepth == andFollow[i].andDepth || !andFollow[previ].isolated)) { ambiguities.resize(ambiguities.size() + 1); ContentModelAmbiguity &a = ambiguities.back(); a.from = this; a.to1 = prev; a.to2 = follow_[i]; a.andDepth = andFollow[i].andDepth; } if (andFollow[previ].isolated) elementTransition[ei] = j; } else elementTransition[ei] = j; j++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -