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