📄 partition.cxx
字号:
// Copyright (c) 1994 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif#include "splib.h"#include "Partition.h"#include "ISet.h"#include "ISetIter.h"#include "SubstTable.h"#include "Link.h"#include "IList.h"#include "IListIter.h"#include "Owner.h"#include "macros.h"#include "EquivClass.h"#include "constant.h"#include "StringC.h"#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifstatic void refineByChar(IList<EquivClass> *, Char);static void refineBySet(IList<EquivClass> *, const ISet<Char> &, unsigned);#if _MSC_VER == 900// Work around MSVC 2.0 bug.typedef SubstTable<Char> _msvc_dummy;#endifPartition::Partition(const ISet<Char> &chars, const ISet<Char> **sets, int nSets, const SubstTable<Char> &subst): map_(0) // eE gets code 0{ IList<EquivClass> classes; classes.insert(new EquivClass); classes.head()->set.addRange(0, charMax); { ISetIter<Char> iter(chars); Char min, max; while (iter.next(min, max)) { do { refineByChar(&classes, subst[min]); } while (min++ != max); } } int i; for (i = 0; i < nSets; i++) refineBySet(&classes, *sets[i], (1 << i)); maxCode_ = 0; setCodes_.resize(nSets); for (IListIter<EquivClass> listIter(classes); !listIter.done(); listIter.next()) { ++maxCode_; ASSERT(maxCode_ != 0); EquivClass *p = listIter.cur(); for (i = 0; i < nSets; i++) if ((1 << i) & p->inSets) setCodes_[i] += maxCode_; ISetIter<Char> setIter(p->set); Char min, max; while (setIter.next(min, max)) map_.setRange(min, max, maxCode_); } { ISetIter<Char> iter(chars); Char min, max; while (iter.next(min, max)) { do { StringC str(subst.inverse(min)); EquivCode code = map_[min]; for (size_t i = 0; i < str.size(); i++) map_.setChar(str[i], code); } while (min++ != max); } }}staticvoid refineByChar(IList<EquivClass> *classes, Char c){ // Avoid modifying *classes, while there's an active iter on it. EquivClass *found = 0; { for (IListIter<EquivClass> iter(*classes); !iter.done(); iter.next()) { if (iter.cur()->set.contains(c)) { found = iter.cur(); break; } } } if (found && !found->set.isSingleton()) { found->set.remove(c); classes->insert(new EquivClass(found->inSets)); classes->head()->set.add(c); }}staticvoid addUpTo(ISet<Char> *to, Char limit, const ISet<Char> &from){ ISetIter<Char> iter(from); Char min, max; while (iter.next(min, max) && min < limit) to->addRange(min, max >= limit ? limit - 1 : max);}enum RefineResult { allIn, allOut, someInSomeOut };staticRefineResult refine(const ISet<Char> &set, const ISet<Char> &refiner, ISet<Char> *inp, ISet<Char> *outp){ Char setMin, setMax, refMin, refMax; ISetIter<Char> refIter(refiner); ISetIter<Char> setIter(set); Boolean oneIn = 0; Boolean oneOut = 0; if (!refIter.next(refMin, refMax)) return allOut; while (setIter.next(setMin, setMax)) { while (setMin <= setMax) { while (refMax < setMin && refIter.next(refMin, refMax)) ; if (refMax < setMin || setMin < refMin) { if (!oneOut) { if (oneIn) addUpTo(inp, setMin, set); oneOut = 1; } if (refMax < setMin || refMin > setMax) { if (oneIn) outp->addRange(setMin, setMax); break; } else { if (oneIn) outp->addRange(setMin, refMin - 1); setMin = refMin; } } else { if (!oneIn) { if (oneOut) addUpTo(outp, setMin, set); oneIn = 1; } if (setMax <= refMax) { if (oneOut) inp->addRange(setMin, setMax); break; } else { // refMax < setMax if (oneOut) inp->addRange(setMin, refMax); // avoid wrapping round if (refMax == charMax) break; setMin = refMax + 1; } } } } if (oneIn) return oneOut ? someInSomeOut : allIn; else return allOut;}staticvoid refineBySet(IList<EquivClass> *classes, const ISet<Char> &set, unsigned setFlag){ Owner<EquivClass> in(new EquivClass), out(new EquivClass); IList<EquivClass> newClasses; for (;;) { EquivClass *p = classes->head(); if (!p) break; if (!out) out = new EquivClass; switch (refine(p->set, set, &in->set, &out->set)) { case someInSomeOut: in->inSets = p->inSets | setFlag; newClasses.insert(in.extract()); out->inSets = p->inSets; newClasses.insert(out.extract()); in = classes->get(); in->set.clear(); in->inSets = 0; break; case allIn: p->inSets |= setFlag; newClasses.insert(classes->get()); break; case allOut: newClasses.insert(classes->get()); break; } } classes->swap(newClasses);}#ifdef SP_NAMESPACE}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -