1 // Copyright (c) 1996, 1997 James Clark
2 // See the file copying.txt for copying permission.
5 #include "ProcessingMode.h"
6 #include "Interpreter.h"
7 #include "MessageArg.h"
8 #include "InterpreterMessages.h"
9 #include "Expression.h"
12 #include "IListIter.h"
17 #ifdef DSSSL_NAMESPACE
18 namespace DSSSL_NAMESPACE {
21 ProcessingMode::ProcessingMode(const StringC &name, const ProcessingMode *initial)
22 : Named(name), initial_(initial), defined_(0)
26 void ProcessingMode::compile(Interpreter &interp)
28 for (int i = 0; i < nRuleType; i++) {
29 for (size_t j = 0; j < rootRules_[i].size(); j++)
30 rootRules_[i][j].action().compile(interp, RuleType(i));
31 for (IListIter<ElementRule> iter(elementRules_[i]); !iter.done(); iter.next())
32 iter.cur()->action().compile(interp, RuleType(i));
36 void ProcessingMode::GroveRules::build(const IList<ElementRule> *lists,
41 for (int ruleType = 0; ruleType < nRuleType; ruleType++) {
42 for (IListIter<ElementRule> iter(lists[ruleType]); !iter.done(); iter.next()) {
44 if (iter.cur()->mustHaveGi(gi)) {
45 Interpreter::normalizeGeneralName(node, gi);
46 ElementRules *p = elementTable.lookup(gi);
48 p = new ElementRules(gi);
49 elementTable.insert(p);
51 p->rules[ruleType].push_back(iter.cur());
54 otherRules[ruleType].push_back(iter.cur());
57 for (int ruleType = 0; ruleType < nRuleType; ruleType++) {
58 NamedTableIter<ElementRules> iter(elementTable);
60 ElementRules *p = iter.next();
63 size_t j = p->rules[ruleType].size();
64 p->rules[ruleType].resize(p->rules[ruleType].size() + otherRules[ruleType].size());
65 for (size_t i = 0; i < otherRules[ruleType].size(); i++)
66 p->rules[ruleType][j++] = otherRules[ruleType][i];
67 sortRules(p->rules[ruleType]);
69 sortRules(otherRules[ruleType]);
76 int ruleCompare(const void *p1, const void *p2)
78 return (*(const ProcessingMode::Rule *const *)p1)
79 ->compareSpecificity(**(const ProcessingMode::Rule *const *)p2);
84 void ProcessingMode::GroveRules::sortRules(Vector<const ElementRule *> &v)
86 qsort(&v[0], v.size(), sizeof(v[0]), ruleCompare);
89 ProcessingMode::Action::Action(unsigned partIndex, Owner<Expression> &expr,
91 : partIndex_(partIndex), defLoc_(loc), sosofo_(0)
96 ProcessingMode::Rule::Rule()
100 ProcessingMode::Rule::Rule(const Ptr<Action> &action)
105 int ProcessingMode::Rule::compareSpecificity(const Rule &r) const
107 unsigned i1 = action().partIndex();
108 unsigned i2 = r.action().partIndex();
111 return i1 < i2 ? -1 : 1;
114 void ProcessingMode::Action::compile(Interpreter &interp, RuleType ruleType)
116 expr_->optimize(interp, Environment(), expr_);
117 ELObj *tem = expr_->constantValue();
119 if (ruleType == constructionRule) {
120 sosofo_ = tem->asSosofo();
126 if (ruleType == constructionRule)
127 check = new CheckSosofoInsn(defLoc_, check);
128 insn_ = expr_->compile(interp, Environment(), 0, check);
131 ProcessingMode::ElementRule::ElementRule(const Ptr<Action> &action,
138 int ProcessingMode::ElementRule::compareSpecificity(const Rule &r) const
140 int result = Rule::compareSpecificity(r);
143 return Pattern::compareSpecificity(*this, (const ElementRule &)r);
146 void ProcessingMode::addRule(bool root,
147 NCVector<Pattern> &patterns,
148 Owner<Expression> &expr,
153 Ptr<Action> action = new Action(interp.currentPartIndex(), expr, loc);
154 for (size_t i = 0; i < patterns.size(); i++)
155 elementRules_[ruleType].insert(new ElementRule(action, patterns[i]));
158 Vector<Rule> &rules = rootRules_[ruleType];
159 rules.push_back(Rule(action));
160 for (size_t i = rules.size() - 1; i > 0; i--) {
161 int cmp = rules[i - 1].compareSpecificity(rules[i]);
163 if (cmp == 0 && ruleType == constructionRule) {
164 interp.setNextLocation(loc);
165 interp.message(InterpreterMessages::duplicateRootRule,
166 rules[i - 1].location());
170 rules[i - 1].swap(rules[i]);
174 ProcessingMode::GroveRules::GroveRules()
179 ProcessingMode::ElementRules::ElementRules(const StringC &name)
184 // Specificity gives specificity of last match; get specificity of current match.
186 const ProcessingMode::Rule *
187 ProcessingMode::findMatch(const NodePtr &node,
188 Pattern::MatchContext &context,
190 Specificity &specificity) const
193 if (node->getGi(gi) == accessOK)
194 return findElementMatch(StringC(gi.data(), gi.size()), node, context, mgr,
197 if (node->getOrigin(tem) != accessOK)
198 return findRootMatch(node, context, mgr, specificity);
203 const ProcessingMode::Rule *
204 ProcessingMode::findElementMatch(const StringC &gi,
206 Pattern::MatchContext &context,
208 Specificity &specificity) const
210 const Vector<const ElementRule *> *vecP = 0;
214 const ProcessingMode &mode
215 = *(initial_ && specificity.toInitial_ ? initial_ : this);
217 const GroveRules &gr = mode.groveRules(node, mgr);
218 const ElementRules *er = gr.elementTable.lookup(gi);
219 vecP = er ? er->rules : gr.otherRules;
221 const Vector<const ElementRule *> &vec = vecP[specificity.ruleType_];
222 ASSERT(specificity.nextRuleIndex_ <= vec.size());
223 for (size_t &i = specificity.nextRuleIndex_; i < vec.size(); i++) {
224 if (vec[i]->trivial() || vec[i]->matches(node, context)) {
225 const Rule *rule = vec[i];
226 elementRuleAdvance(node, context, mgr, specificity, vec);
233 if (specificity.toInitial_)
235 specificity.nextRuleIndex_ = 0;
236 specificity.toInitial_ = 1;
238 if (specificity.ruleType_ == constructionRule)
240 specificity.ruleType_ = constructionRule;
241 specificity.nextRuleIndex_ = 0;
242 specificity.toInitial_ = 0;
247 const ProcessingMode::Rule *
248 ProcessingMode::findRootMatch(const NodePtr &node,
249 Pattern::MatchContext &context,
251 Specificity &specificity) const
255 const ProcessingMode &mode = *(initial_ && specificity.toInitial_ ? initial_ : this);
256 const Vector<Rule> &rules = mode.rootRules_[specificity.ruleType_];
257 if (specificity.nextRuleIndex_ < rules.size())
258 return &rules[specificity.nextRuleIndex_++];
259 if (!initial_ || specificity.toInitial_)
261 specificity.nextRuleIndex_ = 0;
262 specificity.toInitial_ = 1;
264 if (specificity.ruleType_ == constructionRule)
266 specificity.ruleType_ = constructionRule;
267 specificity.nextRuleIndex_ = 0;
268 specificity.toInitial_ = 0;
273 const ProcessingMode::GroveRules &ProcessingMode::groveRules(const NodePtr &node,
274 Messenger &mgr) const
276 unsigned long n = node->groveIndex();
277 ProcessingMode *cache = (ProcessingMode *)this;
278 if (n >= groveRules_.size())
279 cache->groveRules_.resize(n + 1);
280 if (!groveRules_[n].built)
281 cache->groveRules_[n].build(elementRules_, node, mgr);
282 return groveRules_[n];
285 void ProcessingMode::elementRuleAdvance(const NodePtr &node,
286 Pattern::MatchContext &context,
288 Specificity &specificity,
289 const Vector<const ElementRule *> &vec)
291 size_t &i = specificity.nextRuleIndex_;
292 if (specificity.ruleType_ != constructionRule) {
300 || vec[hit]->ElementRule::compareSpecificity(*vec[i]) != 0)
302 } while (!(vec[i]->trivial() || vec[i]->matches(node, context)));
306 if ((lnp = LocNode::convert(node)) != 0
307 && lnp->getLocation(nodeLoc) == accessOK)
308 mgr.setNextLocation(nodeLoc);
309 mgr.message(InterpreterMessages::ambiguousMatch);
312 } while (i < vec.size()
313 && vec[hit]->ElementRule::compareSpecificity(*vec[i]) == 0);
316 #ifdef DSSSL_NAMESPACE