1 #ifndef __XPATHTOKEN_H__
2 #define __XPATHTOKEN_H__
4 /**
5 * Phoebe DOM Implementation.
6 *
7 * This is a C++ approximation of the W3C DOM model, which follows
8 * fairly closely the specifications in the various .idl files, copies of
9 * which are provided for reference. Most important is this one:
10 *
11 * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
12 *
13 * Authors:
14 * Bob Jamison
15 *
16 * Copyright (C) 2006 Bob Jamison
17 *
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Lesser General Public
20 * License as published by the Free Software Foundation; either
21 * version 2.1 of the License, or (at your option) any later version.
22 *
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details.
27 *
28 * You should have received a copy of the GNU Lesser General Public
29 * License along with this library; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 */
34 #include "dom.h"
36 #include <math.h>
38 #include <vector>
40 namespace org
41 {
42 namespace w3c
43 {
44 namespace dom
45 {
46 namespace xpath
47 {
49 typedef org::w3c::dom::DOMString DOMString;
52 class TokenExecutor;
55 //########################################################################
56 //# S T A C K I T E M
57 //########################################################################
60 /**
61 * This represents a single value on the evaluation stack
62 */
63 class StackItem
64 {
65 public:
67 /**
68 * Constructor
69 */
70 StackItem()
71 { init(); }
73 /**
74 * Copy constructor
75 */
76 StackItem(const StackItem &other)
77 { assign(other); }
79 /**
80 * Destructor
81 */
82 virtual ~StackItem()
83 {}
85 /**
86 *
87 */
88 StackItem &operator=(const StackItem &other)
89 { assign(other); return *this; }
91 //treat the stack item like an union of string, integer, and double
93 /**
94 * String value
95 */
96 DOMString sval;
98 /**
99 * Integer value
100 */
101 long ival;
103 /**
104 * Double value;
105 */
106 double dval;
109 private:
111 void init()
112 {
113 sval = "";
114 ival = 0;
115 dval = 0.0;
116 }
118 void assign(const StackItem &other)
119 {
120 sval = other.sval;
121 ival = other.ival;
122 dval = other.dval;
123 }
125 };
129 //########################################################################
130 //# X P A T H T O K E N
131 //########################################################################
133 class Token;
134 class Stack;
136 typedef bool (*TokenFunc)(Token &tok, Stack &stack);
139 /**
140 * This is a pseudocode-type class that executes itself on a stack,
141 * much like stack-oriented languages such as FORTH or Postscript.
142 * Each token can pop zero or more tokens off the stack, and push
143 * zero or one token back onto it. When a list of tokens is completed,
144 * a single stack value should be left on the stack.
145 */
146 class Token
147 {
148 public:
150 /**
151 * Token types. Look in xpathtoken.cpp's function table
152 * to see how these types map to their respective
153 * functionalities
154 */
155 typedef enum
156 {
157 //primitives
158 TOK_NOP = 0,
159 TOK_STR,
160 TOK_INT,
161 TOK_FLOAT,
162 //operators
163 TOK_AND,
164 TOK_OR,
165 TOK_MOD,
166 TOK_DIV,
167 TOK_MUL,
168 TOK_DOUBLE_SLASH,
169 TOK_SLASH,
170 TOK_PIPE,
171 TOK_PLUS,
172 TOK_MINUS,
173 TOK_NEG,
174 TOK_EQUALS,
175 TOK_NOT_EQUALS,
176 TOK_LESS_THAN_EQUALS,
177 TOK_LESS_THAN,
178 TOK_GREATER_THAN_EQUALS,
179 TOK_GREATER_THAN,
180 //path types
181 TOK_ABSOLUTE,
182 TOK_RELATIVE,
183 TOK_STEP,
184 TOK_NAME_TEST,
185 TOK_EXPR,
186 TOK_UNION,
187 //axis types
188 TOK_AXIS_ANCESTOR_OR_SELF,
189 TOK_AXIS_ANCESTOR,
190 TOK_AXIS_ATTRIBUTE,
191 TOK_AXIS_CHILD,
192 TOK_AXIS_DESCENDANT_OR_SELF,
193 TOK_AXIS_DESCENDANT,
194 TOK_AXIS_FOLLOWING_SIBLING,
195 TOK_AXIS_FOLLOWING,
196 TOK_AXIS_NAMESPACE,
197 TOK_AXIS_PARENT,
198 TOK_AXIS_PRECEDING_SIBLING,
199 TOK_AXIS_PRECEDING,
200 TOK_AXIS_SELF,
201 //function types
202 TOK_FUNC_LAST,
203 TOK_FUNC_POSITION,
204 TOK_FUNC_COUNT,
205 TOK_FUNC_ID,
206 TOK_FUNC_LOCAL_NAME,
207 TOK_FUNC_NAMESPACE_URI,
208 TOK_FUNC_NAME,
209 TOK_FUNC_STRING,
210 TOK_FUNC_CONCAT,
211 TOK_FUNC_STARTS_WITH,
212 TOK_FUNC_CONTAINS,
213 TOK_FUNC_SUBSTRING_BEFORE,
214 TOK_FUNC_SUBSTRING_AFTER,
215 TOK_FUNC_SUBSTRING,
216 TOK_FUNC_STRING_LENGTH,
217 TOK_FUNC_NORMALIZE_SPACE,
218 TOK_FUNC_TRANSLATE,
219 TOK_FUNC_BOOLEAN,
220 TOK_FUNC_NOT,
221 TOK_FUNC_TRUE,
222 TOK_FUNC_FALSE,
223 TOK_FUNC_LANG,
224 TOK_FUNC_NUMBER,
225 TOK_FUNC_SUM,
226 TOK_FUNC_FLOOR,
227 TOK_FUNC_CEILING,
228 TOK_FUNC_ROUND,
229 } TokenType;
234 /**
235 * Constructor with a NOP default type
236 */
237 Token()
238 { init(); }
240 /**
241 * Constructor with a NOP default type
242 */
243 Token(int typeArg)
244 { init(); type = typeArg; }
246 /**
247 * Constructor with a NOP default type
248 */
249 Token(int typeArg,
250 long ivalArg, double dvalArg, const DOMString &svalArg)
251 {
252 init();
253 type = typeArg,
254 ival = ivalArg;
255 dval = dvalArg;
256 sval = svalArg;
257 }
259 /**
260 * Copy constructor
261 */
262 Token(const Token &other)
263 { assign(other); }
265 /**
266 * Assignment
267 */
268 Token &operator=(const Token &other)
269 { assign(other); return *this; }
271 /**
272 * Destructor
273 */
274 virtual ~Token()
275 {}
277 /**
278 * Return the enumerated TokenType of this token
279 */
280 virtual int getType()
281 { return type; }
283 /**
284 * Return true if the type is one of the Axis types
285 * above;
286 */
287 virtual bool isAxis()
288 {
289 return type>=TOK_AXIS_ANCESTOR_OR_SELF &&
290 type <= TOK_AXIS_SELF;
291 }
292 /**
293 * Return the string TokenType of this token
294 */
295 virtual DOMString getTypeString();
297 /**
298 * Let this token execute itself on the given stack,
299 * possibly adding Nodes to the node list.
300 */
301 virtual bool execute(Stack &stack)
302 {
303 if (tokenFunc)
304 return tokenFunc(*this, stack);
305 return false;
306 }
308 /**
309 * Print the contents of this token
310 */
311 virtual void dump()
312 {
313 printf("%s %s %f %ld\n",
314 getTypeString().c_str(), sval.c_str(), dval, ival);
315 }
317 //treat the token like an union of string, integer, and double
319 /**
320 * String value
321 */
322 DOMString sval;
324 /**
325 * Integer value
326 */
327 long ival;
329 /**
330 * Double value;
331 */
332 double dval;
334 /**
335 *
336 */
337 static Token create(int type, long ival,
338 double dval, const DOMString &sval);
340 /**
341 *
342 */
343 static Token create(int type)
344 { return create(type, 0, 0.0, ""); }
346 /**
347 *
348 */
349 static Token create(int type, long val)
350 { return create(type, val, 0.0, ""); }
352 /**
353 *
354 */
355 static Token create(int type, double val)
356 { return create(type, 0, val, ""); }
358 /**
359 *
360 */
361 static Token create(int type, const DOMString &val)
362 { return create(type, 0, 0.0, val); }
366 protected:
368 /**
369 * The enmerated token type
370 */
371 int type;
373 /**
374 * The function that defines the behaviour of this token
375 */
376 TokenFunc tokenFunc;
379 private:
381 void init()
382 {
383 tokenFunc = NULL;
384 type = TOK_NOP;
385 ival = 0L;
386 dval = 0.0;
387 //sval = ""; //not necessary
388 }
390 void assign(const Token &other)
391 {
392 tokenFunc = other.tokenFunc;
393 type = other.type;
394 sval = other.sval;
395 ival = other.ival;
396 dval = other.dval;
397 }
400 };
403 //########################################################################
404 //# S T A C K
405 //########################################################################
407 /**
408 *
409 */
410 class Stack
411 {
412 public:
414 //# From 2.3, principal type of child axes
415 typedef enum
416 {
417 AXIS_ATTRIBUTE,
418 AXIS_NAMESPACE,
419 AXIS_ELEMENT
420 } PrincipalNodeType;
422 /**
423 * Constructor
424 */
425 Stack(TokenExecutor &par) : parent(par)
426 { clear(); }
428 /**
429 * Copy constructor
430 */
431 Stack(const Stack &other) : parent(other.parent)
432 { assign(other); }
434 /**
435 * Destructor
436 */
437 virtual ~Stack()
438 {}
440 /**
441 *
442 */
443 Stack &operator=(const Stack &other)
444 { assign(other); return *this; }
446 /**
447 *
448 */
449 void push(StackItem &item)
450 { return stackItems.push_back(item); }
452 /**
453 *
454 */
455 StackItem pop()
456 {
457 if (stackItems.size() < 1)
458 {
459 //TODO: error here
460 StackItem item;
461 return item;
462 }
463 std::vector<StackItem>::iterator iter =
464 stackItems.end() - 1;
465 StackItem item = *iter;
466 stackItems.erase(iter);
467 return item;
468 }
470 /**
471 *
472 */
473 virtual void clear()
474 {
475 stackItems.clear();
476 principalNodeType = AXIS_ELEMENT;
477 }
479 private:
481 void assign(const Stack &other)
482 {
483 principalNodeType = other.principalNodeType;
484 stackItems = other.stackItems;
485 }
487 int principalNodeType;
489 std::vector<StackItem> stackItems;
491 TokenExecutor &parent;
493 };
498 //########################################################################
499 //# T O K E N L I S T
500 //########################################################################
502 /**
503 *
504 */
505 class TokenList
506 {
507 public:
509 /**
510 *
511 */
512 TokenList()
513 { init(); }
515 /**
516 *
517 */
518 TokenList(const TokenList &other)
519 { assign(other); }
521 /**
522 *
523 */
524 TokenList &operator=(const TokenList &other)
525 { assign(other); return *this; }
527 /**
528 *
529 */
530 virtual ~TokenList()
531 { }
534 /**
535 *
536 */
537 virtual void add(const Token &token)
538 { tokens.push_back(token); }
540 /**
541 *
542 */
543 virtual std::vector<Token> &getTokens()
544 { return tokens; }
546 /**
547 *
548 */
549 virtual void dump()
550 {
551 for (unsigned int i=0 ; i<tokens.size() ; i++)
552 {
553 Token token = tokens[i];
554 token.dump();
555 }
556 }
558 /**
559 *
560 */
561 virtual void clear()
562 {
563 tokens.clear();
564 }
566 private:
569 void init()
570 {
571 clear();
572 }
574 void assign(const TokenList &other)
575 {
576 tokens = other.tokens;
577 }
579 std::vector<Token> tokens;
582 };
587 //########################################################################
588 //# T O K E N E X E C U T O R
589 //########################################################################
592 /**
593 * A token evaluator, with stack and axis context
594 */
595 class TokenExecutor
596 {
597 public:
599 /**
600 * Constructor
601 */
602 TokenExecutor();
604 /**
605 * Copy constructor
606 */
607 TokenExecutor(const TokenExecutor &other);
609 /**
610 * Destructor
611 */
612 virtual ~TokenExecutor();
614 /**
615 * Assign our values to those of the other
616 */
617 virtual void assign(const TokenExecutor &other);
619 /**
620 * Reset the stack to its original settings
621 */
622 virtual void reset();
624 /**
625 * Execute a list upon a given node. For each Axis encountered,
626 * get the nodes encountered so far, and execute the rest of the
627 * list of tokens upon each of the nodes.
628 */
629 int execute(std::vector<Token> &tokens,
630 int position,
631 const NodePtr node,
632 NodeList &nodeList);
634 /**
635 * Execute a token list on the stack
636 */
637 bool execute(TokenList &list,
638 const NodePtr node,
639 NodeList &result);
641 private:
643 /**
644 *
645 */
646 TokenList tokenList;
648 /**
649 *
650 */
651 NodeList nodeList;
654 };
659 } // namespace xpath
660 } // namespace dom
661 } // namespace w3c
662 } // namespace org
669 #endif /* __XPATHTOKEN_H__ */
670 //########################################################################
671 //# E N D O F F I L E
672 //########################################################################