Initial revision
[TestXSLT.git] / libsablot / src / engine / expr.h
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         EXFF_NONE
251 };
252
253 class Expression;
254
255 /**********************************************************
256 N u m b e r
257 **********************************************************/
258
259 class Number /* : public SabObj */
260 {
261 public:
262     Number();
263     Number(double);
264     Number& operator= (double);
265     Number& operator= (const Str &);
266     operator double () const;
267     Bool operator== (double);
268     Bool operator< (double);
269     Bool operator> (double);
270     Bool operator== (Number&);
271     Bool operator< (Number&);
272     Bool operator> (Number&);
273     Bool isNaN();
274     Bool isInf();
275     void setNaN();
276     int round();
277 private:
278     double x;
279 };
280
281 /**********************************************************
282 External
283 **********************************************************/
284 #ifdef ENABLE_JS
285 class External
286 {
287 public:
288   External() : priv(NULL) {};
289   External(void *prv, void *val);
290   External(External& other);
291   ~External();
292   void* getValue();
293   void assign(const External& other);
294 private:
295   void decref();
296   JSExternalPrivate *priv;
297 };
298 #endif
299
300 /**********************************************************
301 L o c S t e p
302 **********************************************************/
303
304 class Element;
305
306 class LocStep /* : public SabObj */
307 {
308     friend class Expression;
309 public:
310     LocStep(Element &ownerV_, ExAxis = AXIS_NONE, ExNodeType = EXNODE_NONE);
311     ~LocStep();
312     void set(ExAxis, ExNodeType);
313     eFlag parse(Sit S, Tokenizer&, int&, Bool defaultToo = FALSE);
314     ExAxis ax;
315     ExNodeType ntype;
316     QName ntest;
317     Str piname; //name for the processing-instruction() node test
318     ExprList preds;
319     void speak(Sit S, DStr &s, SpeakMode mode);
320     Bool matchesWithoutPreds(Sit S, NodeHandle v);
321     // eFlag createContextNoPreds(Context *&, int);
322     eFlag shift(Sit S, NodeHandle &v, NodeHandle baseV);
323     Bool positional;
324     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
325     Element &getOwnerElement() {return ownerV;}
326 private:
327     int badPreds;
328     Element &ownerV;
329 };
330
331
332 /**********************************************************
333 E x p r e s s i o n
334 **********************************************************/
335
336 class Element;
337
338 class Expression
339 {
340 public:
341     Expression(Element & owner_, ExFunctor = EXF_NONE);
342     ~Expression();
343     void clearContent();
344     void setLS(ExAxis, ExNodeType);
345     eFlag speak(Sit S, DStr &,SpeakMode);
346     eFlag parse(Sit S, const DStr &, Bool = FALSE, Bool defaultToo = FALSE);
347     eFlag parse(Sit S, Tokenizer&, int, int, Bool defaultToo = FALSE);
348     eFlag eval(Sit S, Expression &, Context *, Bool resolvingGlobals = FALSE);
349     Number tonumber(Sit S);
350 #ifdef ENABLE_JS
351     External toexternal(Sit S);
352 #endif
353     eFlag tostring(Sit S, Str& result);
354     const Str& tostringRef() const;
355     Bool tobool();
356     Context& tonodeset();
357     const Context& tonodesetRef();
358     eFlag matchesPattern(Sit S, Context *, Bool &result);
359     eFlag trueFor(Sit S, Context *, Bool&);
360     //
361     ExType type;
362     ExFunctor functor;
363     ExprList args;
364     eFlag createContext(Sit S, Context *&, int = -1);
365     LocStep *step;
366     int hasPath;
367     void setAtom(Context*);
368     void setAtom(const Number&);
369     void setAtom(const DStr&);
370     void setAtom(Bool);
371 #ifdef ENABLE_JS
372     void setAtom(const External&);
373 #endif
374     Tree* setFragment();
375     Tree* pTree;
376
377     // optimizePositional() sets usesLast and positional
378     // returns: 2 if pred contains last()   ( -> usesLast && positional )
379     //          1 if position() only        ( -> positional )
380     //          0 if neither
381     int optimizePositional(int level);
382
383     // optimizePositionBounds() sets optimizePosition...
384     void optimizePositionBounds();
385
386     // inBounds: 
387     // returns 0 if the position is within bounds, -1 if before, 1 if after
388     int inBounds(int position) const;
389     Element& getOwnerElement() const;
390     Tree& getOwnerTree() const;
391     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
392     Bool containsFunctor(ExFunctor func);
393 protected: 
394 private:
395     union
396     {
397       QName *pName;    //of function or variable
398       Str *patomstring;
399       Bool atombool;
400       Number *patomnumber;
401       Context *patomnodeset;
402 #ifdef ENABLE_JS
403       External *patomexternal;
404 #endif
405     };
406     Bool compareCC(Sit S, ExFunctor, const Context &, const Context &);
407     Bool compareCS(Sit S, ExFunctor, const Context &, const Str &);
408     Bool compareCN(Sit S, ExFunctor, const Context &, const Number &);
409     eFlag compare(Sit S, Bool &, Expression &, ExFunctor);
410     Bool isOp(ExToken, int &);
411     eFlag callOp(Sit S, Expression&, ExprList&);
412     eFlag callFunc(Sit S, Expression&, ExprList&, Context *);
413     eFlag parseBasic(Sit S, Tokenizer &, int, int, Bool defaultToo = FALSE);
414     eFlag parseLP(Sit S, Tokenizer&, int &, Bool dropRoot, Bool defaultToo = FALSE);
415     eFlag matchesSinglePath(Sit S, NodeHandle v, int lastIndex, Bool &result);
416     eFlag matchesSingleStep(Sit S, NodeHandle v, Bool &result);
417     eFlag createLPContextLevel(Sit S, int stepLevel, int stepsCount,
418         NodeHandle base, Context& info, Context *theResult);
419     eFlag createLPContext(Sit S, Context *&, int, NodeHandle globalCurrent = NULL);
420     eFlag createLPContextSum(Sit S, Context *&, NodeHandle globalCurrent = NULL);
421     eFlag getDocument_(Sit S, NodeHandle& newroot, 
422         const Str& location, const Str& baseUri, Processor *proc);
423
424     Bool 
425         isPattern;
426     eFlag patternOK(Sit S);
427     void setAtomNoCopy(Context &);
428
429     // in a predicate, these give the bounds to context positions that
430     // suffice to be processed
431     int optimizePositionFrom,
432         optimizePositionTo;
433
434     // in a predicate, this is true iff the predicate depends on last()
435     Bool usesLast,
436         positional;
437         
438     Element &owner;
439 };
440
441 #endif //ifndef ExprHIncl