1 /*
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is the Sablotron XSLT Processor.
13  *
14  * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15  * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16  * Ginger Alliance Ltd. All Rights Reserved.
17  *
18  * Contributor(s):
19  *
20  * Alternatively, the contents of this file may be used under the
21  * terms of the GNU General Public License Version 2 or later (the
22  * "GPL"), in which case the provisions of the GPL are applicable
23  * instead of those above.  If you wish to allow use of your
24  * version of this file only under the terms of the GPL and not to
25  * allow others to use your version of this file under the MPL,
26  * indicate your decision by deleting the provisions above and
27  * replace them with the notice and other provisions required by
28  * the GPL.  If you do not delete the provisions above, a recipient
29  * may use your version of this file under either the MPL or the
30  * GPL.
31  */
32 
33 // EXPR.H
34 
35 #ifndef ExprHIncl
36 #define ExprHIncl
37 
38 // GP: clean
39 
40 #include "base.h"
41 #include "datastr.h"
42 #include "proc.h"
43 #include "sxpath.h"
44 #include "jsext.h"
45 
46 class Vertex;
47 
48 /**********************************************************
49 token types
50 **********************************************************/
51 
52 enum ExToken
53 {
54     //end of parsed string
55     TOK_END,
56 
57         //names
58         TOK_NAME,       // name test, incl. '*' and 'prefix:*'
59         TOK_AXISNAME,   // name followed by ::
60         TOK_NTNAME,     // node(), text() etc.
61         TOK_FNAME,      // other names followed by (
62 
63         //symbols
64         TOK_LPAREN,     TOK_RPAREN,
65         TOK_LBRACKET,   TOK_RBRACKET,
66         TOK_PERIOD,     TOK_DPERIOD,
67         TOK_ATSIGN,     TOK_COMMA,
68         TOK_DCOLON,     TOK_DSLASH,
69         TOK_SLASH,
70 
71         //variable reference ($...)
72         TOK_VAR,
73         //string in quotes
74         TOK_LITERAL,
75         //real number
76         TOK_NUMBER,
77 
78         //operators
79         TOKGROUP_OPERATORS,
80         TOK_OR = TOKGROUP_OPERATORS,
81         TOK_AND,
82         TOK_EQ,
83         TOK_NEQ,
84         TOK_LT,
85         TOK_GT,
86         TOK_LE,
87         TOK_GE,
88         TOK_PLUS,
89         TOK_MINUS2,
90         TOK_MINUS = TOK_MINUS2,
91         TOK_MULT,
92         TOK_MOD,
93         TOK_DIV,
94         TOK_MINUS1,
95         TOK_VERT,
96 
97         TOK_STAR,        // as wildcard in names
98         TOK_NONE
99 };
100 
101 class TokenItem /* : public SabObj */
102 {
103 public:
104     ExToken tok;
105     char* firstc;
106     int len;
107     void speak(DStr &, SpeakMode mode);
108 };
109 
110 //ExNodeType is defined in base.h
111 //array exNodeTypeNames in base.cpp
112 
113 class Tokenizer
114 {
115 public:
116     Tokenizer(Expression &owner_);
117     ~Tokenizer();
118 	int findTop(ExToken token, int from);
119     eFlag tokenize(Sit S, const Str &astring);
120     eFlag getToken(Sit S, char *&, TokenItem&, ExToken);
121     eFlag getDelim(Sit S, int &, Bool = FALSE);
122     eFlag stripParens(Sit S, int &, int &);
123     DStr string;
124     PList<TokenItem*> items;
125 private:
126     ExToken tryShort(char *&, ExToken);
127     eFlag lookToken(Sit S, ExToken &, char*, ExToken);
128     eFlag getToken_(Sit S, ExToken &, char*&, ExToken);
129     eFlag getNumber(Sit S, char *&);
130     eFlag getName(Sit S, ExToken&, char *&, ExToken);
131     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
132     Expression &owner;
133 };
134 
135 /*
136 XPath expression types. Correspondence to Sablotron classes:
137 NUMBER          class Number
138 STRING          class Str
139 BOOLEAN         Bool
140 NODESET         class Context
141 */
142 
143 enum ExType
144 {
145     EX_NUMBER,
146     EX_STRING,
147     EX_BOOLEAN,
148     EX_NODESET,
149     EX_NODESET_PATTERN,
150     EX_NONE,
151     EX_FRAGMENT,
152     EX_EXTERNAL,
153     EX_UNKNOWN
154 
155 };
156 
157 /*
158 The following enum comprises four categories of "functors":
159 (1) basic (atom, variable reference etc.)
160 (2) operators (EXFO_...)
161 (3) functions in the XPath core library (EXFF_XPATH_...)
162 (4) functions in the XSLT core library (EXFF_XSLT_...)
163 
164 Groups (2) through (4) should be listed in the given order (that is, operators -
165 XPath functions - XSLT functions) and should end with an item ..._Z
166 (e.g. EXFO_Z).
167 */
168 
169 enum ExFunctor
170 {
171     EXF_ATOM,
172         EXF_VAR,
173         EXF_LOCPATH,
174         EXF_LOCSTEP,
175         EXF_OTHER_FUNC,
176         EXF_FILTER,
177         EXF_STRINGSEQ,
178         EXF_FRAGMENT,
179         EXF_NONE,
180 
181         // EXFO_... (operators)
182         EXFO_OR,
183         EXFO_AND,
184         EXFO_EQ,
185         EXFO_NEQ,
186         EXFO_LT,
187         EXFO_LE,
188         EXFO_GT,
189         EXFO_GE,
190         EXFO_PLUS,
191         EXFO_MINUS2,
192         EXFO_MINUS = EXFO_MINUS2,
193         EXFO_MULT,
194         EXFO_DIV,
195         EXFO_MOD,
196         EXFO_MINUS1,
197         EXFO_UNION,
198         EXFO_Z,             //last in group
199 
200         //functions (fall into 2 groups: core XPath and core XSLT)
201         EXF_FUNCTION,
202 
203         // XPath, NODESET
204         EXFF_LAST,
205         EXFF_POSITION,
206         EXFF_COUNT,
207         EXFF_ID,
208         EXFF_LOCAL_NAME,
209         EXFF_NAMESPACE_URI,
210         EXFF_NAME,
211 
212         // XPath, STRING
213         EXFF_STRING,
214         EXFF_CONCAT,
215         EXFF_STARTS_WITH,
216         EXFF_CONTAINS,
217         EXFF_SUBSTRING_BEFORE,
218         EXFF_SUBSTRING_AFTER,
219         EXFF_SUBSTRING,
220         EXFF_STRING_LENGTH,
221         EXFF_NORMALIZE_SPACE,
222         EXFF_TRANSLATE,
223 
224         // XPath, BOOLEAN
225         EXFF_BOOLEAN,
226         EXFF_NOT,
227         EXFF_TRUE,
228         EXFF_FALSE,
229         EXFF_LANG,
230 
231         // XPath, NUMBER
232         EXFF_NUMBER,
233         EXFF_SUM,
234         EXFF_FLOOR,
235         EXFF_CEILING,
236         EXFF_ROUND,
237 
238         // XSLT core
239         EXFF_DOCUMENT,
240         EXFF_KEY,
241         EXFF_FORMAT_NUMBER,
242         EXFF_CURRENT,
243         EXFF_UNPARSED_ENTITY_URI,
244         EXFF_GENERATE_ID,
245         EXFF_SYSTEM_PROPERTY,
246 
247     //XSLT extensions
248         EXFF_FUNCTION_AVAILABLE,
249         EXFF_ELEMENT_AVAILABLE,
250 
251     //GA extensions
252     EXFF_EVAL,
253 
254         EXFF_NONE
255 };
256 
257 class Expression;
258 
259 /**********************************************************
260 N u m b e r
261 **********************************************************/
262 
263 class Number /* : public SabObj */
264 {
265 public:
266     Number();
267     Number(double);
268     Number& operator= (double);
269     Number& operator= (const Str &);
270     operator double () const;
271     Bool operator== (double);
272     Bool operator< (double);
273     Bool operator> (double);
274     Bool operator== (Number&);
275     Bool operator< (Number&);
276     Bool operator> (Number&);
277     Bool isNaN();
278     Bool isInf();
279     void setNaN();
280     int round();
281 private:
282     double x;
283 };
284 
285 /**********************************************************
286 External
287 **********************************************************/
288 #ifdef ENABLE_JS
289 class External
290 {
291 public:
External()292   External() : priv(NULL) {};
293   External(void *prv, void *val);
294   External(External& other);
295   ~External();
296   void* getValue();
297   void assign(const External& other);
298 private:
299   void decref();
300   JSExternalPrivate *priv;
301 };
302 #endif
303 
304 /**********************************************************
305 L o c S t e p
306 **********************************************************/
307 
308 class Element;
309 
310 class LocStep /* : public SabObj */
311 {
312     friend class Expression;
313 public:
314     LocStep(Element &ownerV_, ExAxis = AXIS_NONE, ExNodeType = EXNODE_NONE);
315     ~LocStep();
316     void set(ExAxis, ExNodeType);
317     eFlag parse(Sit S, Tokenizer&, int&, Bool defaultToo = FALSE);
318     ExAxis ax;
319     ExNodeType ntype;
320     QName ntest;
321     Str piname; //name for the processing-instruction() node test
322     ExprList preds;
323     void speak(Sit S, DStr &s, SpeakMode mode);
324     Bool matchesWithoutPreds(Sit S, NodeHandle v);
325     // eFlag createContextNoPreds(Context *&, int);
326     eFlag shift(Sit S, NodeHandle &v, NodeHandle baseV);
327     Bool positional;
328     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
getOwnerElement()329     Element &getOwnerElement() {return ownerV;}
330 private:
331     int badPreds;
332     Element &ownerV;
333 };
334 
335 
336 /**********************************************************
337 E x p r e s s i o n
338 **********************************************************/
339 
340 class Element;
341 
342 class Expression
343 {
344 public:
345     Expression(Element & owner_, ExFunctor = EXF_NONE);
346     ~Expression();
347     void clearContent();
348     void setLS(ExAxis, ExNodeType);
349     eFlag speak(Sit S, DStr &,SpeakMode);
350     eFlag parse(Sit S, const DStr &, Bool = FALSE, Bool defaultToo = FALSE);
351     eFlag parse(Sit S, Tokenizer&, int, int, Bool defaultToo = FALSE);
352     eFlag eval(Sit S, Expression &, Context *, Bool resolvingGlobals = FALSE);
353     Number tonumber(Sit S);
354 #ifdef ENABLE_JS
355     External& toexternal(Sit S);
356 #endif
357     eFlag tostring(Sit S, Str& result);
358     const Str& tostringRef() const;
359     Bool tobool();
360     Context& tonodeset();
361     const Context& tonodesetRef();
362     eFlag matchesPattern(Sit S, Context *, Bool &result);
363     eFlag trueFor(Sit S, Context *, Bool&);
364     //
365     ExType type;
366     ExFunctor functor;
367     ExprList args;
368     eFlag createContext(Sit S, Context *&, int = -1);
369     LocStep *step;
370     int hasPath;
371     void setAtom(Context*);
372     void setAtom(const Number&);
373     void setAtom(const DStr&);
374     void setAtom(Bool);
375 #ifdef ENABLE_JS
376     void setAtom(const External&);
377 #endif
378     Tree* setFragment();
379     Tree* pTree;
380 
381     // optimizePositional() sets usesLast and positional
382     // returns: 2 if pred contains last()   ( -> usesLast && positional )
383     //          1 if position() only        ( -> positional )
384     //          0 if neither
385     int optimizePositional(int level);
386 
387     // optimizePositionBounds() sets optimizePosition...
388     void optimizePositionBounds();
389 
390     // inBounds:
391     // returns 0 if the position is within bounds, -1 if before, 1 if after
392     int inBounds(int position) const;
393     Element& getOwnerElement() const;
394     Tree& getOwnerTree() const;
395     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
396     Bool containsFunctor(ExFunctor func);
397 protected:
398 private:
399     union
400     {
401       QName *pName;    //of function or variable
402       Str *patomstring;
403       Bool atombool;
404       Number *patomnumber;
405       Context *patomnodeset;
406 #ifdef ENABLE_JS
407       External *patomexternal;
408 #endif
409     };
410     Bool compareCC(Sit S, ExFunctor, const Context &, const Context &);
411     Bool compareCS(Sit S, ExFunctor, const Context &, const Str &);
412     Bool compareCN(Sit S, ExFunctor, const Context &, const Number &);
413     eFlag compare(Sit S, Bool &, Expression &, ExFunctor);
414     Bool isOp(ExToken, int &);
415     eFlag callOp(Sit S, Expression&, ExprList&);
416     eFlag callFunc(Sit S, Expression&, ExprList&, Context *);
417     eFlag parseBasic(Sit S, Tokenizer &, int, int, Bool defaultToo = FALSE);
418     eFlag parseLP(Sit S, Tokenizer&, int &, Bool dropRoot, Bool defaultToo = FALSE);
419     eFlag matchesSinglePath(Sit S, NodeHandle v, int lastIndex, Bool &result);
420     eFlag matchesSingleStep(Sit S, NodeHandle v, Bool &result);
421     eFlag createLPContextLevel(Sit S, int stepLevel, int stepsCount,
422         NodeHandle base, Context& info, Context *theResult);
423     eFlag createLPContext(Sit S, Context *&, int, NodeHandle globalCurrent = NULL);
424     eFlag createLPContextSum(Sit S, Context *&, NodeHandle globalCurrent = NULL);
425     eFlag getDocument_(Sit S, NodeHandle& newroot,
426         const Str& location, const Str& baseUri, Processor *proc);
427 
428     Bool
429         isPattern;
430     eFlag patternOK(Sit S);
431     void setAtomNoCopy(Context &);
432 
433     // in a predicate, these give the bounds to context positions that
434     // suffice to be processed
435     int optimizePositionFrom,
436         optimizePositionTo;
437 
438     // in a predicate, this is true iff the predicate depends on last()
439     Bool usesLast,
440         positional;
441 
442     Element &owner;
443 };
444 
445 #endif //ifndef ExprHIncl
446