~ubuntu-branches/ubuntu/trusty/openjade1.3/trusty

« back to all changes in this revision

Viewing changes to style/ProcessingMode.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2002-04-09 00:01:50 UTC
  • Revision ID: james.westby@ubuntu.com-20020409000150-r9rkyalxlhvf9ba3
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 1996, 1997 James Clark
 
2
// See the file copying.txt for copying permission.
 
3
 
 
4
#include "stylelib.h"
 
5
#include "ProcessingMode.h"
 
6
#include "Interpreter.h"
 
7
#include "MessageArg.h"
 
8
#include "InterpreterMessages.h"
 
9
#include "Expression.h"
 
10
#include "Insn.h"
 
11
#include "Insn2.h"
 
12
#include "IListIter.h"
 
13
#include "LocNode.h"
 
14
#include "macros.h"
 
15
#include <stdlib.h>
 
16
 
 
17
#ifdef DSSSL_NAMESPACE
 
18
namespace DSSSL_NAMESPACE {
 
19
#endif
 
20
 
 
21
ProcessingMode::ProcessingMode(const StringC &name, const ProcessingMode *initial)
 
22
: Named(name), initial_(initial), defined_(0)
 
23
{
 
24
}
 
25
 
 
26
void ProcessingMode::compile(Interpreter &interp)
 
27
{
 
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));
 
33
  }
 
34
}
 
35
 
 
36
void ProcessingMode::GroveRules::build(const IList<ElementRule> *lists,
 
37
                                       const NodePtr &node,
 
38
                                       Messenger &)
 
39
{
 
40
  built = 1;
 
41
  for (int ruleType = 0; ruleType < nRuleType; ruleType++) {
 
42
    for (IListIter<ElementRule> iter(lists[ruleType]); !iter.done(); iter.next()) {
 
43
      StringC gi;
 
44
      if (iter.cur()->mustHaveGi(gi)) {
 
45
        Interpreter::normalizeGeneralName(node, gi);
 
46
        ElementRules *p = elementTable.lookup(gi);
 
47
        if (!p) {
 
48
          p = new ElementRules(gi);
 
49
          elementTable.insert(p);
 
50
        }
 
51
        p->rules[ruleType].push_back(iter.cur());
 
52
      }
 
53
      else
 
54
        otherRules[ruleType].push_back(iter.cur());
 
55
    }
 
56
  }
 
57
  for (int ruleType = 0; ruleType < nRuleType; ruleType++) {
 
58
    NamedTableIter<ElementRules> iter(elementTable);
 
59
    for (;;) {
 
60
      ElementRules *p = iter.next();
 
61
      if (!p)
 
62
        break;
 
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]);
 
68
    }
 
69
    sortRules(otherRules[ruleType]);
 
70
  }
 
71
}
 
72
 
 
73
extern "C" {
 
74
 
 
75
static
 
76
int ruleCompare(const void *p1, const void *p2)
 
77
{
 
78
  return (*(const ProcessingMode::Rule *const *)p1)
 
79
         ->compareSpecificity(**(const ProcessingMode::Rule *const *)p2);
 
80
}
 
81
 
 
82
}
 
83
 
 
84
void ProcessingMode::GroveRules::sortRules(Vector<const ElementRule *> &v)
 
85
{
 
86
  qsort(&v[0], v.size(), sizeof(v[0]), ruleCompare);
 
87
}
 
88
 
 
89
ProcessingMode::Action::Action(unsigned partIndex, Owner<Expression> &expr,
 
90
                           const Location &loc)
 
91
: partIndex_(partIndex), defLoc_(loc), sosofo_(0)
 
92
{
 
93
  expr.swap(expr_);
 
94
}
 
95
 
 
96
ProcessingMode::Rule::Rule()
 
97
{
 
98
}
 
99
 
 
100
ProcessingMode::Rule::Rule(const Ptr<Action> &action)
 
101
: action_(action)
 
102
{
 
103
}
 
104
 
 
105
int ProcessingMode::Rule::compareSpecificity(const Rule &r) const
 
106
{
 
107
  unsigned i1 = action().partIndex();
 
108
  unsigned i2 = r.action().partIndex();
 
109
  if (i1 == i2)
 
110
    return 0;
 
111
  return i1 < i2 ? -1 : 1;
 
112
}
 
113
 
 
114
void ProcessingMode::Action::compile(Interpreter &interp, RuleType ruleType)
 
115
{
 
116
  expr_->optimize(interp, Environment(), expr_);
 
117
  ELObj *tem = expr_->constantValue();
 
118
  if (tem) {
 
119
    if (ruleType == constructionRule) {
 
120
      sosofo_ = tem->asSosofo();
 
121
      if (sosofo_)
 
122
        return;
 
123
    }
 
124
  }
 
125
  InsnPtr check;
 
126
  if (ruleType == constructionRule)
 
127
    check = new CheckSosofoInsn(defLoc_, check);
 
128
  insn_ = expr_->compile(interp, Environment(), 0, check);
 
129
}
 
130
 
 
131
ProcessingMode::ElementRule::ElementRule(const Ptr<Action> &action,
 
132
                                         Pattern &pattern)
 
133
: Rule(action)
 
134
{
 
135
  pattern.swap(*this);
 
136
}
 
137
 
 
138
int ProcessingMode::ElementRule::compareSpecificity(const Rule &r) const
 
139
{
 
140
  int result = Rule::compareSpecificity(r);
 
141
  if (result)
 
142
    return result;
 
143
  return Pattern::compareSpecificity(*this, (const ElementRule &)r);
 
144
}
 
145
 
 
146
void ProcessingMode::addRule(bool root,
 
147
                             NCVector<Pattern> &patterns,
 
148
                             Owner<Expression> &expr,
 
149
                             RuleType ruleType,
 
150
                             const Location &loc,
 
151
                             Interpreter &interp)
 
152
{
 
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]));
 
156
  if (!root)
 
157
    return;
 
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]);
 
162
    if (cmp <= 0) {
 
163
      if (cmp == 0 && ruleType == constructionRule) {
 
164
        interp.setNextLocation(loc);
 
165
        interp.message(InterpreterMessages::duplicateRootRule,
 
166
                       rules[i - 1].location());
 
167
      }
 
168
      break;
 
169
    }
 
170
    rules[i - 1].swap(rules[i]);
 
171
  }
 
172
}
 
173
 
 
174
ProcessingMode::GroveRules::GroveRules()
 
175
: built(0)
 
176
{
 
177
}
 
178
 
 
179
ProcessingMode::ElementRules::ElementRules(const StringC &name)
 
180
: Named(name)
 
181
{
 
182
}
 
183
 
 
184
// Specificity gives specificity of last match; get specificity of current match.
 
185
 
 
186
const ProcessingMode::Rule *
 
187
ProcessingMode::findMatch(const NodePtr &node,
 
188
                          Pattern::MatchContext &context,
 
189
                          Messenger &mgr,
 
190
                          Specificity &specificity) const
 
191
{
 
192
  GroveString gi;
 
193
  if (node->getGi(gi) == accessOK)
 
194
    return findElementMatch(StringC(gi.data(), gi.size()), node, context, mgr,
 
195
                            specificity);
 
196
  NodePtr tem;
 
197
  if (node->getOrigin(tem) != accessOK)
 
198
    return findRootMatch(node, context, mgr, specificity);
 
199
  return 0;
 
200
}
 
201
 
 
202
 
 
203
const ProcessingMode::Rule *
 
204
ProcessingMode::findElementMatch(const StringC &gi,
 
205
                                 const NodePtr &node,
 
206
                                 Pattern::MatchContext &context,
 
207
                                 Messenger &mgr,
 
208
                                 Specificity &specificity) const
 
209
{
 
210
  const Vector<const ElementRule *> *vecP = 0;
 
211
 
 
212
  for (;;) {
 
213
    for (;;) {
 
214
      const ProcessingMode &mode
 
215
        = *(initial_ && specificity.toInitial_ ? initial_ : this);
 
216
      if (!vecP) {
 
217
        const GroveRules &gr = mode.groveRules(node, mgr);
 
218
        const ElementRules *er = gr.elementTable.lookup(gi);
 
219
        vecP = er ? er->rules : gr.otherRules;
 
220
      }
 
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);
 
227
          return rule;
 
228
        }
 
229
      }
 
230
      if (!initial_)
 
231
        break;
 
232
      vecP = 0;
 
233
      if (specificity.toInitial_)
 
234
        break;
 
235
      specificity.nextRuleIndex_ = 0;
 
236
      specificity.toInitial_ = 1;
 
237
    }
 
238
    if (specificity.ruleType_ == constructionRule)
 
239
      break;
 
240
    specificity.ruleType_ = constructionRule;
 
241
    specificity.nextRuleIndex_ = 0;
 
242
    specificity.toInitial_ = 0;
 
243
  }
 
244
  return 0;
 
245
}
 
246
 
 
247
const ProcessingMode::Rule *
 
248
ProcessingMode::findRootMatch(const NodePtr &node,
 
249
                              Pattern::MatchContext &context,
 
250
                              Messenger &mgr,
 
251
                              Specificity &specificity) const
 
252
{
 
253
  for (;;) {
 
254
    for (;;) {
 
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_)
 
260
        break;
 
261
      specificity.nextRuleIndex_ = 0;
 
262
      specificity.toInitial_ = 1;
 
263
    }
 
264
    if (specificity.ruleType_ == constructionRule)
 
265
      break;
 
266
    specificity.ruleType_ = constructionRule;
 
267
    specificity.nextRuleIndex_ = 0;
 
268
    specificity.toInitial_ = 0;
 
269
  }
 
270
  return 0;
 
271
}
 
272
 
 
273
const ProcessingMode::GroveRules &ProcessingMode::groveRules(const NodePtr &node,
 
274
                                                             Messenger &mgr) const
 
275
{
 
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];
 
283
}
 
284
 
 
285
void ProcessingMode::elementRuleAdvance(const NodePtr &node,
 
286
                                        Pattern::MatchContext &context,
 
287
                                        Messenger &mgr,
 
288
                                        Specificity &specificity,
 
289
                                        const Vector<const ElementRule *> &vec)
 
290
{
 
291
  size_t &i = specificity.nextRuleIndex_;
 
292
  if (specificity.ruleType_ != constructionRule) {
 
293
    ++i;
 
294
    return;
 
295
  }
 
296
  size_t hit = i;
 
297
  do {
 
298
    ++i;
 
299
    if (i >= vec.size()
 
300
        || vec[hit]->ElementRule::compareSpecificity(*vec[i]) != 0)
 
301
      return;
 
302
  } while (!(vec[i]->trivial() || vec[i]->matches(node, context)));
 
303
 
 
304
  const LocNode *lnp;
 
305
  Location nodeLoc;
 
306
  if ((lnp = LocNode::convert(node)) != 0
 
307
      && lnp->getLocation(nodeLoc) == accessOK)
 
308
    mgr.setNextLocation(nodeLoc);
 
309
  mgr.message(InterpreterMessages::ambiguousMatch);
 
310
  do {
 
311
    ++i;
 
312
  } while (i < vec.size()
 
313
           && vec[hit]->ElementRule::compareSpecificity(*vec[i]) == 0);
 
314
}
 
315
 
 
316
#ifdef DSSSL_NAMESPACE
 
317
}
 
318
#endif