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 <cstdio>
39 #include <vector>
41 namespace org
42 {
43 namespace w3c
44 {
45 namespace dom
46 {
47 namespace xpath
48 {
50 typedef org::w3c::dom::DOMString DOMString;
53 class TokenExecutor;
56 //########################################################################
57 //# S T A C K I T E M
58 //########################################################################
61 /**
62 * This represents a single value on the evaluation stack
63 */
64 class StackItem
65 {
66 public:
68 /**
69 * Constructor
70 */
71 StackItem()
72 { init(); }
74 /**
75 * Copy constructor
76 */
77 StackItem(const StackItem &other)
78 { assign(other); }
80 /**
81 * Destructor
82 */
83 virtual ~StackItem()
84 {}
86 /**
87 *
88 */
89 StackItem &operator=(const StackItem &other)
90 { assign(other); return *this; }
92 //treat the stack item like an union of string, integer, and double
94 /**
95 * String value
96 */
97 DOMString sval;
99 /**
100 * Integer value
101 */
102 long ival;
104 /**
105 * Double value;
106 */
107 double dval;
110 private:
112 void init()
113 {
114 sval = "";
115 ival = 0;
116 dval = 0.0;
117 }
119 void assign(const StackItem &other)
120 {
121 sval = other.sval;
122 ival = other.ival;
123 dval = other.dval;
124 }
126 };
130 //########################################################################
131 //# X P A T H T O K E N
132 //########################################################################
134 class Token;
135 class Stack;
137 typedef bool (*TokenFunc)(Token &tok, Stack &stack);
140 /**
141 * This is a pseudocode-type class that executes itself on a stack,
142 * much like stack-oriented languages such as FORTH or Postscript.
143 * Each token can pop zero or more tokens off the stack, and push
144 * zero or one token back onto it. When a list of tokens is completed,
145 * a single stack value should be left on the stack.
146 */
147 class Token
148 {
149 public:
151 /**
152 * Token types. Look in xpathtoken.cpp's function table
153 * to see how these types map to their respective
154 * functionalities
155 */
156 typedef enum
157 {
158 //primitives
159 TOK_NOP = 0,
160 TOK_STR,
161 TOK_INT,
162 TOK_FLOAT,
163 //operators
164 TOK_AND,
165 TOK_OR,
166 TOK_MOD,
167 TOK_DIV,
168 TOK_MUL,
169 TOK_DOUBLE_SLASH,
170 TOK_SLASH,
171 TOK_PIPE,
172 TOK_PLUS,
173 TOK_MINUS,
174 TOK_NEG,
175 TOK_EQUALS,
176 TOK_NOT_EQUALS,
177 TOK_LESS_THAN_EQUALS,
178 TOK_LESS_THAN,
179 TOK_GREATER_THAN_EQUALS,
180 TOK_GREATER_THAN,
181 //path types
182 TOK_ABSOLUTE,
183 TOK_RELATIVE,
184 TOK_STEP,
185 TOK_NAME_TEST,
186 TOK_EXPR,
187 TOK_UNION,
188 //axis types
189 TOK_AXIS_ANCESTOR_OR_SELF,
190 TOK_AXIS_ANCESTOR,
191 TOK_AXIS_ATTRIBUTE,
192 TOK_AXIS_CHILD,
193 TOK_AXIS_DESCENDANT_OR_SELF,
194 TOK_AXIS_DESCENDANT,
195 TOK_AXIS_FOLLOWING_SIBLING,
196 TOK_AXIS_FOLLOWING,
197 TOK_AXIS_NAMESPACE,
198 TOK_AXIS_PARENT,
199 TOK_AXIS_PRECEDING_SIBLING,
200 TOK_AXIS_PRECEDING,
201 TOK_AXIS_SELF,
202 //function types
203 TOK_FUNC_LAST,
204 TOK_FUNC_POSITION,
205 TOK_FUNC_COUNT,
206 TOK_FUNC_ID,
207 TOK_FUNC_LOCAL_NAME,
208 TOK_FUNC_NAMESPACE_URI,
209 TOK_FUNC_NAME,
210 TOK_FUNC_STRING,
211 TOK_FUNC_CONCAT,
212 TOK_FUNC_STARTS_WITH,
213 TOK_FUNC_CONTAINS,
214 TOK_FUNC_SUBSTRING_BEFORE,
215 TOK_FUNC_SUBSTRING_AFTER,
216 TOK_FUNC_SUBSTRING,
217 TOK_FUNC_STRING_LENGTH,
218 TOK_FUNC_NORMALIZE_SPACE,
219 TOK_FUNC_TRANSLATE,
220 TOK_FUNC_BOOLEAN,
221 TOK_FUNC_NOT,
222 TOK_FUNC_TRUE,
223 TOK_FUNC_FALSE,
224 TOK_FUNC_LANG,
225 TOK_FUNC_NUMBER,
226 TOK_FUNC_SUM,
227 TOK_FUNC_FLOOR,
228 TOK_FUNC_CEILING,
229 TOK_FUNC_ROUND,
230 } TokenType;
235 /**
236 * Constructor with a NOP default type
237 */
238 Token()
239 { init(); }
241 /**
242 * Constructor with a NOP default type
243 */
244 Token(int typeArg)
245 { init(); type = typeArg; }
247 /**
248 * Constructor with a NOP default type
249 */
250 Token(int typeArg,
251 long ivalArg, double dvalArg, const DOMString &svalArg)
252 {
253 init();
254 type = typeArg,
255 ival = ivalArg;
256 dval = dvalArg;
257 sval = svalArg;
258 }
260 /**
261 * Copy constructor
262 */
263 Token(const Token &other)
264 { assign(other); }
266 /**
267 * Assignment
268 */
269 Token &operator=(const Token &other)
270 { assign(other); return *this; }
272 /**
273 * Destructor
274 */
275 virtual ~Token()
276 {}
278 /**
279 * Return the enumerated TokenType of this token
280 */
281 virtual int getType()
282 { return type; }
284 /**
285 * Return true if the type is one of the Axis types
286 * above;
287 */
288 virtual bool isAxis()
289 {
290 return type>=TOK_AXIS_ANCESTOR_OR_SELF &&
291 type <= TOK_AXIS_SELF;
292 }
293 /**
294 * Return the string TokenType of this token
295 */
296 virtual DOMString getTypeString();
298 /**
299 * Let this token execute itself on the given stack,
300 * possibly adding Nodes to the node list.
301 */
302 virtual bool execute(Stack &stack)
303 {
304 if (tokenFunc)
305 return tokenFunc(*this, stack);
306 return false;
307 }
309 /**
310 * Print the contents of this token
311 */
312 virtual void dump()
313 {
314 printf("%s %s %f %ld\n",
315 getTypeString().c_str(), sval.c_str(), dval, ival);
316 }
318 //treat the token like an union of string, integer, and double
320 /**
321 * String value
322 */
323 DOMString sval;
325 /**
326 * Integer value
327 */
328 long ival;
330 /**
331 * Double value;
332 */
333 double dval;
335 /**
336 *
337 */
338 static Token create(int type, long ival,
339 double dval, const DOMString &sval);
341 /**
342 *
343 */
344 static Token create(int type)
345 { return create(type, 0, 0.0, ""); }
347 /**
348 *
349 */
350 static Token create(int type, long val)
351 { return create(type, val, 0.0, ""); }
353 /**
354 *
355 */
356 static Token create(int type, double val)
357 { return create(type, 0, val, ""); }
359 /**
360 *
361 */
362 static Token create(int type, const DOMString &val)
363 { return create(type, 0, 0.0, val); }
367 protected:
369 /**
370 * The enmerated token type
371 */
372 int type;
374 /**
375 * The function that defines the behaviour of this token
376 */
377 TokenFunc tokenFunc;
380 private:
382 void init()
383 {
384 tokenFunc = NULL;
385 type = TOK_NOP;
386 ival = 0L;
387 dval = 0.0;
388 //sval = ""; //not necessary
389 }
391 void assign(const Token &other)
392 {
393 tokenFunc = other.tokenFunc;
394 type = other.type;
395 sval = other.sval;
396 ival = other.ival;
397 dval = other.dval;
398 }
401 };
404 //########################################################################
405 //# S T A C K
406 //########################################################################
408 /**
409 *
410 */
411 class Stack
412 {
413 public:
415 //# From 2.3, principal type of child axes
416 typedef enum
417 {
418 AXIS_ATTRIBUTE,
419 AXIS_NAMESPACE,
420 AXIS_ELEMENT
421 } PrincipalNodeType;
423 /**
424 * Constructor
425 */
426 Stack(TokenExecutor &par) : parent(par)
427 { clear(); }
429 /**
430 * Copy constructor
431 */
432 Stack(const Stack &other) : parent(other.parent)
433 { assign(other); }
435 /**
436 * Destructor
437 */
438 virtual ~Stack()
439 {}
441 /**
442 *
443 */
444 Stack &operator=(const Stack &other)
445 { assign(other); return *this; }
447 /**
448 *
449 */
450 void push(StackItem &item)
451 { return stackItems.push_back(item); }
453 /**
454 *
455 */
456 StackItem pop()
457 {
458 if (stackItems.size() < 1)
459 {
460 //TODO: error here
461 StackItem item;
462 return item;
463 }
464 std::vector<StackItem>::iterator iter =
465 stackItems.end() - 1;
466 StackItem item = *iter;
467 stackItems.erase(iter);
468 return item;
469 }
471 /**
472 *
473 */
474 virtual void clear()
475 {
476 stackItems.clear();
477 principalNodeType = AXIS_ELEMENT;
478 }
480 private:
482 void assign(const Stack &other)
483 {
484 principalNodeType = other.principalNodeType;
485 stackItems = other.stackItems;
486 }
488 int principalNodeType;
490 std::vector<StackItem> stackItems;
492 TokenExecutor &parent;
494 };
499 //########################################################################
500 //# T O K E N L I S T
501 //########################################################################
503 /**
504 *
505 */
506 class TokenList
507 {
508 public:
510 /**
511 *
512 */
513 TokenList()
514 { init(); }
516 /**
517 *
518 */
519 TokenList(const TokenList &other)
520 { assign(other); }
522 /**
523 *
524 */
525 TokenList &operator=(const TokenList &other)
526 { assign(other); return *this; }
528 /**
529 *
530 */
531 virtual ~TokenList()
532 { }
535 /**
536 *
537 */
538 virtual void add(const Token &token)
539 { tokens.push_back(token); }
541 /**
542 *
543 */
544 virtual std::vector<Token> &getTokens()
545 { return tokens; }
547 /**
548 *
549 */
550 virtual void dump()
551 {
552 for (unsigned int i=0 ; i<tokens.size() ; i++)
553 {
554 Token token = tokens[i];
555 token.dump();
556 }
557 }
559 /**
560 *
561 */
562 virtual void clear()
563 {
564 tokens.clear();
565 }
567 private:
570 void init()
571 {
572 clear();
573 }
575 void assign(const TokenList &other)
576 {
577 tokens = other.tokens;
578 }
580 std::vector<Token> tokens;
583 };
588 //########################################################################
589 //# T O K E N E X E C U T O R
590 //########################################################################
593 /**
594 * A token evaluator, with stack and axis context
595 */
596 class TokenExecutor
597 {
598 public:
600 /**
601 * Constructor
602 */
603 TokenExecutor();
605 /**
606 * Copy constructor
607 */
608 TokenExecutor(const TokenExecutor &other);
610 /**
611 * Destructor
612 */
613 virtual ~TokenExecutor();
615 /**
616 * Assign our values to those of the other
617 */
618 virtual void assign(const TokenExecutor &other);
620 /**
621 * Reset the stack to its original settings
622 */
623 virtual void reset();
625 /**
626 * Execute a list upon a given node. For each Axis encountered,
627 * get the nodes encountered so far, and execute the rest of the
628 * list of tokens upon each of the nodes.
629 */
630 int execute(std::vector<Token> &tokens,
631 int position,
632 const NodePtr node,
633 NodeList &nodeList);
635 /**
636 * Execute a token list on the stack
637 */
638 bool execute(TokenList &list,
639 const NodePtr node,
640 NodeList &result);
642 private:
644 /**
645 *
646 */
647 TokenList tokenList;
649 /**
650 *
651 */
652 NodeList nodeList;
655 };
660 } // namespace xpath
661 } // namespace dom
662 } // namespace w3c
663 } // namespace org
670 #endif /* __XPATHTOKEN_H__ */
671 //########################################################################
672 //# E N D O F F I L E
673 //########################################################################