1 // Copyright (c) 1997 James Clark
2 // See the file copying.txt for copying permission.
3
4 #ifndef Pattern_INCLUDED
5 #define Pattern_INCLUDED 1
6
7 #include "Boolean.h"
8 #include "Node.h"
9 #include "Link.h"
10 #include "IList.h"
11 #include "IListIter.h"
12 #include "StringC.h"
13 #include "Vector.h"
14 #include "Ptr.h"
15 #include "Resource.h"
16
17 #ifdef DSSSL_NAMESPACE
18 namespace DSSSL_NAMESPACE {
19 #endif
20
21 class Pattern {
22 public:
23 class MatchContext : public SdataMapper {
24 public:
25 const Vector<StringC> &classAttributeNames() const;
26 const Vector<StringC> &idAttributeNames() const;
27 protected:
28 Vector<StringC> classAttributeNames_;
29 Vector<StringC> idAttributeNames_;
30 };
31 class Qualifier : public Link {
32 public:
33 virtual ~Qualifier();
34 virtual bool satisfies(const NodePtr &, MatchContext &) const = 0;
35 virtual void contributeSpecificity(int *) const = 0;
36 virtual bool vacuous() const;
37 protected:
38 static bool matchAttribute(const StringC &name,
39 const StringC &value,
40 const NodePtr &nd,
41 MatchContext &context);
42 };
43 class IdQualifier : public Qualifier {
44 public:
45 IdQualifier(const StringC &);
46 bool satisfies(const NodePtr &, MatchContext &) const;
47 void contributeSpecificity(int *) const;
48 private:
49 StringC id_;
50 };
51 class ClassQualifier : public Qualifier {
52 public:
53 ClassQualifier(const StringC &);
54 bool satisfies(const NodePtr &, MatchContext &) const;
55 void contributeSpecificity(int *) const;
56 private:
57 StringC class_;
58 };
59 class AttributeHasValueQualifier : public Qualifier {
60 public:
61 AttributeHasValueQualifier(const StringC &);
62 bool satisfies(const NodePtr &, MatchContext &) const;
63 void contributeSpecificity(int *) const;
64 private:
65 StringC name_;
66 };
67 class AttributeMissingValueQualifier : public Qualifier {
68 public:
69 AttributeMissingValueQualifier(const StringC &);
70 bool satisfies(const NodePtr &, MatchContext &) const;
71 void contributeSpecificity(int *) const;
72 private:
73 StringC name_;
74 };
75 class AttributeQualifier : public Qualifier {
76 public:
77 AttributeQualifier(const StringC &, const StringC &);
78 bool satisfies(const NodePtr &, MatchContext &) const;
79 void contributeSpecificity(int *) const;
80 private:
81 StringC name_;
82 StringC value_;
83 };
84 class PositionQualifier : public Qualifier {
85 public:
86 void contributeSpecificity(int *) const;
87 };
88 class FirstOfTypeQualifier : public PositionQualifier {
89 public:
90 bool satisfies(const NodePtr &, MatchContext &) const;
91 };
92 class LastOfTypeQualifier : public PositionQualifier {
93 public:
94 bool satisfies(const NodePtr &, MatchContext &) const;
95 };
96 class FirstOfAnyQualifier : public PositionQualifier {
97 public:
98 bool satisfies(const NodePtr &, MatchContext &) const;
99 };
100 class LastOfAnyQualifier : public PositionQualifier {
101 public:
102 bool satisfies(const NodePtr &, MatchContext &) const;
103 };
104 class OnlyQualifier : public Qualifier {
105 public:
106 void contributeSpecificity(int *) const;
107 };
108 class OnlyOfTypeQualifier : public OnlyQualifier {
109 public:
110 bool satisfies(const NodePtr &, MatchContext &) const;
111 };
112 class OnlyOfAnyQualifier : public OnlyQualifier {
113 public:
114 bool satisfies(const NodePtr &, MatchContext &) const;
115 };
116 class VacuousQualifier : public Qualifier {
117 public:
118 bool vacuous() const;
119 };
120 class PriorityQualifier : public VacuousQualifier {
121 public:
122 PriorityQualifier(long);
123 void contributeSpecificity(int *) const;
124 bool satisfies(const NodePtr &, MatchContext &) const;
125 private:
126 long n_;
127 };
128 class ImportanceQualifier : public VacuousQualifier {
129 public:
130 ImportanceQualifier(long);
131 void contributeSpecificity(int *) const;
132 bool satisfies(const NodePtr &, MatchContext &) const;
133 private:
134 long n_;
135 };
136 typedef unsigned Repeat;
137 class Element : public Link {
138 public:
139 Element(const StringC &);
140 bool matches(const NodePtr &, MatchContext &) const;
141 void contributeSpecificity(int *) const;
142 void addQualifier(Qualifier *);
143 void setRepeat(Repeat minRepeat, Repeat maxRepeat);
144 Repeat minRepeat() const;
145 Repeat maxRepeat() const;
146 bool mustHaveGi(StringC &) const;
147 bool trivial() const;
148 private:
149 StringC gi_;
150 Repeat minRepeat_;
151 Repeat maxRepeat_;
152 IList<Qualifier> qualifiers_;
153 };
154 class ChildrenQualifier : public Qualifier {
155 public:
156 ChildrenQualifier(IList<Element> &);
157 bool satisfies(const NodePtr &, MatchContext &) const;
158 void contributeSpecificity(int *) const;
159 private:
160 IList<Element> children_;
161 };
162 Pattern();
163 Pattern(IList<Element> &);
164 void swap(Pattern &);
165 bool matches(const NodePtr &, MatchContext &) const;
166 // If mustHaveGi returns true, then any element that matches the pattern
167 // must have the string returned in str.
168 bool mustHaveGi(StringC &str) const;
169 // A pattern is trivial if any element that has the gi returned my mustHaveGi
170 // matches the pattern, or, if mustHaveGi returns false, if any element matches
171 // the pattern.
172 bool trivial() const;
173 static int compareSpecificity(const Pattern &, const Pattern &);
174 enum {
175 importanceSpecificity,
176 idSpecificity,
177 classSpecificity,
178 giSpecificity,
179 repeatSpecificity,
180 prioritySpecificity,
181 onlySpecificity,
182 positionSpecificity,
183 attributeSpecificity,
184 nSpecificity
185 };
186 private:
187 Pattern(const Pattern &); // undefined
188 void operator=(const Pattern &); // undefined
189 void computeSpecificity(int *) const;
190 static bool computeTrivial(const IList<Element> &);
191
192 static bool matchAncestors(const IListIter<Element> &,
193 const NodePtr &,
194 MatchContext &);
195 static bool matchAncestors1(const IListIter<Element> &,
196 const NodePtr &,
197 MatchContext &);
198
199 IList<Element> ancestors_; // first is self, second is parent ...
200 bool trivial_;
201 };
202
203 inline
setRepeat(Repeat minRepeat,Repeat maxRepeat)204 void Pattern::Element::setRepeat(Repeat minRepeat, Repeat maxRepeat)
205 {
206 minRepeat_ = minRepeat;
207 maxRepeat_ = maxRepeat;
208 }
209
210 inline
minRepeat()211 Pattern::Repeat Pattern::Element::minRepeat() const
212 {
213 return minRepeat_;
214 }
215
216 inline
maxRepeat()217 Pattern::Repeat Pattern::Element::maxRepeat() const
218 {
219 return maxRepeat_;
220 }
221
222 inline
addQualifier(Qualifier * q)223 void Pattern::Element::addQualifier(Qualifier *q)
224 {
225 qualifiers_.insert(q);
226 }
227
228 inline
matchAncestors(const IListIter<Element> & ancestors,const NodePtr & node,MatchContext & context)229 bool Pattern::matchAncestors(const IListIter<Element> &ancestors,
230 const NodePtr &node,
231 MatchContext &context)
232 {
233 return ancestors.done() || matchAncestors1(ancestors, node, context);
234 }
235
236 inline
matches(const NodePtr & nd,MatchContext & context)237 bool Pattern::matches(const NodePtr &nd, MatchContext &context) const
238 {
239 return matchAncestors(IListIter<Element>(ancestors_),
240 nd,
241 context);
242 }
243
244 inline
swap(Pattern & pattern)245 void Pattern::swap(Pattern &pattern)
246 {
247 ancestors_.swap(pattern.ancestors_);
248 bool tem = trivial_;
249 trivial_ = pattern.trivial_;
250 pattern.trivial_ = tem;
251 }
252
253 inline
mustHaveGi(StringC & gi)254 bool Pattern::Element::mustHaveGi(StringC &gi) const
255 {
256 if (minRepeat_ == 0)
257 return 0;
258 else if (gi_.size()) {
259 gi = gi_;
260 return 1;
261 }
262 else
263 return 0;
264 }
265
266 inline
mustHaveGi(StringC & gi)267 bool Pattern::mustHaveGi(StringC &gi) const
268 {
269 return !ancestors_.empty() && ancestors_.head()->mustHaveGi(gi);
270 }
271
272 inline
classAttributeNames()273 const Vector<StringC> &Pattern::MatchContext::classAttributeNames() const
274 {
275 return classAttributeNames_;
276 }
277
278 inline
idAttributeNames()279 const Vector<StringC> &Pattern::MatchContext::idAttributeNames() const
280 {
281 return idAttributeNames_;
282 }
283
284 inline
trivial()285 bool Pattern::trivial() const
286 {
287 return trivial_;
288 }
289
290 #ifdef DSSSL_NAMESPACE
291 }
292 #endif
293
294 #endif /* not Pattern_INCLUDED */
295