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