Attachment #38595: To be super-reviewed (diff -u -N) for bug #75102

View | Details | Raw Unified | Return to bug 75102
Collapse All | Expand All

(-)Makefile.in (-2 / +3 lines)
Line     Link Here 
 Lines 77-88    Link Here 
77
  ../source/xpath/BooleanResult.o \
77
  ../source/xpath/BooleanResult.o \
78
  ../source/xpath/ElementExpr.o \
78
  ../source/xpath/ElementExpr.o \
79
  ../source/xpath/ErrorFunctionCall.o \
79
  ../source/xpath/ErrorFunctionCall.o \
80
  ../source/xpath/Expr.o \
80
  ../source/xpath/ExprLexer.o \
81
  ../source/xpath/ExprLexer.o \
82
  ../source/xpath/ExprLexerChars.o \
81
  ../source/xpath/ExprParser.o \
83
  ../source/xpath/ExprParser.o \
82
  ../source/xpath/ExtensionFunctionCall.o \
84
  ../source/xpath/ExtensionFunctionCall.o \
83
  ../source/xpath/FilterExpr.o \
85
  ../source/xpath/FilterExpr.o \
84
  ../source/xpath/FunctionCall.o \
86
  ../source/xpath/FunctionCall.o \
85
  ../source/xpath/IdentityExpr.o \
86
  ../source/xpath/LocationStep.o \
87
  ../source/xpath/LocationStep.o \
87
  ../source/xpath/MultiplicativeExpr.o \
88
  ../source/xpath/MultiplicativeExpr.o \
88
  ../source/xpath/NodeSet.o \
89
  ../source/xpath/NodeSet.o \
 Lines 91-97    Link Here 
91
  ../source/xpath/NumberExpr.o \
92
  ../source/xpath/NumberExpr.o \
92
  ../source/xpath/NumberFunctionCall.o \
93
  ../source/xpath/NumberFunctionCall.o \
93
  ../source/xpath/NumberResult.o \
94
  ../source/xpath/NumberResult.o \
94
  ../source/xpath/ParentExpr.o \
95
  ../source/xpath/PathExpr.o \
95
  ../source/xpath/PathExpr.o \
96
  ../source/xpath/PredicateList.o \
96
  ../source/xpath/PredicateList.o \
97
  ../source/xpath/RelationalExpr.o \
97
  ../source/xpath/RelationalExpr.o \
 Lines 101-106    Link Here 
101
  ../source/xpath/StringResult.o \
101
  ../source/xpath/StringResult.o \
102
  ../source/xpath/TextExpr.o \
102
  ../source/xpath/TextExpr.o \
103
  ../source/xpath/UnionExpr.o \
103
  ../source/xpath/UnionExpr.o \
104
  ../source/xpath/UnaryExpr.o \
104
  ../source/xpath/VariableRefExpr.o \
105
  ../source/xpath/VariableRefExpr.o \
105
  ../source/xpath/XPathNames.o \
106
  ../source/xpath/XPathNames.o \
106
  ../source/xpath/XPathProcessor.o \
107
  ../source/xpath/XPathProcessor.o \
(-)makefile.win (-2 / +3 lines)
Line     Link Here 
 Lines 72-83    Link Here 
72
	..\source\xpath\$(OBJDIR)\BooleanResult.obj \
72
	..\source\xpath\$(OBJDIR)\BooleanResult.obj \
73
	..\source\xpath\$(OBJDIR)\ElementExpr.obj \
73
	..\source\xpath\$(OBJDIR)\ElementExpr.obj \
74
	..\source\xpath\$(OBJDIR)\ErrorFunctionCall.obj \
74
	..\source\xpath\$(OBJDIR)\ErrorFunctionCall.obj \
75
	..\source\xpath\$(OBJDIR)\Expr.obj \
75
	..\source\xpath\$(OBJDIR)\ExprLexer.obj \
76
	..\source\xpath\$(OBJDIR)\ExprLexer.obj \
77
	..\source\xpath\$(OBJDIR)\ExprLexerChars.obj \
76
	..\source\xpath\$(OBJDIR)\ExprParser.obj \
78
	..\source\xpath\$(OBJDIR)\ExprParser.obj \
77
	..\source\xpath\$(OBJDIR)\ExtensionFunctionCall.obj \
79
	..\source\xpath\$(OBJDIR)\ExtensionFunctionCall.obj \
78
	..\source\xpath\$(OBJDIR)\FilterExpr.obj \
80
	..\source\xpath\$(OBJDIR)\FilterExpr.obj \
79
	..\source\xpath\$(OBJDIR)\FunctionCall.obj \
81
	..\source\xpath\$(OBJDIR)\FunctionCall.obj \
80
	..\source\xpath\$(OBJDIR)\IdentityExpr.obj \
81
	..\source\xpath\$(OBJDIR)\LocationStep.obj \
82
	..\source\xpath\$(OBJDIR)\LocationStep.obj \
82
	..\source\xpath\$(OBJDIR)\MultiplicativeExpr.obj \
83
	..\source\xpath\$(OBJDIR)\MultiplicativeExpr.obj \
83
	..\source\xpath\$(OBJDIR)\NodeSet.obj \
84
	..\source\xpath\$(OBJDIR)\NodeSet.obj \
 Lines 86-92    Link Here 
86
	..\source\xpath\$(OBJDIR)\NumberExpr.obj \
87
	..\source\xpath\$(OBJDIR)\NumberExpr.obj \
87
	..\source\xpath\$(OBJDIR)\NumberFunctionCall.obj \
88
	..\source\xpath\$(OBJDIR)\NumberFunctionCall.obj \
88
	..\source\xpath\$(OBJDIR)\NumberResult.obj \
89
	..\source\xpath\$(OBJDIR)\NumberResult.obj \
89
	..\source\xpath\$(OBJDIR)\ParentExpr.obj \
90
	..\source\xpath\$(OBJDIR)\PathExpr.obj \
90
	..\source\xpath\$(OBJDIR)\PathExpr.obj \
91
	..\source\xpath\$(OBJDIR)\PredicateList.obj \
91
	..\source\xpath\$(OBJDIR)\PredicateList.obj \
92
	..\source\xpath\$(OBJDIR)\RelationalExpr.obj \
92
	..\source\xpath\$(OBJDIR)\RelationalExpr.obj \
 Lines 96-101    Link Here 
96
	..\source\xpath\$(OBJDIR)\StringResult.obj \
96
	..\source\xpath\$(OBJDIR)\StringResult.obj \
97
	..\source\xpath\$(OBJDIR)\TextExpr.obj \
97
	..\source\xpath\$(OBJDIR)\TextExpr.obj \
98
	..\source\xpath\$(OBJDIR)\UnionExpr.obj \
98
	..\source\xpath\$(OBJDIR)\UnionExpr.obj \
99
	..\source\xpath\$(OBJDIR)\UnaryExpr.obj \
99
	..\source\xpath\$(OBJDIR)\VariableRefExpr.obj \
100
	..\source\xpath\$(OBJDIR)\VariableRefExpr.obj \
100
	..\source\xpath\$(OBJDIR)\XPathNames.obj \
101
	..\source\xpath\$(OBJDIR)\XPathNames.obj \
101
	..\source\xpath\$(OBJDIR)\XPathProcessor.obj \
102
	..\source\xpath\$(OBJDIR)\XPathProcessor.obj \
(-)Makefile.in (-2 / +3 lines)
Line     Link Here 
 Lines 70-81    Link Here 
70
  ../xpath/BooleanResult.o \
70
  ../xpath/BooleanResult.o \
71
  ../xpath/ElementExpr.o \
71
  ../xpath/ElementExpr.o \
72
  ../xpath/ErrorFunctionCall.o \
72
  ../xpath/ErrorFunctionCall.o \
73
  ../xpath/Expr.o \
73
  ../xpath/ExprLexer.o \
74
  ../xpath/ExprLexer.o \
75
  ../xpath/ExprLexerChars.o \
74
  ../xpath/ExprParser.o \
76
  ../xpath/ExprParser.o \
75
  ../xpath/ExtensionFunctionCall.o \
77
  ../xpath/ExtensionFunctionCall.o \
76
  ../xpath/FilterExpr.o \
78
  ../xpath/FilterExpr.o \
77
  ../xpath/FunctionCall.o \
79
  ../xpath/FunctionCall.o \
78
  ../xpath/IdentityExpr.o \
79
  ../xpath/LocationStep.o \
80
  ../xpath/LocationStep.o \
80
  ../xpath/MultiplicativeExpr.o \
81
  ../xpath/MultiplicativeExpr.o \
81
  ../xpath/NodeSet.o \
82
  ../xpath/NodeSet.o \
 Lines 83-89    Link Here 
83
  ../xpath/NumberExpr.o \
84
  ../xpath/NumberExpr.o \
84
  ../xpath/NumberFunctionCall.o \
85
  ../xpath/NumberFunctionCall.o \
85
  ../xpath/NumberResult.o \
86
  ../xpath/NumberResult.o \
86
  ../xpath/ParentExpr.o \
87
  ../xpath/PathExpr.o \
87
  ../xpath/PathExpr.o \
88
  ../xpath/PredicateList.o \
88
  ../xpath/PredicateList.o \
89
  ../xpath/RelationalExpr.o \
89
  ../xpath/RelationalExpr.o \
 Lines 93-98    Link Here 
93
  ../xpath/StringResult.o \
93
  ../xpath/StringResult.o \
94
  ../xpath/TextExpr.o \
94
  ../xpath/TextExpr.o \
95
  ../xpath/UnionExpr.o \
95
  ../xpath/UnionExpr.o \
96
  ../xpath/UnaryExpr.o \
96
  ../xpath/VariableRefExpr.o \
97
  ../xpath/VariableRefExpr.o \
97
  ../xpath/XPathNames.o \
98
  ../xpath/XPathNames.o \
98
  ../xml/XMLUtils.o \
99
  ../xml/XMLUtils.o \
(-)makefile.win (-2 / +3 lines)
Line     Link Here 
 Lines 68-79    Link Here 
68
  ../xpath/$(OBJDIR)/BooleanResult.obj \
68
  ../xpath/$(OBJDIR)/BooleanResult.obj \
69
  ../xpath/$(OBJDIR)/ElementExpr.obj \
69
  ../xpath/$(OBJDIR)/ElementExpr.obj \
70
  ../xpath/$(OBJDIR)/ErrorFunctionCall.obj \
70
  ../xpath/$(OBJDIR)/ErrorFunctionCall.obj \
71
  ../xpath/$(OBJDIR)/Expr.obj \
71
  ../xpath/$(OBJDIR)/ExprLexer.obj \
72
  ../xpath/$(OBJDIR)/ExprLexer.obj \
73
  ../xpath/$(OBJDIR)/ExprLexerChars.obj \
72
  ../xpath/$(OBJDIR)/ExprParser.obj \
74
  ../xpath/$(OBJDIR)/ExprParser.obj \
73
  ../xpath/$(OBJDIR)/ExtensionFunctionCall.obj \
75
  ../xpath/$(OBJDIR)/ExtensionFunctionCall.obj \
74
  ../xpath/$(OBJDIR)/FilterExpr.obj \
76
  ../xpath/$(OBJDIR)/FilterExpr.obj \
75
  ../xpath/$(OBJDIR)/FunctionCall.obj \
77
  ../xpath/$(OBJDIR)/FunctionCall.obj \
76
  ../xpath/$(OBJDIR)/IdentityExpr.obj \
77
  ../xpath/$(OBJDIR)/LocationStep.obj \
78
  ../xpath/$(OBJDIR)/LocationStep.obj \
78
  ../xpath/$(OBJDIR)/MultiplicativeExpr.obj \
79
  ../xpath/$(OBJDIR)/MultiplicativeExpr.obj \
79
  ../xpath/$(OBJDIR)/NodeSet.obj \
80
  ../xpath/$(OBJDIR)/NodeSet.obj \
 Lines 81-87    Link Here 
81
  ../xpath/$(OBJDIR)/NumberExpr.obj \
82
  ../xpath/$(OBJDIR)/NumberExpr.obj \
82
  ../xpath/$(OBJDIR)/NumberFunctionCall.obj \
83
  ../xpath/$(OBJDIR)/NumberFunctionCall.obj \
83
  ../xpath/$(OBJDIR)/NumberResult.obj \
84
  ../xpath/$(OBJDIR)/NumberResult.obj \
84
  ../xpath/$(OBJDIR)/ParentExpr.obj \
85
  ../xpath/$(OBJDIR)/PathExpr.obj \
85
  ../xpath/$(OBJDIR)/PathExpr.obj \
86
  ../xpath/$(OBJDIR)/PredicateList.obj \
86
  ../xpath/$(OBJDIR)/PredicateList.obj \
87
  ../xpath/$(OBJDIR)/RelationalExpr.obj \
87
  ../xpath/$(OBJDIR)/RelationalExpr.obj \
 Lines 91-96    Link Here 
91
  ../xpath/$(OBJDIR)/StringResult.obj \
91
  ../xpath/$(OBJDIR)/StringResult.obj \
92
  ../xpath/$(OBJDIR)/TextExpr.obj \
92
  ../xpath/$(OBJDIR)/TextExpr.obj \
93
  ../xpath/$(OBJDIR)/UnionExpr.obj \
93
  ../xpath/$(OBJDIR)/UnionExpr.obj \
94
  ../xpath/$(OBJDIR)/UnaryExpr.obj \
94
  ../xpath/$(OBJDIR)/VariableRefExpr.obj \
95
  ../xpath/$(OBJDIR)/VariableRefExpr.obj \
95
  ../xpath/$(OBJDIR)/XPathNames.obj \
96
  ../xpath/$(OBJDIR)/XPathNames.obj \
96
  ../xml/$(OBJDIR)/XMLUtils.obj \
97
  ../xml/$(OBJDIR)/XMLUtils.obj \
(-)BasicNodeExpr.cpp (-9 / +22 lines)
Line     Link Here 
 Lines 38-43    Link Here 
38
**/
38
**/
39
BasicNodeExpr::BasicNodeExpr() {
39
BasicNodeExpr::BasicNodeExpr() {
40
    this->type = NodeExpr::NODE_EXPR;
40
    this->type = NodeExpr::NODE_EXPR;
41
    nodeNameSet = MB_FALSE;
41
} //-- BasicNodeExpr
42
} //-- BasicNodeExpr
42
43
43
/**
44
/**
 Lines 45-50    Link Here 
45
**/
46
**/
46
BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType) {
47
BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType) {
47
    this->type = nodeExprType;
48
    this->type = nodeExprType;
49
    nodeNameSet = MB_FALSE;
48
} //-- BasicNodeExpr
50
} //-- BasicNodeExpr
49
51
50
/**
52
/**
 Lines 56-61    Link Here 
56
 //- Public Methods -/
58
 //- Public Methods -/
57
//------------------/
59
//------------------/
58
60
61
void BasicNodeExpr::setNodeName(const String& name) {
62
    this->nodeName = name;
63
    nodeNameSet = MB_TRUE;
64
}
65
66
  //-----------------------------/
67
 //- Methods from NodeExpr.cpp -/
68
//-----------------------------/
69
59
/**
70
/**
60
 * Evaluates this Expr based on the given context node and processor state
71
 * Evaluates this Expr based on the given context node and processor state
61
 * @param context the context node for evaluation of this Expr
72
 * @param context the context node for evaluation of this Expr
 Lines 75-91    Link Here 
75
    return nodeSet;
86
    return nodeSet;
76
} //-- evaluate
87
} //-- evaluate
77
88
78
  //-----------------------------/
79
 //- Methods from NodeExpr.cpp -/
80
//-----------------------------/
81
82
/**
89
/**
83
 * Returns the default priority of this Pattern based on the given Node,
90
 * Returns the default priority of this Expr based on the given Node,
84
 * context Node, and ContextState.
91
 * context Node, and ContextState.
85
 * If this pattern does not match the given Node under the current context Node and
86
 * ContextState then Negative Infinity is returned.
87
**/
92
**/
88
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
93
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
94
    if (nodeNameSet) return 0;
89
    return -0.5;
95
    return -0.5;
90
} //-- getDefaultPriority
96
} //-- getDefaultPriority
91
97
 Lines 107-113    Link Here 
107
        case NodeExpr::COMMENT_EXPR:
113
        case NodeExpr::COMMENT_EXPR:
108
            return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
114
            return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
109
        case NodeExpr::PI_EXPR :
115
        case NodeExpr::PI_EXPR :
110
            return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE);
116
            return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE &&
117
                            !nodeNameSet || nodeName.isEqual(node->getNodeName()));
111
        default: //-- node()
118
        default: //-- node()
112
            if(node->getNodeType() == Node::TEXT_NODE)
119
            if(node->getNodeType() == Node::TEXT_NODE)
113
                return !cs->isStripSpaceAllowed(node);
120
                return !cs->isStripSpaceAllowed(node);
 Lines 133-139    Link Here 
133
            dest.append("comment()");
140
            dest.append("comment()");
134
            break;
141
            break;
135
        case NodeExpr::PI_EXPR :
142
        case NodeExpr::PI_EXPR :
136
            dest.append("processing-instruction()");
143
            dest.append("processing-instruction(");
144
            if (nodeNameSet) {
145
                dest.append('\'');
146
                dest.append(nodeName);
147
                dest.append('\'');
148
            }
149
            dest.append(')');
137
            break;
150
            break;
138
        default: //-- node()
151
        default: //-- node()
139
            dest.append("node()");
152
            dest.append("node()");
(-)source/xpath/Expr.cpp (+48 lines)
Added Link Here 
Added Link Here 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 Initial Developer of the Original Code is Jonas Sicking.
13
 * Portions created by Jonas Sicking are Copyright (C) 2001, Jonas Sicking.
14
 * All rights reserved.
15
 *
16
 * Contributor(s):
17
 * Jonas Sicking, sicking@bigfoot.com
18
 *   -- original author.
19
 */
20
 
21
#include "Expr.h"
22
23
Expr::~Expr() {
24
} //-- ~Expr
25
26
/**
27
 * Determines whether this Expr matches the given node within
28
 * the given context
29
**/
30
MBool Expr::matches(Node* node, Node* context, ContextState* cs)
31
{
32
    #ifndef TX_EXE
33
    NS_ASSERTION(0,"Expr::matches() called");
34
    #endif
35
    return MB_FALSE;
36
} //-- matches
37
38
/**
39
 * Returns the default priority of this Expr based on the given Node,
40
 * context Node, and ContextState.
41
**/
42
double Expr::getDefaultPriority(Node* node, Node* context, ContextState* cs)
43
{
44
    #ifndef TX_EXE
45
    NS_ASSERTION(0,"Expr::matches() called");
46
    #endif
47
    return 0;
48
} //-- getDefaultPriority
(-)Expr.h (-636 / +120 lines)
Line     Link Here 
 Lines 24-29    Link Here 
24
 *   -- 19990806
24
 *   -- 19990806
25
 *     - changed constant short declarations in many of the classes
25
 *     - changed constant short declarations in many of the classes
26
 *       with enumerations, commented with //--LF
26
 *       with enumerations, commented with //--LF
27
 * Jonas Sicking, sicking@bigfoot.com
28
 *   -- removal of Patterns and some restructuring
29
 *      in the class set
27
 *
30
 *
28
 * $Id: Expr.h,v 1.13 2001/05/12 09:54:15 nisheeth%netscape.com Exp $
31
 * $Id: Expr.h,v 1.13 2001/05/12 09:54:15 nisheeth%netscape.com Exp $
29
 */
32
 */
 Lines 52-57    Link Here 
52
//necessary prototypes
55
//necessary prototypes
53
class FunctionCall;
56
class FunctionCall;
54
57
58
typedef class Expr Pattern;
59
typedef class Expr PatternExpr;
60
61
55
/**
62
/**
56
 * The expression context and state class used when evaluating XPath Expressions.
63
 * The expression context and state class used when evaluating XPath Expressions.
57
**/
64
**/
 Lines 115-121    Link Here 
115
    /**
122
    /**
116
     * Virtual destructor, important for subclasses
123
     * Virtual destructor, important for subclasses
117
    **/
124
    **/
118
    virtual ~Expr() {};
125
    virtual ~Expr();
119
126
120
    /**
127
    /**
121
     * Evaluates this Expr based on the given context node and processor state
128
     * Evaluates this Expr based on the given context node and processor state
 Lines 127-132    Link Here 
127
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
134
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
128
135
129
    /**
136
    /**
137
     * Determines whether this Expr matches the given node within
138
     * the given context
139
    **/
140
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
141
142
    /**
143
     * Returns the default priority of this Expr based on the given Node,
144
     * context Node, and ContextState.
145
    **/
146
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
147
148
    /**
130
     * Returns the String representation of this Expr.
149
     * Returns the String representation of this Expr.
131
     * @param dest the String to use when creating the String
150
     * @param dest the String to use when creating the String
132
     * representation. The String representation will be appended to
151
     * representation. The String representation will be appended to
 Lines 138-144    Link Here 
138
157
139
}; //-- Expr
158
}; //-- Expr
140
159
141
142
/**
160
/**
143
 * This class represents a FunctionCall as defined by the XPath 1.0
161
 * This class represents a FunctionCall as defined by the XPath 1.0
144
 * Recommendation.
162
 * Recommendation.
 Lines 149-171    Link Here 
149
167
150
    static const String INVALID_PARAM_COUNT;
168
    static const String INVALID_PARAM_COUNT;
151
169
152
153
    virtual ~FunctionCall();
170
    virtual ~FunctionCall();
154
171
155
    /**
172
    /**
156
     * Adds the given parameter to this FunctionCall's parameter list
173
     * Virtual methods from Expr 
157
     * @param expr the Expr to add to this FunctionCall's parameter list
158
    **/
174
    **/
159
    void addParam(Expr* expr);
175
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
176
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
177
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
178
    virtual void toString(String& dest);
160
179
161
    /**
180
    /**
162
     * Evaluates this Expr based on the given context node and processor state
181
     * Adds the given parameter to this FunctionCall's parameter list
163
     * @param context the context node for evaluation of this Expr
182
     * @param expr the Expr to add to this FunctionCall's parameter list
164
     * @param ps the ContextState containing the stack information needed
165
     * for evaluation
166
     * @return the result of the evaluation
167
    **/
183
    **/
168
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
184
    void addParam(Expr* expr);
169
185
170
    /**
186
    /**
171
     * Returns the name of this FunctionCall
187
     * Returns the name of this FunctionCall
 Lines 184-198    Link Here 
184
     * @param name the name of this Function
200
     * @param name the name of this Function
185
    **/
201
    **/
186
    void setName(const String& name);
202
    void setName(const String& name);
187
    /**
188
     * Returns the String representation of this Pattern.
189
     * @param dest the String to use when creating the String
190
     * representation. The String representation will be appended to
191
     * any data in the destination String, to allow cascading calls to
192
     * other #toString() methods for Expressions.
193
     * @return the String representation of this Pattern.
194
    **/
195
    virtual void toString(String& dest);
196
203
197
204
198
protected:
205
protected:
 Lines 221-317    Link Here 
221
    String name;
228
    String name;
222
}; //-- FunctionCall
229
}; //-- FunctionCall
223
230
224
/**
225
 * A base Pattern class
226
**/
227
class Pattern {
228
229
public:
230
231
    /**
232
     * Virtual destructor, important for subclasses
233
    **/
234
    virtual ~Pattern() {};
235
236
    /**
237
     * Returns the default priority of this Pattern based on the given Node,
238
     * context Node, and ContextState.
239
     * If this pattern does not match the given Node under the current context Node and
240
     * ContextState then Negative Infinity is returned.
241
    **/
242
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
243
244
    /**
245
     * Determines whether this Pattern matches the given node within
246
     * the given context
247
    **/
248
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
249
250
251
    /**
252
     * Returns the String representation of this Pattern.
253
     * @param dest the String to use when creating the String
254
     * representation. The String representation will be appended to
255
     * any data in the destination String, to allow cascading calls to
256
     * other #toString() methods for Expressions.
257
     * @return the String representation of this Pattern.
258
    **/
259
    virtual void toString(String& dest) = 0;
260
261
}; //-- Pattern
262
231
263
264
/**
232
/**
265
 * A Base class for all Expressions and Patterns
266
**/
267
class PatternExpr :
268
    public Expr,
269
    public Pattern
270
{
271
272
public:
273
274
    /**
275
     * Virtual destructor, important for subclasses
276
    **/
277
    virtual ~PatternExpr() {};
278
279
    /**
280
     * Evaluates this Expr based on the given context node and processor state
281
     * @param context the context node for evaluation of this Expr
282
     * @param ps the ContextState containing the stack information needed
283
     * for evaluation
284
     * @return the result of the evaluation
285
    **/
286
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
287
288
    /**
289
     * Returns the default priority of this Pattern based on the given Node,
290
     * context Node, and ContextState.
291
     * If this pattern does not match the given Node under the current context Node and
292
     * ContextState then Negative Infinity is returned.
293
    **/
294
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
295
296
    /**
297
     * Determines whether this PatternExpr matches the given node within
298
     * the given context
299
    **/
300
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
301
302
    /**
303
     * Returns the String representation of this PatternExpr.
304
     * @param dest the String to use when creating the String
305
     * representation. The String representation will be appended to
306
     * any data in the destination String, to allow cascading calls to
307
     * other #toString() methods for Expressions.
308
     * @return the String representation of this PatternExpr.
309
    **/
310
    virtual void toString(String& dest) = 0;
311
312
}; //-- PatternExpr
313
314
/**
315
 * Represents an AttributeValueTemplate
233
 * Represents an AttributeValueTemplate
316
**/
234
**/
317
class AttributeValueTemplate: public Expr {
235
class AttributeValueTemplate: public Expr {
 Lines 328-349    Link Here 
328
    void addExpr(Expr* expr);
246
    void addExpr(Expr* expr);
329
247
330
    /**
248
    /**
331
     * Evaluates this Expr based on the given context node and processor state
249
     * Virtual methods from Expr 
332
     * @param context the context node for evaluation of this Expr
333
     * @param ps the ContextState containing the stack information needed
334
     * for evaluation
335
     * @return the result of the evaluation
336
    **/
250
    **/
337
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
251
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
338
339
    /**
340
     * Returns the String representation of this Expr.
341
     * @param dest the String to use when creating the String
342
     * representation. The String representation will be appended to
343
     * any data in the destination String, to allow cascading calls to
344
     * other #toString() methods for Expressions.
345
     * @return the String representation of this Expr.
346
    **/
347
    virtual void toString(String& str);
252
    virtual void toString(String& str);
348
253
349
private:
254
private:
 Lines 355-361    Link Here 
355
 * This class represents a NodeTestExpr as defined by the XSL
260
 * This class represents a NodeTestExpr as defined by the XSL
356
 * Working Draft
261
 * Working Draft
357
**/
262
**/
358
class NodeExpr : public PatternExpr {
263
class NodeExpr : public Expr {
359
264
360
public:
265
public:
361
266
 Lines 379-411    Link Here 
379
    //------------------/
284
    //------------------/
380
285
381
    /**
286
    /**
382
     * Returns the default priority of this Pattern based on the given Node,
383
     * context Node, and ContextState.
384
     * If this pattern does not match the given Node under the current context Node and
385
     * ContextState then Negative Infinity is returned.
386
    **/
387
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
388
389
    /**
390
     * Returns the type of this NodeExpr
287
     * Returns the type of this NodeExpr
391
     * @return the type of this NodeExpr
288
     * @return the type of this NodeExpr
392
    **/
289
    **/
393
    virtual short getType() = 0;
290
    virtual short getType() = 0;
394
291
395
    /**
292
    /**
396
     * Determines whether this NodeExpr matches the given node within
293
     * Virtual methods from Expr 
397
     * the given context
398
    **/
294
    **/
399
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
295
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
400
296
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
401
    /**
402
     * Returns the String representation of this Pattern.
403
     * @param dest the String to use when creating the String
404
     * representation. The String representation will be appended to
405
     * any data in the destination String, to allow cascading calls to
406
     * other #toString() methods for Expressions.
407
     * @return the String representation of this Pattern.
408
    **/
409
    virtual void toString(String& dest) = 0;
297
    virtual void toString(String& dest) = 0;
410
298
411
}; //-- NodeExpr
299
}; //-- NodeExpr
 Lines 440-486    Link Here 
440
    **/
328
    **/
441
    void setName(const String& name);
329
    void setName(const String& name);
442
330
443
    //-----------------------------------/
444
   //- Method signatures from NodeExpr -/
445
  //-----------------------------------/
446
447
    /**
331
    /**
448
     * Returns the default priority of this Pattern based on the given Node,
332
     * Virtual methods from NodeExpr 
449
     * context Node, and ContextState.
450
     * If this pattern does not match the given Node under the current context Node and
451
     * ContextState then Negative Infinity is returned.
452
    **/
333
    **/
453
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
454
455
    /**
456
     * Evaluates this Expr based on the given context node and processor state
457
     * @param context the context node for evaluation of this Expr
458
     * @param ps the ContextState containing the stack information needed
459
     * for evaluation
460
     * @return the result of the evaluation
461
    **/
462
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
334
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
463
464
    /**
465
     * Returns the type of this NodeExpr
466
     * @return the type of this NodeExpr
467
    **/
468
    short getType();
335
    short getType();
469
470
    /**
471
     * Determines whether this NodeExpr matches the given node within
472
     * the given context
473
    **/
474
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
336
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
475
337
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
476
    /**
477
     * Returns the String representation of this NodeExpr.
478
     * @param dest the String to use when creating the String
479
     * representation. The String representation will be appended to
480
     * any data in the destination String, to allow cascading calls to
481
     * other #toString() methods for Expressions.
482
     * @return the String representation of this NodeExpr.
483
    **/
484
    virtual void toString(String& dest);
338
    virtual void toString(String& dest);
485
339
486
private:
340
private:
 Lines 521-572    Link Here 
521
     * Destroys this BasicNodeExpr
375
     * Destroys this BasicNodeExpr
522
    **/
376
    **/
523
    virtual ~BasicNodeExpr();
377
    virtual ~BasicNodeExpr();
524
378
    
525
    //-----------------------------------/
526
   //- Method signatures from NodeExpr -/
527
  //-----------------------------------/
528
529
    /**
379
    /**
530
     * Returns the default priority of this Pattern based on the given Node,
380
     * Sets the name of the node to match. Only availible for pi nodes
531
     * context Node, and ContextState.
532
     * If this pattern does not match the given Node under the current context Node and
533
     * ContextState then Negative Infinity is returned.
534
    **/
381
    **/
535
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
382
    void setNodeName(const String& name);
536
383
537
    /**
384
    /**
538
     * Evaluates this Expr based on the given context node and processor state
385
     * Virtual methods from NodeExpr 
539
     * @param context the context node for evaluation of this Expr
540
     * @param ps the ContextState containing the stack information needed
541
     * for evaluation
542
     * @return the result of the evaluation
543
    **/
386
    **/
544
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
387
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
545
546
    /**
547
     * Returns the type of this NodeExpr
548
     * @return the type of this NodeExpr
549
    **/
550
    short getType();
388
    short getType();
551
552
    /**
553
     * Determines whether this NodeExpr matches the given node within
554
     * the given context
555
    **/
556
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
389
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
557
390
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
558
    /**
559
     * Returns the String representation of this NodeExpr.
560
     * @param dest the String to use when creating the String
561
     * representation. The String representation will be appended to
562
     * any data in the destination String, to allow cascading calls to
563
     * other #toString() methods for Expressions.
564
     * @return the String representation of this NodeExpr.
565
    **/
566
    virtual void toString(String& dest);
391
    virtual void toString(String& dest);
567
392
568
private:
393
private:
569
    NodeExprType type;
394
    NodeExprType type;
395
    String nodeName;
396
    MBool nodeNameSet;
570
}; //-- BasicNodeExpr
397
}; //-- BasicNodeExpr
571
398
572
/**
399
/**
 Lines 597-643    Link Here 
597
    **/
424
    **/
598
    void setName(const String& name);
425
    void setName(const String& name);
599
426
600
    //-----------------------------------/
601
   //- Method signatures from NodeExpr -/
602
  //-----------------------------------/
603
604
    /**
427
    /**
605
     * Evaluates this Expr based on the given context node and processor state
428
     * Virtual methods from NodeExpr 
606
     * @param context the context node for evaluation of this Expr
607
     * @param ps the ContextState containing the stack information needed
608
     * for evaluation
609
     * @return the result of the evaluation
610
    **/
429
    **/
611
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
430
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
612
613
    /**
614
     * Returns the default priority of this Pattern based on the given Node,
615
     * context Node, and ContextState.
616
     * If this pattern does not match the given Node under the current context Node and
617
     * ContextState then Negative Infinity is returned.
618
    **/
619
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
620
621
    /**
622
     * Returns the type of this NodeExpr
623
     * @return the type of this NodeExpr
624
    **/
625
    short getType();
431
    short getType();
626
432
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
627
    /**
628
     * Determines whether this NodeExpr matches the given node within
629
     * the given context
630
    **/
631
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
433
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
632
633
    /**
634
     * Returns the String representation of this NodeExpr.
635
     * @param dest the String to use when creating the String
636
     * representation. The String representation will be appended to
637
     * any data in the destination String, to allow cascading calls to
638
     * other #toString() methods for Expressions.
639
     * @return the String representation of this NodeExpr.
640
    **/
641
    virtual void toString(String& dest);
434
    virtual void toString(String& dest);
642
435
643
private:
436
private:
 Lines 655-775    Link Here 
655
}; //-- ElementExpr
448
}; //-- ElementExpr
656
449
657
/**
450
/**
658
 * This class represents a IdentityExpr, which only matches a node
659
 * if it is equal to the context node
660
**/
661
class IdentityExpr : public Expr {
662
663
public:
664
665
      //------------------/
666
     //- Public Methods -/
667
    //------------------/
668
669
    /**
670
     * Evaluates this Expr based on the given context node and processor state
671
     * @param context the context node for evaluation of this Expr
672
     * @param ps the ContextState containing the stack information needed
673
     * for evaluation
674
     * @return the result of the evaluation
675
    **/
676
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
677
678
    /**
679
     * Returns the String representation of this NodeExpr.
680
     * @param dest the String to use when creating the String
681
     * representation. The String representation will be appended to
682
     * any data in the destination String, to allow cascading calls to
683
     * other #toString() methods for Expressions.
684
     * @return the String representation of this NodeExpr.
685
    **/
686
    virtual void toString(String& dest);
687
688
}; //-- IdentityExpr
689
690
/**
691
 * This class represents a ParentExpr, which only selects a node
692
 * if it is equal to the context node's parent
693
**/
694
class ParentExpr : public Expr {
695
696
public:
697
698
      //------------------/
699
     //- Public Methods -/
700
    //------------------/
701
702
    /**
703
     * Evaluates this Expr based on the given context node and processor state
704
     * @param context the context node for evaluation of this Expr
705
     * @param ps the ContextState containing the stack information needed
706
     * for evaluation
707
     * @return the result of the evaluation
708
    **/
709
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
710
711
712
    /**
713
     * Returns the String representation of this NodeExpr.
714
     * @param dest the String to use when creating the String
715
     * representation. The String representation will be appended to
716
     * any data in the destination String, to allow cascading calls to
717
     * other #toString() methods for Expressions.
718
     * @return the String representation of this NodeExpr.
719
    **/
720
    virtual void toString(String& dest);
721
722
}; //-- ParentExpr
723
724
/**
725
 * This class represents a TextExpr, which only matches any text node
451
 * This class represents a TextExpr, which only matches any text node
726
**/
452
**/
727
class TextExpr : public NodeExpr {
453
class TextExpr : public NodeExpr {
728
454
729
public:
455
public:
730
731
      //------------------/
732
     //- Public Methods -/
733
    //------------------/
734
735
    /**
736
     * Evaluates this Expr based on the given context node and processor state
737
     * @param context the context node for evaluation of this Expr
738
     * @param ps the ContextState containing the stack information needed
739
     * for evaluation
740
     * @return the result of the evaluation
741
    **/
742
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
743
744
    /**
745
     * Returns the default priority of this Pattern based on the given Node,
746
     * context Node, and ContextState.
747
     * If this pattern does not match the given Node under the current context Node and
748
     * ContextState then Negative Infinity is returned.
749
    **/
750
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
751
752
    /**
753
     * Returns the type of this NodeExpr
754
     * @return the type of this NodeExpr
755
    **/
756
    virtual short getType();
757
758
    /**
759
     * Determines whether this NodeExpr matches the given node within
760
     * the given context
761
    **/
762
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
763
456
457
      //------------------/
458
     //- Public Methods -/
459
    //------------------/
764
460
765
    /**
461
    /**
766
     * Returns the String representation of this NodeExpr.
462
     * Virtual methods from NodeExpr 
767
     * @param dest the String to use when creating the String
768
     * representation. The String representation will be appended to
769
     * any data in the destination String, to allow cascading calls to
770
     * other #toString() methods for Expressions.
771
     * @return the String representation of this NodeExpr.
772
    **/
463
    **/
464
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
465
    virtual short getType();
466
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
467
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
773
    virtual void toString(String& dest);
468
    virtual void toString(String& dest);
774
469
775
}; //-- TextExpr
470
}; //-- TextExpr
 Lines 827-833    Link Here 
827
    List predicates;
522
    List predicates;
828
}; //-- PredicateList
523
}; //-- PredicateList
829
524
830
class LocationStep : public PredicateList, public PatternExpr {
525
class LocationStep : public PredicateList, public Expr {
831
526
832
public:
527
public:
833
528
 Lines 887-933    Link Here 
887
    **/
582
    **/
888
    void setNodeExpr(NodeExpr* nodeExpr);
583
    void setNodeExpr(NodeExpr* nodeExpr);
889
584
890
      //------------------------------------/
891
     //- Virtual methods from PatternExpr -/
892
    //------------------------------------/
893
894
    /**
585
    /**
895
     * Evaluates this Expr based on the given context node and processor state
586
     * Virtual methods from Expr 
896
     * @param context the context node for evaluation of this Expr
897
     * @param ps the ContextState containing the stack information needed
898
     * for evaluation
899
     * @return the result of the evaluation
900
    **/
587
    **/
901
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
588
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
902
903
    /**
904
     * Returns the default priority of this Pattern based on the given Node,
905
     * context Node, and ContextState.
906
     * If this pattern does not match the given Node under the current context Node and
907
     * ContextState then Negative Infinity is returned.
908
    **/
909
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
910
911
    /**
912
     * Determines whether this PatternExpr matches the given node within
913
     * the given context
914
    **/
915
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
589
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
916
590
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
917
    /**
918
     * Returns the String representation of this PatternExpr.
919
     * @param dest the String to use when creating the String
920
     * representation. The String representation will be appended to
921
     * any data in the destination String, to allow cascading calls to
922
     * other #toString() methods for Expressions.
923
     * @return the String representation of this PatternExpr.
924
    **/
925
    virtual void toString(String& dest);
591
    virtual void toString(String& dest);
926
592
927
private:
593
private:
928
594
929
  NodeExpr* nodeExpr;
595
    NodeExpr* nodeExpr;
930
  short     axisIdentifier;
596
    short     axisIdentifier;
931
597
932
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
598
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
933
    void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
599
    void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
 Lines 935-941    Link Here 
935
}; //-- LocationStep
601
}; //-- LocationStep
936
602
937
603
938
class FilterExpr : public PredicateList, public PatternExpr {
604
class FilterExpr : public PredicateList, public Expr {
939
605
940
public:
606
public:
941
607
 Lines 962-1007    Link Here 
962
    **/
628
    **/
963
    void setExpr(Expr* expr);
629
    void setExpr(Expr* expr);
964
630
965
      //------------------------------------/
966
     //- Virtual methods from PatternExpr -/
967
    //------------------------------------/
968
969
    /**
631
    /**
970
     * Evaluates this Expr based on the given context node and processor state
632
     * Virtual methods from Expr 
971
     * @param context the context node for evaluation of this Expr
972
     * @param ps the ContextState containing the stack information needed
973
     * for evaluation
974
     * @return the result of the evaluation
975
    **/
633
    **/
976
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
634
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
977
978
    /**
979
     * Returns the default priority of this Pattern based on the given Node,
980
     * context Node, and ContextState.
981
     * If this pattern does not match the given Node under the current context Node and
982
     * ContextState then Negative Infinity is returned.
983
    **/
984
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
985
986
    /**
987
     * Determines whether this PatternExpr matches the given node within
988
     * the given context
989
    **/
990
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
635
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
991
636
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
992
    /**
993
     * Returns the String representation of this PatternExpr.
994
     * @param dest the String to use when creating the String
995
     * representation. The String representation will be appended to
996
     * any data in the destination String, to allow cascading calls to
997
     * other #toString() methods for Expressions.
998
     * @return the String representation of this PatternExpr.
999
    **/
1000
    virtual void toString(String& dest);
637
    virtual void toString(String& dest);
1001
638
1002
private:
639
private:
1003
640
1004
  Expr*     expr;
641
    Expr* expr;
1005
642
1006
}; //-- FilterExpr
643
}; //-- FilterExpr
1007
644
 Lines 1015-1036    Link Here 
1015
    ~NumberExpr();
652
    ~NumberExpr();
1016
653
1017
    /**
654
    /**
1018
     * Evaluates this Expr based on the given context node and processor state
655
     * Virtual methods from Expr 
1019
     * @param context the context node for evaluation of this Expr
1020
     * @param ps the ContextState containing the stack information needed
1021
     * for evaluation
1022
     * @return the result of the evaluation
1023
    **/
656
    **/
1024
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
657
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1025
1026
    /**
1027
     * Returns the String representation of this Expr.
1028
     * @param dest the String to use when creating the String
1029
     * representation. The String representation will be appended to
1030
     * any data in the destination String, to allow cascading calls to
1031
     * other #toString() methods for Expressions.
1032
     * @return the String representation of this Expr.
1033
    **/
1034
    virtual void toString(String& str);
658
    virtual void toString(String& str);
1035
659
1036
private:
660
private:
 Lines 1052-1073    Link Here 
1052
    ~StringExpr();
676
    ~StringExpr();
1053
677
1054
    /**
678
    /**
1055
     * Evaluates this Expr based on the given context node and processor state
679
     * Virtual methods from Expr 
1056
     * @param context the context node for evaluation of this Expr
1057
     * @param ps the ContextState containing the stack information needed
1058
     * for evaluation
1059
     * @return the result of the evaluation
1060
    **/
680
    **/
1061
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
681
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1062
1063
    /**
1064
     * Returns the String representation of this Expr.
1065
     * @param dest the String to use when creating the String
1066
     * representation. The String representation will be appended to
1067
     * any data in the destination String, to allow cascading calls to
1068
     * other #toString() methods for Expressions.
1069
     * @return the String representation of this Expr.
1070
    **/
1071
    virtual void toString(String& str);
682
    virtual void toString(String& str);
1072
683
1073
private:
684
private:
 Lines 1106-1127    Link Here 
1106
717
1107
718
1108
    /**
719
    /**
1109
     * Evaluates this Expr based on the given context node and processor state
720
     * Virtual methods from Expr 
1110
     * @param context the context node for evaluation of this Expr
1111
     * @param ps the ContextState containing the stack information needed
1112
     * for evaluation
1113
     * @return the result of the evaluation
1114
    **/
721
    **/
1115
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
722
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1116
1117
    /**
1118
     * Returns the String representation of this Expr.
1119
     * @param dest the String to use when creating the String
1120
     * representation. The String representation will be appended to
1121
     * any data in the destination String, to allow cascading calls to
1122
     * other #toString() methods for Expressions.
1123
     * @return the String representation of this Expr.
1124
    **/
1125
    virtual void toString(String& str);
723
    virtual void toString(String& str);
1126
724
1127
725
 Lines 1133-1138    Link Here 
1133
}; //-- AdditiveExpr
731
}; //-- AdditiveExpr
1134
732
1135
/**
733
/**
734
 * Represents an UnaryExpr. Returns the negative value of it's expr.
735
**/
736
class UnaryExpr : public Expr {
737
738
public:
739
740
     UnaryExpr();
741
     UnaryExpr(Expr* expr);
742
     ~UnaryExpr();
743
744
    /**
745
     * Sets the expression to negate
746
    **/
747
    void setExpr(Expr* expr);
748
749
    /**
750
     * Virtual methods from Expr 
751
    **/
752
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
753
    virtual void toString(String& str);
754
755
private:
756
    Expr* expr;
757
}; //-- UnaryExpr
758
759
/**
1136
 * Represents a BooleanExpr, a binary expression that
760
 * Represents a BooleanExpr, a binary expression that
1137
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
761
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
1138
**/
762
**/
 Lines 1148-1180    Link Here 
1148
     ~BooleanExpr();
772
     ~BooleanExpr();
1149
773
1150
    /**
774
    /**
1151
     * Sets the left side of this AdditiveExpr
775
     * Sets the left side of this BooleanExpr
1152
    **/
776
    **/
1153
    void setLeftExpr(Expr* leftExpr);
777
    void setLeftExpr(Expr* leftExpr);
1154
778
1155
    /**
779
    /**
1156
     * Sets the right side of this AdditiveExpr
780
     * Sets the right side of this BooleanExpr
1157
    **/
781
    **/
1158
    void setRightExpr(Expr* rightExpr);
782
    void setRightExpr(Expr* rightExpr);
1159
783
1160
784
1161
    /**
785
    /**
1162
     * Evaluates this Expr based on the given context node and processor state
786
     * Virtual methods from Expr 
1163
     * @param context the context node for evaluation of this Expr
1164
     * @param ps the ContextState containing the stack information needed
1165
     * for evaluation
1166
     * @return the result of the evaluation
1167
    **/
787
    **/
1168
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
788
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1169
1170
    /**
1171
     * Returns the String representation of this Expr.
1172
     * @param dest the String to use when creating the String
1173
     * representation. The String representation will be appended to
1174
     * any data in the destination String, to allow cascading calls to
1175
     * other #toString() methods for Expressions.
1176
     * @return the String representation of this Expr.
1177
    **/
1178
    virtual void toString(String& str);
789
    virtual void toString(String& str);
1179
790
1180
791
 Lines 1215-1242    Link Here 
1215
    **/
826
    **/
1216
    void setRightExpr(Expr* rightExpr);
827
    void setRightExpr(Expr* rightExpr);
1217
828
1218
1219
    /**
829
    /**
1220
     * Evaluates this Expr based on the given context node and processor state
830
     * Virtual methods from Expr 
1221
     * @param context the context node for evaluation of this Expr
1222
     * @param ps the ContextState containing the stack information needed
1223
     * for evaluation
1224
     * @return the result of the evaluation
1225
    **/
831
    **/
1226
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
832
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1227
1228
    /**
1229
     * Returns the String representation of this Expr.
1230
     * @param dest the String to use when creating the String
1231
     * representation. The String representation will be appended to
1232
     * any data in the destination String, to allow cascading calls to
1233
     * other #toString() methods for Expressions.
1234
     * @return the String representation of this Expr.
1235
    **/
1236
    virtual void toString(String& str);
833
    virtual void toString(String& str);
1237
834
1238
1239
1240
private:
835
private:
1241
    short op;
836
    short op;
1242
    Expr* leftExpr;
837
    Expr* leftExpr;
 Lines 1273-1298    Link Here 
1273
     ~RelationalExpr();
868
     ~RelationalExpr();
1274
869
1275
    /**
870
    /**
1276
     * Evaluates this Expr based on the given context node and processor state
871
     * Virtual methods from Expr 
1277
     * @param context the context node for evaluation of this Expr
1278
     * @param ps the ContextState containing the stack information needed
1279
     * for evaluation
1280
     * @return the result of the evaluation
1281
    **/
872
    **/
1282
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
873
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1283
1284
    /**
1285
     * Returns the String representation of this Expr.
1286
     * @param dest the String to use when creating the String
1287
     * representation. The String representation will be appended to
1288
     * any data in the destination String, to allow cascading calls to
1289
     * other #toString() methods for Expressions.
1290
     * @return the String representation of this Expr.
1291
    **/
1292
    virtual void toString(String& str);
874
    virtual void toString(String& str);
1293
875
1294
1295
1296
private:
876
private:
1297
    short op;
877
    short op;
1298
    Expr* leftExpr;
878
    Expr* leftExpr;
 Lines 1320-1341    Link Here 
1320
    void setName(const String& name);
900
    void setName(const String& name);
1321
901
1322
    /**
902
    /**
1323
     * Evaluates this Expr based on the given context node and processor state
903
     * Virtual methods from Expr 
1324
     * @param context the context node for evaluation of this Expr
1325
     * @param ps the ContextState containing the stack information needed
1326
     * for evaluation
1327
     * @return the result of the evaluation
1328
    **/
904
    **/
1329
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
905
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1330
1331
    /**
1332
     * Returns the String representation of this Expr.
1333
     * @param dest the String to use when creating the String
1334
     * representation. The String representation will be appended to
1335
     * any data in the destination String, to allow cascading calls to
1336
     * other #toString() methods for Expressions.
1337
     * @return the String representation of this Expr.
1338
    **/
1339
    virtual void toString(String& str);
906
    virtual void toString(String& str);
1340
907
1341
private:
908
private:
 Lines 1346-1352    Link Here 
1346
/**
913
/**
1347
 *  Represents a PathExpr
914
 *  Represents a PathExpr
1348
**/
915
**/
1349
class PathExpr : public PatternExpr {
916
class PathExpr : public Expr {
1350
917
1351
public:
918
public:
1352
919
 Lines 1361-1426    Link Here 
1361
    PathExpr();
928
    PathExpr();
1362
929
1363
    /**
930
    /**
1364
     * Destructor, will delete all Pattern Expressions
931
     * Destructor, will delete all Expressions
1365
    **/
932
    **/
1366
    virtual ~PathExpr();
933
    virtual ~PathExpr();
1367
934
1368
    /**
935
    /**
1369
     * Adds the PatternExpr to this PathExpr
936
     * Adds the Expr to this PathExpr
1370
     * @param expr the Expr to add to this PathExpr
937
     * @param expr the Expr to add to this PathExpr
1371
     * @param index the index at which to add the given Expr
938
     * @param index the index at which to add the given Expr
1372
    **/
939
    **/
1373
    void addPatternExpr(int index, PatternExpr* expr, short ancestryOp);
940
    void addExpr(int index, Expr* expr, short ancestryOp);
1374
941
1375
    /**
942
    /**
1376
     * Adds the PatternExpr to this PathExpr
943
     * Adds the Expr to this PathExpr
1377
     * @param expr the Expr to add to this PathExpr
944
     * @param expr the Expr to add to this PathExpr
1378
    **/
945
    **/
1379
    void addPatternExpr(PatternExpr* expr, short ancestryOp);
946
    void addExpr(Expr* expr, short ancestryOp);
1380
947
1381
    virtual MBool isAbsolute();
948
    virtual MBool isAbsolute();
1382
949
1383
      //------------------------------------/
1384
     //- Virtual methods from PatternExpr -/
1385
    //------------------------------------/
1386
1387
    /**
950
    /**
1388
     * Evaluates this Expr based on the given context node and processor state
951
     * Virtual methods from Expr 
1389
     * @param context the context node for evaluation of this Expr
1390
     * @param ps the ContextState containing the stack information needed
1391
     * for evaluation
1392
     * @return the result of the evaluation
1393
    **/
952
    **/
1394
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
953
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1395
1396
    /**
1397
     * Returns the default priority of this Pattern based on the given Node,
1398
     * context Node, and ContextState.
1399
     * If this pattern does not match the given Node under the current context Node and
1400
     * ContextState then Negative Infinity is returned.
1401
    **/
1402
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1403
1404
    /**
1405
     * Determines whether this PatternExpr matches the given node within
1406
     * the given context
1407
    **/
1408
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
954
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1409
955
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1410
    /**
1411
     * Returns the String representation of this PatternExpr.
1412
     * @param dest the String to use when creating the String
1413
     * representation. The String representation will be appended to
1414
     * any data in the destination String, to allow cascading calls to
1415
     * other #toString() methods for Expressions.
1416
     * @return the String representation of this PatternExpr.
1417
    **/
1418
    virtual void toString(String& dest);
956
    virtual void toString(String& dest);
1419
957
1420
private:
958
private:
1421
959
1422
    struct PathExprItem {
960
    struct PathExprItem {
1423
        PatternExpr* pExpr;
961
        Expr* expr;
1424
        short ancestryOp;
962
        short ancestryOp;
1425
    };
963
    };
1426
964
 Lines 1428-1440    Link Here 
1428
966
1429
   /**
967
   /**
1430
    * Selects from the descendants of the context node
968
    * Selects from the descendants of the context node
1431
    * all nodes that match the PatternExpr
969
    * all nodes that match the Expr
1432
    * -- this will be moving to a Utility class
970
    * -- this will be moving to a Utility class
1433
   **/
971
   **/
1434
   void evalDescendants(PatternExpr* pExpr,
972
   void evalDescendants(Expr* expr,
1435
                        Node* context,
973
                        Node* context,
1436
                        ContextState* cs,
974
                        ContextState* cs,
1437
                        NodeSet* nodes);
975
                        NodeSet* resNodes);
1438
976
1439
}; //-- PathExpr
977
}; //-- PathExpr
1440
978
 Lines 1450-1496    Link Here 
1450
    //------------------/
988
    //------------------/
1451
989
1452
    /**
990
    /**
1453
     * Evaluates this Expr based on the given context node and processor state
991
     * Virtual methods from Expr 
1454
     * @param context the context node for evaluation of this Expr
1455
     * @param ps the ContextState containing the stack information needed
1456
     * for evaluation
1457
     * @return the result of the evaluation
1458
    **/
992
    **/
1459
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
993
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1460
1461
    virtual MBool isAbsolute();
1462
1463
    /**
1464
     * Returns the default priority of this Pattern based on the given Node,
1465
     * context Node, and ContextState.
1466
     * If this pattern does not match the given Node under the current context Node and
1467
     * ContextState then Negative Infinity is returned.
1468
    **/
1469
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1470
1471
    /**
1472
     * Determines whether this NodeExpr matches the given node within
1473
     * the given context
1474
    **/
1475
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
994
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1476
995
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1477
    /**
1478
     * Returns the String representation of this PatternExpr.
1479
     * @param dest the String to use when creating the String
1480
     * representation. The String representation will be appended to
1481
     * any data in the destination String, to allow cascading calls to
1482
     * other #toString() methods for Expressions.
1483
     * @return the String representation of this PatternExpr.
1484
    **/
1485
    virtual void toString(String& dest);
996
    virtual void toString(String& dest);
1486
997
998
    virtual MBool isAbsolute();
999
1487
1000
1488
}; //-- RootExpr
1001
}; //-- RootExpr
1489
1002
1490
/**
1003
/**
1491
 *  Represents a UnionExpr
1004
 *  Represents a UnionExpr
1492
**/
1005
**/
1493
class UnionExpr : public PatternExpr {
1006
class UnionExpr : public Expr {
1494
1007
1495
public:
1008
public:
1496
1009
 Lines 1508-1556    Link Here 
1508
     * Adds the PathExpr to this UnionExpr
1021
     * Adds the PathExpr to this UnionExpr
1509
     * @param expr the Expr to add to this UnionExpr
1022
     * @param expr the Expr to add to this UnionExpr
1510
    **/
1023
    **/
1511
    void addPathExpr(PathExpr* expr);
1024
    void addExpr(Expr* expr);
1512
1025
1513
    /**
1026
    /**
1514
     * Adds the PathExpr to this UnionExpr at the specified index
1027
     * Adds the PathExpr to this UnionExpr at the specified index
1515
     * @param expr the Expr to add to this UnionExpr
1028
     * @param expr the Expr to add to this UnionExpr
1516
    **/
1029
    **/
1517
    void addPathExpr(int index, PathExpr* expr);
1030
    void addExpr(int index, Expr* expr);
1518
1519
      //------------------------------------/
1520
     //- Virtual methods from PatternExpr -/
1521
    //------------------------------------/
1522
1031
1523
    /**
1032
    /**
1524
     * Evaluates this Expr based on the given context node and processor state
1033
     * Virtual methods from Expr 
1525
     * @param context the context node for evaluation of this Expr
1526
     * @param ps the ContextState containing the stack information needed
1527
     * for evaluation
1528
     * @return the result of the evaluation
1529
    **/
1034
    **/
1530
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1035
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1531
1532
    /**
1533
     * Returns the default priority of this Pattern based on the given Node,
1534
     * context Node, and ContextState.
1535
     * If this pattern does not match the given Node under the current context Node and
1536
     * ContextState then Negative Infinity is returned.
1537
    **/
1538
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1539
1540
    /**
1541
     * Determines whether this PatternExpr matches the given node within
1542
     * the given context
1543
    **/
1544
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1036
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1545
1037
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1546
    /**
1547
     * Returns the String representation of this PatternExpr.
1548
     * @param dest the String to use when creating the String
1549
     * representation. The String representation will be appended to
1550
     * any data in the destination String, to allow cascading calls to
1551
     * other #toString() methods for Expressions.
1552
     * @return the String representation of this PatternExpr.
1553
    **/
1554
    virtual void toString(String& dest);
1038
    virtual void toString(String& dest);
1555
1039
1556
private:
1040
private:
(-)ExprLexer.cpp (-585 / +355 lines)
Line     Link Here 
 Lines 1-4    Link Here 
1
/*
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 
2
 * The contents of this file are subject to the Mozilla Public
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
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
4
 * except in compliance with the License. You may obtain a copy of
 Lines 29-34    Link Here 
29
 *   -- Fixed bug in parse method so that we make sure we check for
29
 *   -- Fixed bug in parse method so that we make sure we check for
30
 *      axis identifier wild cards, such as ancestor::*
30
 *      axis identifier wild cards, such as ancestor::*
31
 *
31
 *
32
 * Axel Hecht <axel@pike.org>
33
 *   -- big beating, general overhaul
34
 *
32
 * $Id: ExprLexer.cpp,v 1.13 2001/05/12 11:59:44 peterv%netscape.com Exp $
35
 * $Id: ExprLexer.cpp,v 1.13 2001/05/12 11:59:44 peterv%netscape.com Exp $
33
 */
36
 */
34
37
 Lines 48-63    Link Here 
48
/**
51
/**
49
 * Default constructor for Token
52
 * Default constructor for Token
50
**/
53
**/
51
Token::Token() {
54
Token::Token()
52
    this->type =0;
55
{
56
  this->type =0;
53
} //-- Token;
57
} //-- Token;
54
58
55
/**
59
/**
56
 * Constructor for Token
60
 * Constructor for Token
57
 * @param type, the type of Token being represented
61
 * @param type, the type of Token being represented
58
**/
62
**/
59
Token::Token(short type) {
63
Token::Token(short type)
60
    this->type = type;
64
{
65
  this->type = type;
61
} //-- Token;
66
} //-- Token;
62
67
63
/**
68
/**
 Lines 65-94    Link Here 
65
 * @param value the value of this Token
70
 * @param value the value of this Token
66
 * @param type, the type of Token being represented
71
 * @param type, the type of Token being represented
67
**/
72
**/
68
Token::Token(const String& value, short type) {
73
Token::Token(const String& value, short type)
69
    this->type = type;
74
{
70
    //-- make copy of value String
75
  this->type = type;
71
    this->value = value;
76
  //-- make copy of value String
77
  this->value = value;
72
} //-- Token
78
} //-- Token
73
79
74
Token::Token(UNICODE_CHAR uniChar, short type) {
80
Token::Token(UNICODE_CHAR uniChar, short type)
75
    this->type = type;
81
{
76
    this->value.append(uniChar);
82
  this->type = type;
83
  this->value.append(uniChar);
77
} //-- Token
84
} //-- Token
78
85
79
/**
86
/**
80
 * Copy Constructor
87
 * Copy Constructor
81
**/
88
**/
82
Token::Token(const Token& token) {
89
Token::Token(const Token& token)
83
    this->type = token.type;
90
{
84
    this->value = token.value;
91
  this->type = token.type;
92
  this->value = token.value;
85
} //-- Token
93
} //-- Token
86
94
87
/**
95
/**
88
 * Destructor for Token
96
 * Destructor for Token
89
**/
97
**/
90
Token::~Token() {
98
Token::~Token()
91
    //-- currently nothing is needed
99
{
100
  //-- currently nothing is needed
92
} //-- ~Token
101
} //-- ~Token
93
102
94
103
 Lines 113-140    Link Here 
113
const String ExprLexer::MODULUS = "mod";
122
const String ExprLexer::MODULUS = "mod";
114
const String ExprLexer::DIVIDE  = "div";
123
const String ExprLexer::DIVIDE  = "div";
115
124
116
117
/**
125
/**
118
 * The set of a XSL Expression Tokens
126
 * The set of Lexer error messages
119
**/
127
 **/
120
const Token ExprLexer::TOKENS[] = {
128
const String ExprLexer::error_message[] =
121
129
{
122
    //-- Nodetype tokens
130
  "VariableReference expected",
123
    Token(ExprLexer::COMMENT,       Token::COMMENT),
131
  "Operator expected",
124
    Token(ExprLexer::NODE,          Token::NODE),
132
  "Literal is not closed",
125
    Token(ExprLexer::PROC_INST,     Token::PROC_INST),
133
  ": not expected",
126
    Token(ExprLexer::TEXT,          Token::TEXT),
134
  "! not expected, use != or not()",
127
    //-- boolean operators
135
  "found a unkown character"
128
    Token(ExprLexer::AND,           Token::AND_OP),
129
    Token(ExprLexer::OR,            Token::OR_OP),
130
131
    //-- multiplicative operators
132
    Token(ExprLexer::MODULUS,       Token::MODULUS_OP),
133
    Token(ExprLexer::DIVIDE,        Token::DIVIDE_OP)
134
};
136
};
135
137
136
const short ExprLexer::NUMBER_OF_TOKENS  = 8;
137
138
  //---------------/
138
  //---------------/
139
 //- Contructors -/
139
 //- Contructors -/
140
//---------------/
140
//---------------/
 Lines 142-725    Link Here 
142
/**
142
/**
143
 * Creates a new ExprLexer using the given String
143
 * Creates a new ExprLexer using the given String
144
**/
144
**/
145
ExprLexer::ExprLexer(const String& pattern) {
145
ExprLexer::ExprLexer(const String& pattern)
146
146
{
147
    firstItem    = 0;
147
  firstItem    = 0;
148
    lastItem     = 0;
148
  lastItem     = 0;
149
    tokenCount   = 0;
149
  tokenCount   = 0;
150
    prevToken    = 0;
150
  prevToken    = 0;
151
    parse(pattern);
151
  endToken.type = Token::END;
152
    currentItem = firstItem;
152
  parse(pattern);
153
  currentItem = firstItem;
153
} //-- ExprLexer
154
} //-- ExprLexer
154
155
155
/**
156
/**
156
 * Destroys this instance of an ExprLexer
157
 * Destroys this instance of an ExprLexer
157
**/
158
**/
158
ExprLexer::~ExprLexer() {
159
ExprLexer::~ExprLexer()
159
   //-- delete tokens
160
{
160
161
  //-- delete tokens
161
   //cout << "~ExprLexer() - start"<<endl;
162
  currentItem = firstItem;
162
   currentItem = firstItem;
163
  while ( currentItem ) {
163
   while ( currentItem ) {
164
    TokenListItem* temp = currentItem->next;
164
       TokenListItem* temp = currentItem->next;
165
    delete currentItem->token;
165
       //cout << "deleting token: " << currentItem->token->value << endl;
166
    delete currentItem;
166
       delete currentItem->token;
167
    currentItem = temp;
167
       delete currentItem;
168
  }
168
       currentItem = temp;
169
   }
170
   //cout << "~ExprLexer() - done"<<endl;
171
} //-- ~ExprLexer
169
} //-- ~ExprLexer
172
170
173
174
int ExprLexer::countAllTokens() {
175
    return tokenCount;
176
} //-- countAllTokens
177
178
int ExprLexer::countRemainingTokens() {
179
    TokenListItem* temp = currentItem;
180
    int c = 0;
181
    while ( temp ) {
182
        ++c;
183
        temp = temp->next;
184
    }
185
    return c;
186
} //-- countRemainingTokens
187
188
171
189
MBool ExprLexer::hasMoreTokens() {
172
MBool ExprLexer::hasMoreTokens()
190
    return (MBool) ( currentItem );
173
{
174
  return (MBool) ( currentItem );
191
} //-- hasMoreTokens
175
} //-- hasMoreTokens
192
176
193
Token* ExprLexer::nextToken() {
177
Token* ExprLexer::nextToken()
194
    if ( currentItem ) {
178
{
195
        Token* token = currentItem->token;
179
  if ( currentItem ) {
196
        currentItem = currentItem->next;
180
    Token* token = currentItem->token;
197
        return token;
181
    currentItem = currentItem->next;
198
    }
182
    return token;
199
    return 0;
183
  }
184
  return &endToken;
200
} //-- nextToken
185
} //-- nextToken
201
186
202
void ExprLexer::pushBack() {
187
void ExprLexer::pushBack()
203
    if ( !currentItem ) {
188
{
204
        currentItem = lastItem;
189
  if ( !currentItem ) {
205
    }
190
    currentItem = lastItem;
206
    else currentItem = currentItem->previous;
191
  }
192
  else currentItem = currentItem->previous;
207
} //-- pushBack
193
} //-- pushBack
208
209
/*
210
Token* ExprLexer::lastToken() {
211
    if (lastItem) {
212
        return lastItem->token;
213
    }
214
    return 0;
215
} //-- lastToken
216
*/
217
194
218
Token* ExprLexer::peek() {
195
Token* ExprLexer::peek()
219
    Token* token = 0;
196
{
220
    TokenListItem* tlItem = currentItem;
197
  if ( currentItem )
221
    if (tlItem) token = tlItem->token;
198
    return currentItem->token;
222
    return token;
199
  return &endToken;
223
} //-- peek
200
} //-- peek
224
201
225
Token* ExprLexer::lookAhead(int offset) {
202
void ExprLexer::addToken(Token* token)
226
    Token* token = 0;
203
{
227
    TokenListItem* tlItem = currentItem;
204
  TokenListItem* tlItem = new TokenListItem;
228
    //-- advance to proper offset
205
  tlItem->token = token;
229
    for ( int i = 0; i < offset; i++ )
206
  tlItem->next  = 0;
230
        if ( tlItem ) tlItem = currentItem->next;
207
  if (lastItem) {
231
208
    tlItem->previous = lastItem;
232
    if (tlItem) token = tlItem->token;
209
    lastItem->next = tlItem;
233
    return token;
210
  }
234
} //-- lookAhead
211
  if (!firstItem) firstItem = tlItem;
235
212
  lastItem = tlItem;
236
void ExprLexer::addToken(Token* token) {
213
  prevToken = token;
237
    TokenListItem* tlItem = new TokenListItem;
214
  ++tokenCount;
238
    tlItem->token = token;
239
    tlItem->next  = 0;
240
    if (lastItem) {
241
        tlItem->previous = lastItem;
242
        lastItem->next = tlItem;
243
    }
244
    if (!firstItem) firstItem = tlItem;
245
    lastItem = tlItem;
246
    prevToken = token;
247
    ++tokenCount;
248
} //-- addToken
215
} //-- addToken
249
216
250
/**
251
 * Returns true if the given character represents an Alpha letter
252
**/
253
MBool ExprLexer::isAlphaChar(Int32 ch) {
254
    if ((ch >= 'a' ) && (ch <= 'z' )) return MB_TRUE;
255
    if ((ch >= 'A' ) && (ch <= 'Z' )) return MB_TRUE;
256
    return MB_FALSE;
257
} //-- isAlphaChar
258
259
/**
217
/**
260
 * Returns true if the given character represents a numeric letter (digit)
218
 * Returns true if the following Token should be an operator.
261
**/
219
 * This is a helper for the first bullet of [XPath 3.7]
262
MBool ExprLexer::isDigit(Int32 ch) {
220
 *  Lexical Structure
263
    if ((ch >= '0') && (ch <= '9'))   return MB_TRUE;
221
**/
222
MBool ExprLexer::nextIsOperatorToken(Token* token)
223
{
224
  if ( !token || token->type == Token::NULL_TOKEN) return MB_FALSE;
225
  /* This relies on the tokens having the right order in ExprLexer.h */
226
  if (token->type >= Token::COMMA && 
227
      token->type <= Token::UNION_OP)
264
    return MB_FALSE;
228
    return MB_FALSE;
265
} //-- isDigit
229
  return MB_TRUE;
266
230
} //-- nextIsOperatorToken
267
/**
268
 * Returns true if the given character is an allowable NCName character
269
**/
270
MBool ExprLexer::isNCNameChar(Int32 ch) {
271
    if (isDigit(ch) || isAlphaChar(ch)) return MB_TRUE;
272
    return (MBool) ((ch == '.') || (ch == '_') || (ch == '-'));
273
} //-- isNCNameChar
274
231
275
/**
232
/**
276
 * Returns true if the given character is an allowable QName character
233
 *  Parses the given String into the set of Tokens
277
**/
278
MBool ExprLexer::isQNameChar(Int32 ch) {
279
    return (MBool) (( ch == ':') || isNCNameChar(ch));
280
} //-- isQNameChar
281
282
/**
283
 * Returns true if the given String is a valid XML QName
284
**/
234
**/
285
MBool ExprLexer::isValidQName(String& name) {
235
void ExprLexer::parse(const String& pattern)
286
236
{
287
    int size = name.length();
237
  String tokenBuffer;
288
    if ( size == 0 ) return MB_FALSE;
238
  Int32 iter = 0, start;
289
    else if ( !isAlphaChar(name.charAt(0))) return MB_FALSE;
239
  Int32 size = pattern.length();
290
    else {
240
  short defType;
291
        for ( int i = 1; i < size; i++) {
241
  UNICODE_CHAR ch;
292
            if ( ! isQNameChar(name.charAt(i))) return MB_FALSE;
242
  if ( size==0 ) return;
243
244
  //-- initialize previous token, this will automatically get
245
  //-- deleted when it goes out of scope
246
  Token nullToken('\0', Token::NULL_TOKEN);
247
248
  prevToken = &nullToken;
249
250
  while (iter < size) {
251
252
    ch = pattern.charAt(iter);
253
    defType = Token::CNAME;
254
255
    if (ch==DOLLAR_SIGN) {
256
      if (++iter == size || !isLetter(ch=pattern.charAt(iter))) {
257
        // Error, VariableReference expected
258
        errorPos = iter;
259
        errorCode = ERROR_UNRESOLVED_VAR_REFERENCE;
260
        if (firstItem)
261
          firstItem->token->type=Token::ERROR;
262
        else
263
          addToken(new Token('\0',Token::ERROR));
264
        iter=size; // bail
265
      } else
266
        defType = Token::VAR_REFERENCE;
267
    } 
268
    // just reuse the QName parsing, which will use defType 
269
    // the token to construct
270
271
    if ( isLetter(ch) ) {
272
      // NCName, can get QName or OperatorName;
273
      //  FunctionName, NodeName, and AxisSpecifier may want whitespace,
274
      //  and are dealt with below
275
      start = iter;
276
      while (++iter < size && 
277
             isNCNameChar(pattern.charAt(iter))) /* just go */ ;
278
      Int32 end = iter;
279
      if (pattern.charAt(iter)==COLON) {
280
        // try QName or wildcard, might need to step back for axis
281
        if (++iter < size)
282
          if (isLetter(pattern.charAt(iter)))
283
            while(++iter < size && 
284
                  isNCNameChar(pattern.charAt(iter))) /* just go */ ;
285
          else if (pattern.charAt(iter)=='*' 
286
                   && defType != Token::VAR_REFERENCE)
287
            ++iter; /* eat wildcard for NameTest, bail for var ref at COLON */
288
          else 
289
            iter--; // step back
290
      }
291
      if (nextIsOperatorToken(prevToken)) {
292
        if (pattern.subString(start,end,subStr).isEqual(AND))
293
          defType = Token::AND_OP;
294
        else if (pattern.subString(start,end,subStr).isEqual(OR))
295
          defType = Token::OR_OP;
296
        else if (pattern.subString(start,end,subStr).isEqual(MODULUS))
297
          defType = Token::MODULUS_OP;
298
        else if (pattern.subString(start,end,subStr).isEqual(DIVIDE))
299
          defType = Token::DIVIDE_OP;
300
        else {
301
          // Error "operator expected"
302
          // XXX QUESTION: spec is not too precise
303
          // badops is sure an error, but is bad:ops, too? We say yes!
304
          errorPos = iter;
305
          errorCode = ERROR_OP_EXPECTED;
306
          if (firstItem)
307
            firstItem->token->type=Token::ERROR;
308
          else
309
            addToken(new Token('\0',Token::ERROR));
310
          iter=size; // bail
293
        }
311
        }
294
    }
312
      }
295
    return MB_TRUE;
313
      addToken(new Token(pattern.subString(start,iter,subStr),defType));
296
} //-- isValidQName
314
    } else if ( isDigit(ch) ) {
297
315
      start = iter;
298
MBool ExprLexer::isOperatorToken(Token* token) {
316
      while (++iter < size && 
299
    if ( !token ) return MB_FALSE;
317
             isDigit(pattern.charAt(iter))) /* just go */;
300
    switch ( token->type ) {
318
      if (pattern.charAt(iter)=='.')
301
        //-- boolean operators
319
        while (++iter < size && 
302
        case Token::AND_OP:
320
               isDigit(pattern.charAt(iter))) /* just go */;
303
        case Token::OR_OP:
321
      addToken(new Token(pattern.subString(start,iter,subStr),Token::NUMBER));
304
        //-- relational operators
322
    } else {
305
        case Token::EQUAL_OP:
323
      switch (ch) {
306
        case Token::NOT_EQUAL_OP:
324
        //-- ignore whitespace
307
        case Token::LESS_THAN_OP:
325
      case SPACE:
308
        case Token::GREATER_THAN_OP:
326
      case TX_TAB:
309
        case Token::LESS_OR_EQUAL_OP:
327
      case TX_CR:
310
        case Token::GREATER_OR_EQUAL_OP:
328
      case TX_LF:
311
        //-- additive operators
329
        ++iter;
312
        case Token::ADDITION_OP:
330
        break;
313
        case Token::SUBTRACTION_OP:
331
      case S_QUOTE :
314
        //-- multiplicative operators
332
      case D_QUOTE :
315
        case Token::DIVIDE_OP:
333
        start=iter;
316
        case Token::MODULUS_OP:
334
        iter = pattern.indexOf(ch,start+1);
317
        case Token::MULTIPLY_OP:
335
        if (iter==NOT_FOUND) {
318
            return MB_TRUE;
336
          // XXX Error reporting "unclosed literal"
319
        default:
337
          errorPos = start;
320
            break;
338
          errorCode = ERROR_UNCLOSED_LITERAL;
321
    }
339
          if (firstItem)
322
340
            firstItem->token->type=Token::ERROR;
323
    return MB_FALSE;
341
          else
324
} //-- isOperatorToken
342
            addToken(new Token('\0',Token::ERROR));
325
343
          iter=size; // bail
326
MBool ExprLexer::matchDelimiter(UNICODE_CHAR ch) {
344
        } else {
327
345
          addToken(new Token(pattern.subString(start+1,iter,subStr),
328
    short tokenType = 0;
346
                             Token::LITERAL));
329
    MBool addChar = MB_TRUE;
347
          ++iter;
330
    switch (ch) {
331
        case FORWARD_SLASH :
332
            tokenType = Token::PARENT_OP;
333
            break;
334
        case L_PAREN :
335
            tokenType = Token::L_PAREN;
336
            break;
337
        case R_PAREN :
338
            tokenType = Token::R_PAREN;
339
            break;
340
        case L_BRACKET :
341
            tokenType = Token::L_BRACKET;
342
            break;
343
        case R_BRACKET :
344
            tokenType = Token::R_BRACKET;
345
            break;
346
        case L_ANGLE :
347
            tokenType = Token::LESS_THAN_OP;
348
            break;
349
        case R_ANGLE :
350
            tokenType = Token::GREATER_THAN_OP;
351
            break;
352
        case COMMA :
353
            tokenType = Token::COMMA;
354
            break;
355
        case PERIOD :
356
            tokenType = Token::SELF_NODE;
357
            break;
358
        case EQUAL :
359
            tokenType = Token::EQUAL_OP;
360
            break;
361
        case PLUS :
362
            tokenType = Token::ADDITION_OP;
363
            break;
364
        case HYPHEN :
365
            tokenType = Token::SUBTRACTION_OP;
366
            break;
367
        case VERT_BAR:
368
            tokenType = Token::UNION_OP;
369
            break;
370
        case AT_SIGN:
371
            tokenType = Token::AT_SIGN;
372
            break;
373
        case DOLLAR_SIGN:
374
            tokenType = Token::VAR_REFERENCE;
375
            addChar = MB_FALSE;
376
            break;
377
        default:
378
            return MB_FALSE;
379
    }
380
    Token* token = 0;
381
    if ( addChar ) token = new Token(ch, tokenType);
382
    else token = new Token(tokenType);
383
384
    addToken(token);
385
    return MB_TRUE;
386
} //-- matchDelimiter
387
388
/**
389
 * Returns true if the value of the given String matches
390
 * an OperatorName
391
**/
392
MBool ExprLexer::matchesOperator(String& buffer) {
393
394
    int index = 0;
395
    while (index < NUMBER_OF_TOKENS) {
396
        Token tok = TOKENS[index++];
397
        if ( tok.value.isEqual(buffer) ) {
398
            if (isOperatorToken( &tok )) return MB_TRUE;
399
        }
348
        }
400
    }
349
        break;
401
    return MB_FALSE;
350
      case PERIOD:
402
351
        // period can be .., .(DIGITS)+ or ., check next
403
} //-- matchesOperator
352
        if (++iter < size) {
404
353
          ch=pattern.charAt(iter);
405
/**
354
          if (isDigit(ch)) {
406
 * Matches the given String to the appropriate Token
355
            start=iter-1;
407
 * @param buffer the current StringBuffer representing the value of the Token
356
            while (++iter < size && 
408
 * @param ch, the current delimiter token
357
                   isDigit(pattern.charAt(iter))) /* just go */;
409
**/
358
            addToken(new Token(pattern.subString(start,iter,subStr),
410
void ExprLexer::matchToken(String& buffer, UNICODE_CHAR ch) {
359
                               Token::NUMBER));
411
360
          } else if (ch==PERIOD) {
412
    if ( buffer.length() == 0) return;
361
            addToken(new Token(pattern.subString(iter-1,iter++,subStr),
413
362
                               Token::PARENT_NODE));
414
    Token* match = new Token();
363
          } else
415
    MBool foundMatch = MB_FALSE;
364
            addToken(new Token(PERIOD, Token::SELF_NODE));
416
    int index = 0;
365
        } else
417
366
          addToken(new Token(ch, Token::SELF_NODE));
418
    //-- check previous token
367
        // iter++ is already in the number test
419
    switch(prevToken->type) {
368
        
420
        case Token::VAR_REFERENCE :
369
        break;
421
            if ( prevToken->value.length() == 0) {
370
      case COLON: // QNames are dealt above, must be axis ident
422
                prevToken->value.append(buffer);
371
        if (++iter < size && pattern.charAt(iter)==COLON &&
423
                buffer.clear();
372
            prevToken->type == Token::CNAME) {
424
                return;
373
          prevToken->type = Token::AXIS_IDENTIFIER;
425
            }
374
          ++iter;
426
            break;
375
        } else {
427
        default:
376
          // XXX Error report "colon is neither QName nor axis"
428
            break;
377
          errorPos = iter;
429
    }
378
          errorCode = ERROR_COLON;
430
379
          if (firstItem)
431
    //-- look for next match
380
            firstItem->token->type=Token::ERROR;
432
    while ( !foundMatch && (index < NUMBER_OF_TOKENS) ) {
381
          else
433
382
            addToken(new Token('\0',Token::ERROR));
434
        Token tok = TOKENS[index++];
383
          iter=size; // bail
435
436
        if ( tok.value.isEqual(buffer) ) {
437
438
            foundMatch = MB_TRUE;
439
440
            switch (tok.type) {
441
442
                //-- NodeType tokens
443
                case Token::COMMENT:
444
                case Token::NODE :
445
                case Token::PROC_INST :
446
                case Token::TEXT :
447
                    // make sure next delimiter is '('
448
                    if ( ch != L_PAREN) {
449
                        foundMatch = MB_FALSE;
450
                        break;
451
                    }
452
                    //-- copy buffer
453
                    match->value = buffer;
454
                    //-- copy type
455
                    match->type = tok.type;
456
                    break;
457
               case Token::MULTIPLY_OP :
458
               case Token::DIVIDE_OP:
459
               case Token::MODULUS_OP:
460
                    switch ( prevToken->type ) {
461
                        case Token::AT_SIGN :
462
                        case Token::NULL_TOKEN:
463
                        case Token::L_PAREN:
464
                        case Token::L_BRACKET:
465
                            foundMatch = MB_FALSE;
466
                            break; //-- do not match
467
                        default:
468
                            if ( isOperatorToken(prevToken) ) {
469
                                foundMatch = MB_FALSE;
470
                                break; //-- do not match
471
                            }
472
                            match->value = buffer;
473
                            match->type = tok.type;
474
                    }
475
                    break;
476
               default :
477
                    //-- copy buffer
478
                    match->value = buffer;
479
                    match->type = tok.type;
480
                    break;
481
            }
482
        } //-- if equal
483
    } //-- while
484
485
    if (!foundMatch) {
486
        //-- copy buffer
487
        match->value = buffer;
488
        //-- look for function name
489
        if ( ch == L_PAREN) match->type = Token::FUNCTION_NAME;
490
        else match->type = Token::CNAME;
491
    }
492
    addToken(match);
493
    buffer.clear();
494
} //-- matchToken
495
496
/**
497
 *  Parses the given String into the set of Tokens
498
**/
499
void ExprLexer::parse(const String& pattern) {
500
501
502
    String tokenBuffer;
503
    UNICODE_CHAR inLiteral = '\0';
504
    MBool inNumber  = MB_FALSE;
505
506
    Int32 currentPos = 0;
507
508
    UNICODE_CHAR ch = '\0';
509
    UNICODE_CHAR prevCh = ch;
510
511
    //-- initialize previous token, this will automatically get
512
    //-- deleted when it goes out of scope
513
    Token nullToken('\0', Token::NULL_TOKEN);
514
515
    prevToken = &nullToken;
516
517
    while (currentPos < pattern.length()) {
518
519
        prevCh = ch;
520
        ch = pattern.charAt(currentPos);
521
522
        if ( inLiteral ) {
523
            //-- look for end of literal
524
            if ( ch == inLiteral ) {
525
                inLiteral = '\0';
526
                addToken(new Token(tokenBuffer, Token::LITERAL));
527
                tokenBuffer.clear();
528
            }
529
            else {
530
                tokenBuffer.append(ch);
531
            }
532
        }
384
        }
533
        else if ( inNumber ) {
385
        break;
534
            if (isDigit(ch) || (ch == '.')) {
386
      case FORWARD_SLASH :
535
                tokenBuffer.append(ch);
387
        if (++iter < size && pattern.charAt(iter)==ch) {
536
            }
388
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
537
            else {
389
                             Token::ANCESTOR_OP));
538
                inNumber = MB_FALSE;
390
        } else {
539
                addToken(new Token(tokenBuffer, Token::NUMBER));
391
          addToken(new Token(ch, Token::PARENT_OP));
540
                tokenBuffer.clear();
541
                //-- push back last char
542
                --currentPos;
543
            }
544
        }
392
        }
545
        else if (isDigit(ch)) {
393
        break;
546
            if  ((tokenBuffer.length() == 0 ) || matchesOperator(tokenBuffer) ) {
394
      case BANG : // can only be !=
547
                //-- match operator and free up token buffer
395
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
548
                matchToken(tokenBuffer, ch);
396
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
549
                inNumber = MB_TRUE;
397
                             Token::NOT_EQUAL_OP));
550
            }
398
        } else {
551
            else if (( tokenBuffer.length() == 1 ) && (prevCh = '-')) {
399
          // Error ! is not not()
552
                inNumber = MB_TRUE;
400
          errorPos = iter;
553
            }
401
          errorCode = ERROR_BANG;
554
            tokenBuffer.append(ch);
402
          if (firstItem)
403
            firstItem->token->type=Token::ERROR;
404
          else
405
            addToken(new Token('\0',Token::ERROR));
406
          iter=size; // bail
555
        }
407
        }
556
        else {
408
        break;
557
            switch (ch) {
409
      case EQUAL:
558
                //-- ignore whitespace
410
        addToken(new Token(ch,Token::EQUAL_OP));
559
                case SPACE:
411
        ++iter;
560
                case TX_TAB:
412
        break;
561
                case TX_CR:
413
      case L_ANGLE:
562
                case TX_LF:
414
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
563
                    break;
415
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
564
                case S_QUOTE :
416
                             Token::LESS_OR_EQUAL_OP));
565
                case D_QUOTE :
417
        } else
566
                    matchToken(tokenBuffer, ch);
418
          addToken(new Token(ch,Token::LESS_THAN_OP));
567
                    inLiteral = ch;
419
        break;
568
                    break;
420
      case R_ANGLE:
569
                case PERIOD:
421
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
570
                    if ( inNumber ) tokenBuffer.append(ch);
422
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
571
                    else if ( prevToken->type == Token::SELF_NODE ) {
423
                             Token::GREATER_OR_EQUAL_OP));
572
                        prevToken->type = Token::PARENT_NODE;
424
        } else
573
                    }
425
          addToken(new Token(ch,Token::GREATER_THAN_OP));
574
                    else if ( tokenBuffer.length() > 0 )
426
        break;
575
                        tokenBuffer.append(ch);
427
      case HYPHEN :
576
                    else matchDelimiter(ch);
428
        addToken(new Token(ch,Token::SUBTRACTION_OP));
577
                    break;
429
        ++iter;
578
                case COLON:
430
        break;
579
                    if ( prevCh == ch) {
431
      case ASTERIX:
580
                        Int32 bufSize = tokenBuffer.length();
432
        if (nextIsOperatorToken(prevToken))
581
                        tokenBuffer.setLength(bufSize-1);
433
          addToken(new Token(ch,Token::MULTIPLY_OP));
582
                        addToken(new Token(tokenBuffer, Token::AXIS_IDENTIFIER));
434
        else
583
                        tokenBuffer.clear();
435
          addToken(new Token(ch,Token::CNAME));
584
                    }
436
        ++iter;
585
                    else tokenBuffer.append(ch);
437
        break;
586
                    break;
438
      case L_PAREN:
587
                case FORWARD_SLASH :
439
        if (prevToken->type == Token::CNAME) {
588
                    matchToken(tokenBuffer, ch);
440
          if (prevToken->value.isEqual(COMMENT))
589
                    if ( prevToken->type == Token::PARENT_OP ) {
441
            prevToken->type = Token::COMMENT;
590
                        prevToken->type = Token::ANCESTOR_OP;
442
          else if (prevToken->value.isEqual(NODE))
591
                        prevToken->value.append(ch);
443
            prevToken->type = Token::NODE;
592
                    }
444
          else if (prevToken->value.isEqual(PROC_INST))
593
                    //-- handle possible error in using /
445
            prevToken->type = Token::PROC_INST;
594
                    else if ( prevToken->type == Token::NUMBER ) {
446
          else if (prevToken->value.isEqual(TEXT))
595
                        prevToken->type = Token::ERROR;
447
            prevToken->type = Token::TEXT;
596
                        prevToken->value = "Error in expression, misuse of '/', try 'div' instead.";
448
          else
597
                    }
449
            prevToken->type = Token::FUNCTION_NAME;
598
                    else matchDelimiter(ch);
599
                    break;
600
                case BANG : //-- used as previous...see EQUAL
601
                    matchToken(tokenBuffer,ch);
602
                    addToken(new Token(ch, Token::ERROR));
603
                    break;
604
                case EQUAL:
605
                    switch ( prevCh ) {
606
                        case BANG:
607
                            prevToken->type = Token::NOT_EQUAL_OP;
608
                            prevToken->value.append("=");
609
                            break;
610
                        case L_ANGLE:
611
                            prevToken->type = Token::LESS_OR_EQUAL_OP;
612
                            prevToken->value.append("=");
613
                            break;
614
                        case R_ANGLE:
615
                            prevToken->type = Token::GREATER_OR_EQUAL_OP;
616
                            prevToken->value.append("=");
617
                            break;
618
                        default:
619
                            matchToken(tokenBuffer, ch);
620
                            matchDelimiter(ch);
621
                            break;
622
                    }
623
                    break;
624
                case L_ANGLE :
625
                case R_ANGLE :
626
                    matchToken(tokenBuffer, ch);
627
                    matchDelimiter(ch);
628
                    break;
629
                case HYPHEN :
630
                    if ( isValidQName(tokenBuffer) && 
631
                         !( prevCh==SPACE || prevCh==TX_TAB||
632
                            prevCh==TX_CR || prevCh==TX_LF ) )
633
                        tokenBuffer.append(ch);
634
                    else {
635
                        switch ( prevToken->type ) {
636
                            case Token::NULL_TOKEN:
637
                            case Token::L_PAREN:
638
                            case Token::L_BRACKET:
639
                            case Token::COMMA:
640
                                inNumber = MB_TRUE;
641
                                tokenBuffer.append(ch);
642
                                break;
643
                            default:
644
                                matchToken(tokenBuffer, ch);
645
                                matchDelimiter(ch);
646
                                break;
647
                        }
648
                    }
649
                    break;
650
                case ASTERIX:
651
                    matchToken(tokenBuffer, ch);
652
                    switch ( prevToken->type ) {
653
                        //-- temporary fix for Namespace wild-cards - KV
654
                        case Token::CNAME :
655
                            prevToken->value.append(ch);
656
                            break;
657
                        //-- end temporary fix for Namespace wild-cards
658
659
                        //-- Fix: make sure check for axis identifier wild cards, such as
660
                        //-- ancestor::* - Marina M.
661
                        case Token::AXIS_IDENTIFIER :
662
                        //-- End Fix
663
                        case Token::PARENT_OP :
664
                        case Token::ANCESTOR_OP:
665
                        case Token::AT_SIGN :
666
                        case Token::NULL_TOKEN:
667
                        case Token::L_PAREN:
668
                        case Token::L_BRACKET:
669
                            tokenBuffer.append(ch);
670
                            //matchDelimiter(ch);
671
                            break;
672
                        default:
673
                            if ( isOperatorToken(prevToken) ) {
674
                                matchDelimiter(ch);
675
                                break; //-- do not match
676
                            }
677
                            addToken( new Token(ch, Token::MULTIPLY_OP) );
678
                    }
679
                    break;
680
                case L_PAREN:
681
                case R_PAREN:
682
                case L_BRACKET:
683
                case R_BRACKET:
684
                case COMMA:
685
                case AT_SIGN :
686
                case PLUS:
687
                case DOLLAR_SIGN :
688
                    matchToken(tokenBuffer, ch);
689
                    matchDelimiter(ch);
690
                    break;
691
                case VERT_BAR:
692
                    matchToken(tokenBuffer, ch);
693
                    matchDelimiter(ch);
694
                    //-- Reset previous token to Null, since this is the "Union Operator"
695
                    //-- and the next set of tokens should start as a fresh expression
696
                    prevToken = &nullToken;
697
                    break;
698
                default:
699
                    switch (prevCh) {
700
                        case SPACE :
701
                        case TX_TAB :
702
                        case TX_CR :
703
                        case TX_LF :
704
                            matchToken(tokenBuffer, ch);
705
                            tokenBuffer.append(ch);
706
                            break;
707
                        default:
708
                            tokenBuffer.append(ch);
709
                            break;
710
                    }
711
                    break;
712
            }
713
        }
450
        }
714
        ++currentPos;
451
        ++iter;
715
    }
452
        addToken(new Token(ch,Token::L_PAREN));
716
    //-- end lexical parsing of current token
453
        break;
717
    //-- freeBuffer if needed
454
      case R_PAREN:
718
455
        ++iter;
719
    if ( inNumber ) {
456
        addToken(new Token(ch,Token::R_PAREN));
720
        addToken(new Token(tokenBuffer, Token::NUMBER));
457
        break;
458
      case L_BRACKET:
459
        ++iter;
460
        addToken(new Token(ch,Token::L_BRACKET));
461
        break;
462
      case R_BRACKET:
463
        ++iter;
464
        addToken(new Token(ch,Token::R_BRACKET));
465
        break;
466
      case COMMA:
467
        ++iter;
468
        addToken(new Token(ch,Token::COMMA));
469
        break;
470
      case AT_SIGN :
471
        ++iter;
472
        addToken(new Token(ch,Token::AT_SIGN));
473
        break;
474
      case PLUS:
475
        ++iter;
476
        addToken(new Token(ch,Token::ADDITION_OP));
477
        break;
478
      case VERT_BAR:
479
        ++iter;
480
        addToken(new Token(ch,Token::UNION_OP));
481
        break;
482
      default:
483
        // Error, don't grok character :-(
484
        errorPos = iter;
485
        errorCode = ERROR_UNKNOWN_CHAR;
486
        if (firstItem)
487
          firstItem->token->type=Token::ERROR;
488
        else
489
          addToken(new Token('\0',Token::ERROR));
490
        iter=size; // bail       
491
      }
721
    }
492
    }
722
    else matchToken(tokenBuffer, ch);
493
  }    
723
    prevToken = 0;
724
} //-- parse
494
} //-- parse
725
495
(-)ExprLexer.h (-63 / +53 lines)
Line     Link Here 
 Lines 1-4    Link Here 
1
/*
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * The contents of this file are subject to the Mozilla Public
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
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
4
 * except in compliance with the License. You may obtain a copy of
 Lines 24-31    Link Here 
24
 * Larry Fitzpatrick
24
 * Larry Fitzpatrick
25
 *    -- changed constant short declarations in Token and ExprLexer to
25
 *    -- changed constant short declarations in Token and ExprLexer to
26
 *       enumerations, commented with //--LF
26
 *       enumerations, commented with //--LF
27
 * 
27
 *
28
 * $Id: ExprLexer.h,v 1.7 2001/05/12 11:59:51 peterv%netscape.com Exp $
29
 */
28
 */
30
29
31
30
 Lines 41-47    Link Here 
41
 * This class was ported from XSL:P, an open source Java based 
40
 * This class was ported from XSL:P, an open source Java based 
42
 * XSLT processor, written by yours truly.
41
 * XSLT processor, written by yours truly.
43
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
42
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
44
 * @version $Revision: 1.7 $ $Date: 2001/05/12 11:59:51 $
45
**/
43
**/
46
class Token {
44
class Token {
47
45
 Lines 60-107    Link Here 
60
        LITERAL,
58
        LITERAL,
61
        NUMBER,
59
        NUMBER,
62
        CNAME,
60
        CNAME,
63
        L_PAREN,
64
        R_PAREN,
65
        L_BRACKET,
66
        R_BRACKET,
67
        COMMA,
68
        FUNCTION_NAME,
61
        FUNCTION_NAME,
69
        AT_SIGN,
70
        VAR_REFERENCE,
62
        VAR_REFERENCE,
71
        PARENT_NODE,
63
        PARENT_NODE,
72
        SELF_NODE,
64
        SELF_NODE,
65
        R_PAREN,
66
        R_BRACKET, // 10
67
        /**
68
         * start of tokens for 3.7, bullet 1
69
         * ExprLexer::nextIsOperatorToken bails if the tokens aren't
70
         * consecutive.
71
         **/
72
        COMMA,
73
        AT_SIGN,
74
        L_PAREN,
75
        L_BRACKET,
73
        AXIS_IDENTIFIER,
76
        AXIS_IDENTIFIER,
74
          //-------------/
77
          //-------------/
75
         //- operators -/
78
         //- operators -/
76
        //-------------/
79
        //-------------/
77
80
78
        //-- boolean ops
81
        //-- boolean ops
79
        AND_OP,
82
        AND_OP, // 16
80
        OR_OP,
83
        OR_OP,
81
84
82
        //-- relational
85
        //-- relational
83
        EQUAL_OP,
86
        EQUAL_OP, // 18
84
        NOT_EQUAL_OP,
87
        NOT_EQUAL_OP,
85
        LESS_THAN_OP,
88
        LESS_THAN_OP,
86
        GREATER_THAN_OP,
89
        GREATER_THAN_OP,
87
        LESS_OR_EQUAL_OP,
90
        LESS_OR_EQUAL_OP,
88
        GREATER_OR_EQUAL_OP,
91
        GREATER_OR_EQUAL_OP,
89
        //-- additive operators
92
        //-- additive operators
90
        ADDITION_OP,
93
        ADDITION_OP, // 24
91
        SUBTRACTION_OP,
94
        SUBTRACTION_OP,
92
        //-- multiplicative
95
        //-- multiplicative
93
        DIVIDE_OP ,
96
        DIVIDE_OP , // 26
94
        MULTIPLY_OP,
97
        MULTIPLY_OP,
95
        MODULUS_OP,
98
        MODULUS_OP,
96
        //-- path operators
99
        //-- path operators
97
        PARENT_OP,
100
        PARENT_OP, // 29
98
        ANCESTOR_OP,
101
        ANCESTOR_OP,
99
        UNION_OP,
102
        UNION_OP,
103
        /**
104
         * end of tokens for 3.7, bullet 1 -/
105
         **/
100
        //-- node type tokens
106
        //-- node type tokens
101
        COMMENT,
107
        COMMENT, // 32
102
        NODE,
108
        NODE,
103
        PROC_INST,
109
        PROC_INST,
104
        TEXT
110
        TEXT,
111
        
112
        //-- Special endtoken
113
        END // 36
105
    };
114
    };
106
115
107
116
 Lines 166-171    Link Here 
166
        TX_LF             = '\r'
175
        TX_LF             = '\r'
167
    };
176
    };
168
177
178
    enum _error_consts {
179
        ERROR_UNRESOLVED_VAR_REFERENCE = 0,
180
        ERROR_OP_EXPECTED,
181
        ERROR_UNCLOSED_LITERAL,
182
        ERROR_COLON,
183
        ERROR_BANG,
184
        ERROR_UNKNOWN_CHAR
185
    };
186
    static const String error_message[];
187
    Int32 errorPos;
188
    short errorCode;
169
189
170
    /*
190
    /*
171
     * Complex Tokens
191
     * Complex Tokens
 Lines 197-227    Link Here 
197
217
198
    ~ExprLexer();
218
    ~ExprLexer();
199
219
200
    /**
201
     * Counts the total number of tokens in this Lexer, even if the token
202
     * has already been seen
203
     * @return the total number of tokens in this Lexer
204
    **/
205
    int countAllTokens();
206
207
    /**
208
     * Counts the remaining number of tokens in this Lexer
209
     * @return the number of remaining tokens in this Lexer
210
    **/
211
    int countRemainingTokens();
212
213
    /**
220
    /**
214
     * Returns the type of token that was last return by a call to nextToken
221
     * Functions for iterating over the TokenList
215
    **/
222
    **/
216
223
217
    Token* lookAhead(int offset);
218
    Token* nextToken();
224
    Token* nextToken();
219
    Token* peek();
225
    Token* peek();
220
    void   pushBack();
226
    void   pushBack();
221
    MBool  hasMoreTokens();
227
    MBool  hasMoreTokens();
222
228
223
    MBool isOperatorToken(Token* token);
224
225
private:
229
private:
226
230
227
    struct TokenListItem {
231
    struct TokenListItem {
 Lines 237-286    Link Here 
237
    int tokenCount;
241
    int tokenCount;
238
242
239
    Token* prevToken;
243
    Token* prevToken;
244
    Token endToken;
240
245
241
    void addToken(Token* token);
246
    void addToken(Token* token);
242
247
243
    /**
248
    /**
244
     * Returns true if the given character represents an Alpha letter
249
     * Returns true if the following Token should be an operator.
245
    **/
250
     * This is a helper for the first bullet of [XPath 3.7]
246
    static MBool isAlphaChar(Int32 ch);
251
     *  Lexical Structure
252
     **/
253
    MBool nextIsOperatorToken(Token* token);
247
254
248
    /**
255
    /**
249
     * Returns true if the given character represents a numeric letter (digit)
256
     * Returns true if the given character represents an Alpha letter
257
     * Implemented in ExprLexerChars.cpp
250
    **/
258
    **/
251
    static MBool isDigit(Int32 ch);
259
    static MBool isLetter(UNICODE_CHAR ch);
252
260
253
    /**
261
    /**
254
     * Returns true if the given character is an allowable QName character
262
     * Returns true if the given character represents a numeric letter (digit)
263
     * Implemented in ExprLexerChars.cpp
255
    **/
264
    **/
256
    static MBool isQNameChar(Int32 ch);
265
    static MBool isDigit(UNICODE_CHAR ch);
257
266
258
    /**
267
    /**
259
     * Returns true if the given character is an allowable NCName character
268
     * Returns true if the given character is an allowable NCName character
260
    **/
269
     * Implemented in ExprLexerChars.cpp
261
    static MBool isNCNameChar(Int32 ch);
262
263
    /**
264
     * Returns true if the given String is a valid XML QName
265
    **/
266
    static MBool isValidQName(String& name);
267
268
    MBool matchDelimiter(UNICODE_CHAR ch);
269
270
    /**
271
     * Returns true if the value of the given String matches
272
     * an OperatorName
273
    **/
270
    **/
274
    MBool matchesOperator(String& buffer);
271
    static MBool isNCNameChar(UNICODE_CHAR ch);
275
276
    /**
277
     * Matches the given String to the appropriate Token
278
     * @param buffer the current StringBuffer representing the value of the Token
279
     * @param ch, the current delimiter token
280
    **/
281
    void matchToken(String& buffer, UNICODE_CHAR ch);
282
283
272
273
    String subStr;
284
    void parse(const String& pattern);
274
    void parse(const String& pattern);
285
275
286
}; //-- ExprLexer
276
}; //-- ExprLexer
(-)source/xpath/ExprLexerChars.cpp (+373 lines)
Added Link Here 
Added Link Here 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 
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 mozilla.org code.
13
 *
14
 * The Initial Developer of the Original Code is Axel Hecht.  Portions
15
 * created by Axel Hecht are Copyright (C) 2001 Axel Hecht. All
16
 * Rights Reserved.
17
 *
18
 * Contributor(s): 
19
 *   Axel Hecht <axel@pike.org> (Original Author)
20
 */
21
22
#include "ExprLexer.h"
23
24
// macros for inclusion of char range headers
25
#define TX_CHAR_RANGE(a,b) if (ch<a) return MB_FALSE; \
26
  if (ch<=b) return MB_TRUE
27
#define TX_MATCH_CHAR(a) if (ch<a) return MB_FALSE; \
28
  if (ch==a) return MB_TRUE
29
30
/**
31
 * Returns true if the given character represents a numeric letter (digit)
32
**/
33
MBool ExprLexer::isDigit(UNICODE_CHAR ch)
34
{
35
  TX_CHAR_RANGE('0','9');
36
  return MB_FALSE;
37
} //-- isDigit
38
39
/**
40
 * Returns true if the given character represents an Alpha letter
41
**/
42
MBool ExprLexer::isLetter(UNICODE_CHAR ch)
43
{
44
/* Letter = BaseChar | Ideographic; and _ */
45
  TX_CHAR_RANGE(0x0041,0x005A);
46
  TX_MATCH_CHAR(0x005F);        /* '_' */
47
  TX_CHAR_RANGE(0x0061,0x007A);
48
  TX_CHAR_RANGE(0x00C0,0x00D6);
49
  TX_CHAR_RANGE(0x00D8,0x00F6);
50
  TX_CHAR_RANGE(0x00F8,0x00FF);
51
  TX_CHAR_RANGE(0x0100,0x0131);
52
  TX_CHAR_RANGE(0x0134,0x013E);
53
  TX_CHAR_RANGE(0x0141,0x0148);
54
  TX_CHAR_RANGE(0x014A,0x017E);
55
  TX_CHAR_RANGE(0x0180,0x01C3);
56
  TX_CHAR_RANGE(0x01CD,0x01F0);
57
  TX_CHAR_RANGE(0x01F4,0x01F5);
58
  TX_CHAR_RANGE(0x01FA,0x0217);
59
  TX_CHAR_RANGE(0x0250,0x02A8);
60
  TX_CHAR_RANGE(0x02BB,0x02C1);
61
  TX_MATCH_CHAR(0x0386);
62
  TX_CHAR_RANGE(0x0388,0x038A);
63
  TX_MATCH_CHAR(0x038C);
64
  TX_CHAR_RANGE(0x038E,0x03A1);
65
  TX_CHAR_RANGE(0x03A3,0x03CE);
66
  TX_CHAR_RANGE(0x03D0,0x03D6);
67
  TX_MATCH_CHAR(0x03DA);
68
  TX_MATCH_CHAR(0x03DC);
69
  TX_MATCH_CHAR(0x03DE);
70
  TX_MATCH_CHAR(0x03E0);
71
  TX_CHAR_RANGE(0x03E2,0x03F3);
72
  TX_CHAR_RANGE(0x0401,0x040C);
73
  TX_CHAR_RANGE(0x040E,0x044F);
74
  TX_CHAR_RANGE(0x0451,0x045C);
75
  TX_CHAR_RANGE(0x045E,0x0481);
76
  TX_CHAR_RANGE(0x0490,0x04C4);
77
  TX_CHAR_RANGE(0x04C7,0x04C8);
78
  TX_CHAR_RANGE(0x04CB,0x04CC);
79
  TX_CHAR_RANGE(0x04D0,0x04EB);
80
  TX_CHAR_RANGE(0x04EE,0x04F5);
81
  TX_CHAR_RANGE(0x04F8,0x04F9);
82
  TX_CHAR_RANGE(0x0531,0x0556);
83
  TX_MATCH_CHAR(0x0559);
84
  TX_CHAR_RANGE(0x0561,0x0586);
85
  TX_CHAR_RANGE(0x05D0,0x05EA);
86
  TX_CHAR_RANGE(0x05F0,0x05F2);
87
  TX_CHAR_RANGE(0x0621,0x063A);
88
  TX_CHAR_RANGE(0x0641,0x064A);
89
  TX_CHAR_RANGE(0x0671,0x06B7);
90
  TX_CHAR_RANGE(0x06BA,0x06BE);
91
  TX_CHAR_RANGE(0x06C0,0x06CE);
92
  TX_CHAR_RANGE(0x06D0,0x06D3);
93
  TX_MATCH_CHAR(0x06D5);
94
  TX_CHAR_RANGE(0x06E5,0x06E6);
95
  TX_CHAR_RANGE(0x0905,0x0939);
96
  TX_MATCH_CHAR(0x093D);
97
  TX_CHAR_RANGE(0x0958,0x0961);
98
  TX_CHAR_RANGE(0x0985,0x098C);
99
  TX_CHAR_RANGE(0x098F,0x0990);
100
  TX_CHAR_RANGE(0x0993,0x09A8);
101
  TX_CHAR_RANGE(0x09AA,0x09B0);
102
  TX_MATCH_CHAR(0x09B2);
103
  TX_CHAR_RANGE(0x09B6,0x09B9);
104
  TX_CHAR_RANGE(0x09DC,0x09DD);
105
  TX_CHAR_RANGE(0x09DF,0x09E1);
106
  TX_CHAR_RANGE(0x09F0,0x09F1);
107
  TX_CHAR_RANGE(0x0A05,0x0A0A);
108
  TX_CHAR_RANGE(0x0A0F,0x0A10);
109
  TX_CHAR_RANGE(0x0A13,0x0A28);
110
  TX_CHAR_RANGE(0x0A2A,0x0A30);
111
  TX_CHAR_RANGE(0x0A32,0x0A33);
112
  TX_CHAR_RANGE(0x0A35,0x0A36);
113
  TX_CHAR_RANGE(0x0A38,0x0A39);
114
  TX_CHAR_RANGE(0x0A59,0x0A5C);
115
  TX_MATCH_CHAR(0x0A5E);
116
  TX_CHAR_RANGE(0x0A72,0x0A74);
117
  TX_CHAR_RANGE(0x0A85,0x0A8B);
118
  TX_MATCH_CHAR(0x0A8D);
119
  TX_CHAR_RANGE(0x0A8F,0x0A91);
120
  TX_CHAR_RANGE(0x0A93,0x0AA8);
121
  TX_CHAR_RANGE(0x0AAA,0x0AB0);
122
  TX_CHAR_RANGE(0x0AB2,0x0AB3);
123
  TX_CHAR_RANGE(0x0AB5,0x0AB9);
124
  TX_MATCH_CHAR(0x0ABD);
125
  TX_MATCH_CHAR(0x0AE0);
126
  TX_CHAR_RANGE(0x0B05,0x0B0C);
127
  TX_CHAR_RANGE(0x0B0F,0x0B10);
128
  TX_CHAR_RANGE(0x0B13,0x0B28);
129
  TX_CHAR_RANGE(0x0B2A,0x0B30);
130
  TX_CHAR_RANGE(0x0B32,0x0B33);
131
  TX_CHAR_RANGE(0x0B36,0x0B39);
132
  TX_MATCH_CHAR(0x0B3D);
133
  TX_CHAR_RANGE(0x0B5C,0x0B5D);
134
  TX_CHAR_RANGE(0x0B5F,0x0B61);
135
  TX_CHAR_RANGE(0x0B85,0x0B8A);
136
  TX_CHAR_RANGE(0x0B8E,0x0B90);
137
  TX_CHAR_RANGE(0x0B92,0x0B95);
138
  TX_CHAR_RANGE(0x0B99,0x0B9A);
139
  TX_MATCH_CHAR(0x0B9C);
140
  TX_CHAR_RANGE(0x0B9E,0x0B9F);
141
  TX_CHAR_RANGE(0x0BA3,0x0BA4);
142
  TX_CHAR_RANGE(0x0BA8,0x0BAA);
143
  TX_CHAR_RANGE(0x0BAE,0x0BB5);
144
  TX_CHAR_RANGE(0x0BB7,0x0BB9);
145
  TX_CHAR_RANGE(0x0C05,0x0C0C);
146
  TX_CHAR_RANGE(0x0C0E,0x0C10);
147
  TX_CHAR_RANGE(0x0C12,0x0C28);
148
  TX_CHAR_RANGE(0x0C2A,0x0C33);
149
  TX_CHAR_RANGE(0x0C35,0x0C39);
150
  TX_CHAR_RANGE(0x0C60,0x0C61);
151
  TX_CHAR_RANGE(0x0C85,0x0C8C);
152
  TX_CHAR_RANGE(0x0C8E,0x0C90);
153
  TX_CHAR_RANGE(0x0C92,0x0CA8);
154
  TX_CHAR_RANGE(0x0CAA,0x0CB3);
155
  TX_CHAR_RANGE(0x0CB5,0x0CB9);
156
  TX_MATCH_CHAR(0x0CDE);
157
  TX_CHAR_RANGE(0x0CE0,0x0CE1);
158
  TX_CHAR_RANGE(0x0D05,0x0D0C);
159
  TX_CHAR_RANGE(0x0D0E,0x0D10);
160
  TX_CHAR_RANGE(0x0D12,0x0D28);
161
  TX_CHAR_RANGE(0x0D2A,0x0D39);
162
  TX_CHAR_RANGE(0x0D60,0x0D61);
163
  TX_CHAR_RANGE(0x0E01,0x0E2E);
164
  TX_MATCH_CHAR(0x0E30);
165
  TX_CHAR_RANGE(0x0E32,0x0E33);
166
  TX_CHAR_RANGE(0x0E40,0x0E45);
167
  TX_CHAR_RANGE(0x0E81,0x0E82);
168
  TX_MATCH_CHAR(0x0E84);
169
  TX_CHAR_RANGE(0x0E87,0x0E88);
170
  TX_MATCH_CHAR(0x0E8A);
171
  TX_MATCH_CHAR(0x0E8D);
172
  TX_CHAR_RANGE(0x0E94,0x0E97);
173
  TX_CHAR_RANGE(0x0E99,0x0E9F);
174
  TX_CHAR_RANGE(0x0EA1,0x0EA3);
175
  TX_MATCH_CHAR(0x0EA5);
176
  TX_MATCH_CHAR(0x0EA7);
177
  TX_CHAR_RANGE(0x0EAA,0x0EAB);
178
  TX_CHAR_RANGE(0x0EAD,0x0EAE);
179
  TX_MATCH_CHAR(0x0EB0);
180
  TX_CHAR_RANGE(0x0EB2,0x0EB3);
181
  TX_MATCH_CHAR(0x0EBD);
182
  TX_CHAR_RANGE(0x0EC0,0x0EC4);
183
  TX_CHAR_RANGE(0x0F40,0x0F47);
184
  TX_CHAR_RANGE(0x0F49,0x0F69);
185
  TX_CHAR_RANGE(0x10A0,0x10C5);
186
  TX_CHAR_RANGE(0x10D0,0x10F6);
187
  TX_MATCH_CHAR(0x1100);
188
  TX_CHAR_RANGE(0x1102,0x1103);
189
  TX_CHAR_RANGE(0x1105,0x1107);
190
  TX_MATCH_CHAR(0x1109);
191
  TX_CHAR_RANGE(0x110B,0x110C);
192
  TX_CHAR_RANGE(0x110E,0x1112);
193
  TX_MATCH_CHAR(0x113C);
194
  TX_MATCH_CHAR(0x113E);
195
  TX_MATCH_CHAR(0x1140);
196
  TX_MATCH_CHAR(0x114C);
197
  TX_MATCH_CHAR(0x114E);
198
  TX_MATCH_CHAR(0x1150);
199
  TX_CHAR_RANGE(0x1154,0x1155);
200
  TX_MATCH_CHAR(0x1159);
201
  TX_CHAR_RANGE(0x115F,0x1161);
202
  TX_MATCH_CHAR(0x1163);
203
  TX_MATCH_CHAR(0x1165);
204
  TX_MATCH_CHAR(0x1167);
205
  TX_MATCH_CHAR(0x1169);
206
  TX_CHAR_RANGE(0x116D,0x116E);
207
  TX_CHAR_RANGE(0x1172,0x1173);
208
  TX_MATCH_CHAR(0x1175);
209
  TX_MATCH_CHAR(0x119E);
210
  TX_MATCH_CHAR(0x11A8);
211
  TX_MATCH_CHAR(0x11AB);
212
  TX_CHAR_RANGE(0x11AE,0x11AF);
213
  TX_CHAR_RANGE(0x11B7,0x11B8);
214
  TX_MATCH_CHAR(0x11BA);
215
  TX_CHAR_RANGE(0x11BC,0x11C2);
216
  TX_MATCH_CHAR(0x11EB);
217
  TX_MATCH_CHAR(0x11F0);
218
  TX_MATCH_CHAR(0x11F9);
219
  TX_CHAR_RANGE(0x1E00,0x1E9B);
220
  TX_CHAR_RANGE(0x1EA0,0x1EF9);
221
  TX_CHAR_RANGE(0x1F00,0x1F15);
222
  TX_CHAR_RANGE(0x1F18,0x1F1D);
223
  TX_CHAR_RANGE(0x1F20,0x1F45);
224
  TX_CHAR_RANGE(0x1F48,0x1F4D);
225
  TX_CHAR_RANGE(0x1F50,0x1F57);
226
  TX_MATCH_CHAR(0x1F59);
227
  TX_MATCH_CHAR(0x1F5B);
228
  TX_MATCH_CHAR(0x1F5D);
229
  TX_CHAR_RANGE(0x1F5F,0x1F7D);
230
  TX_CHAR_RANGE(0x1F80,0x1FB4);
231
  TX_CHAR_RANGE(0x1FB6,0x1FBC);
232
  TX_MATCH_CHAR(0x1FBE);
233
  TX_CHAR_RANGE(0x1FC2,0x1FC4);
234
  TX_CHAR_RANGE(0x1FC6,0x1FCC);
235
  TX_CHAR_RANGE(0x1FD0,0x1FD3);
236
  TX_CHAR_RANGE(0x1FD6,0x1FDB);
237
  TX_CHAR_RANGE(0x1FE0,0x1FEC);
238
  TX_CHAR_RANGE(0x1FF2,0x1FF4);
239
  TX_CHAR_RANGE(0x1FF6,0x1FFC);
240
  TX_MATCH_CHAR(0x2126);
241
  TX_CHAR_RANGE(0x212A,0x212B);
242
  TX_MATCH_CHAR(0x212E);
243
  TX_CHAR_RANGE(0x2180,0x2182);
244
  TX_MATCH_CHAR(0x3007);
245
  TX_CHAR_RANGE(0x3021,0x3029);
246
  TX_CHAR_RANGE(0x3041,0x3094);
247
  TX_CHAR_RANGE(0x30A1,0x30FA);
248
  TX_CHAR_RANGE(0x3105,0x312C);
249
  TX_CHAR_RANGE(0x4E00,0x9FA5);
250
  TX_CHAR_RANGE(0xAC00,0xD7A3);
251
  return MB_FALSE;
252
} //-- isAlphaChar
253
254
/**
255
 * Returns true if the given character is an allowable NCName character
256
**/
257
MBool ExprLexer::isNCNameChar(UNICODE_CHAR ch)
258
{
259
/* NCNameChar = Letter | Digit ('0'-'9') | '.' | '-' | '_'  | 
260
   CombiningChar | Extender */
261
  if (isLetter(ch)) return MB_TRUE;  /* Letter | '_' */
262
263
  TX_CHAR_RANGE(0x002D,0x002E);  /* '-' | '.' */
264
  TX_CHAR_RANGE(0x0030,0x0039);  /* Digit */
265
  TX_MATCH_CHAR(0x00B7);
266
  TX_MATCH_CHAR(0x02D0);
267
  TX_MATCH_CHAR(0x02D1);
268
  TX_CHAR_RANGE(0x0300,0x0345);
269
  TX_CHAR_RANGE(0x0360,0x0361);
270
  TX_MATCH_CHAR(0x0387);
271
  TX_CHAR_RANGE(0x0483,0x0486);
272
  TX_CHAR_RANGE(0x0591,0x05A1);
273
  TX_CHAR_RANGE(0x05A3,0x05B9);
274
  TX_CHAR_RANGE(0x05BB,0x05BD);
275
  TX_MATCH_CHAR(0x05BF);
276
  TX_CHAR_RANGE(0x05C1,0x05C2);
277
  TX_MATCH_CHAR(0x05C4);
278
  TX_MATCH_CHAR(0x0640);
279
  TX_CHAR_RANGE(0x064B,0x0652);
280
  TX_MATCH_CHAR(0x0670);
281
  TX_CHAR_RANGE(0x06D6,0x06DC);
282
  TX_CHAR_RANGE(0x06DD,0x06DF);
283
  TX_CHAR_RANGE(0x06E0,0x06E4);
284
  TX_CHAR_RANGE(0x06E7,0x06E8);
285
  TX_CHAR_RANGE(0x06EA,0x06ED);
286
  TX_CHAR_RANGE(0x0901,0x0903);
287
  TX_MATCH_CHAR(0x093C);
288
  TX_CHAR_RANGE(0x093E,0x094C);
289
  TX_MATCH_CHAR(0x094D);
290
  TX_CHAR_RANGE(0x0951,0x0954);
291
  TX_CHAR_RANGE(0x0962,0x0963);
292
  TX_CHAR_RANGE(0x0981,0x0983);
293
  TX_MATCH_CHAR(0x09BC);
294
  TX_MATCH_CHAR(0x09BE);
295
  TX_MATCH_CHAR(0x09BF);
296
  TX_CHAR_RANGE(0x09C0,0x09C4);
297
  TX_CHAR_RANGE(0x09C7,0x09C8);
298
  TX_CHAR_RANGE(0x09CB,0x09CD);
299
  TX_MATCH_CHAR(0x09D7);
300
  TX_CHAR_RANGE(0x09E2,0x09E3);
301
  TX_MATCH_CHAR(0x0A02);
302
  TX_MATCH_CHAR(0x0A3C);
303
  TX_MATCH_CHAR(0x0A3E);
304
  TX_MATCH_CHAR(0x0A3F);
305
  TX_CHAR_RANGE(0x0A40,0x0A42);
306
  TX_CHAR_RANGE(0x0A47,0x0A48);
307
  TX_CHAR_RANGE(0x0A4B,0x0A4D);
308
  TX_CHAR_RANGE(0x0A70,0x0A71);
309
  TX_CHAR_RANGE(0x0A81,0x0A83);
310
  TX_MATCH_CHAR(0x0ABC);
311
  TX_CHAR_RANGE(0x0ABE,0x0AC5);
312
  TX_CHAR_RANGE(0x0AC7,0x0AC9);
313
  TX_CHAR_RANGE(0x0ACB,0x0ACD);
314
  TX_CHAR_RANGE(0x0B01,0x0B03);
315
  TX_MATCH_CHAR(0x0B3C);
316
  TX_CHAR_RANGE(0x0B3E,0x0B43);
317
  TX_CHAR_RANGE(0x0B47,0x0B48);
318
  TX_CHAR_RANGE(0x0B4B,0x0B4D);
319
  TX_CHAR_RANGE(0x0B56,0x0B57);
320
  TX_CHAR_RANGE(0x0B82,0x0B83);
321
  TX_CHAR_RANGE(0x0BBE,0x0BC2);
322
  TX_CHAR_RANGE(0x0BC6,0x0BC8);
323
  TX_CHAR_RANGE(0x0BCA,0x0BCD);
324
  TX_MATCH_CHAR(0x0BD7);
325
  TX_CHAR_RANGE(0x0C01,0x0C03);
326
  TX_CHAR_RANGE(0x0C3E,0x0C44);
327
  TX_CHAR_RANGE(0x0C46,0x0C48);
328
  TX_CHAR_RANGE(0x0C4A,0x0C4D);
329
  TX_CHAR_RANGE(0x0C55,0x0C56);
330
  TX_CHAR_RANGE(0x0C82,0x0C83);
331
  TX_CHAR_RANGE(0x0CBE,0x0CC4);
332
  TX_CHAR_RANGE(0x0CC6,0x0CC8);
333
  TX_CHAR_RANGE(0x0CCA,0x0CCD);
334
  TX_CHAR_RANGE(0x0CD5,0x0CD6);
335
  TX_CHAR_RANGE(0x0D02,0x0D03);
336
  TX_CHAR_RANGE(0x0D3E,0x0D43);
337
  TX_CHAR_RANGE(0x0D46,0x0D48);
338
  TX_CHAR_RANGE(0x0D4A,0x0D4D);
339
  TX_MATCH_CHAR(0x0D57);
340
  TX_MATCH_CHAR(0x0E31);
341
  TX_CHAR_RANGE(0x0E34,0x0E3A);
342
  TX_MATCH_CHAR(0x0E46);
343
  TX_CHAR_RANGE(0x0E47,0x0E4E);
344
  TX_MATCH_CHAR(0x0EB1);
345
  TX_CHAR_RANGE(0x0EB4,0x0EB9);
346
  TX_CHAR_RANGE(0x0EBB,0x0EBC);
347
  TX_MATCH_CHAR(0x0EC6);
348
  TX_CHAR_RANGE(0x0EC8,0x0ECD);
349
  TX_CHAR_RANGE(0x0F18,0x0F19);
350
  TX_MATCH_CHAR(0x0F35);
351
  TX_MATCH_CHAR(0x0F37);
352
  TX_MATCH_CHAR(0x0F39);
353
  TX_MATCH_CHAR(0x0F3E);
354
  TX_MATCH_CHAR(0x0F3F);
355
  TX_CHAR_RANGE(0x0F71,0x0F84);
356
  TX_CHAR_RANGE(0x0F86,0x0F8B);
357
  TX_CHAR_RANGE(0x0F90,0x0F95);
358
  TX_MATCH_CHAR(0x0F97);
359
  TX_CHAR_RANGE(0x0F99,0x0FAD);
360
  TX_CHAR_RANGE(0x0FB1,0x0FB7);
361
  TX_MATCH_CHAR(0x0FB9);
362
  TX_CHAR_RANGE(0x20D0,0x20DC);
363
  TX_MATCH_CHAR(0x20E1);
364
  TX_MATCH_CHAR(0x3005);
365
  TX_CHAR_RANGE(0x302A,0x302F);
366
  TX_CHAR_RANGE(0x3031,0x3035);
367
  TX_MATCH_CHAR(0x3099);
368
  TX_MATCH_CHAR(0x309A);
369
  TX_CHAR_RANGE(0x309D,0x309E);
370
  TX_CHAR_RANGE(0x30FC,0x30FE);
371
  return MB_FALSE;
372
} //-- isNCNameChar
373
(-)ExprParser.cpp (-361 / +305 lines)
Line     Link Here 
 Lines 1-4    Link Here 
1
/*
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * The contents of this file are subject to the Mozilla Public
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
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
4
 * except in compliance with the License. You may obtain a copy of
 Lines 45-53    Link Here 
45
#include "FunctionLib.h"
45
#include "FunctionLib.h"
46
#include "Names.h"
46
#include "Names.h"
47
47
48
const String ExprParser::L_CURLY_BRACE = "{";
49
const String ExprParser::R_CURLY_BRACE = "}";
50
51
/**
48
/**
52
 * Creates a new ExprParser
49
 * Creates a new ExprParser
53
**/
50
**/
 Lines 60-145    Link Here 
60
57
61
/**
58
/**
62
 * Creates an Attribute Value Template using the given value
59
 * Creates an Attribute Value Template using the given value
60
 * This should move to XSLProcessor class
63
**/
61
**/
64
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
62
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
65
    (const String& attValue)
63
    (const String& attValue)
66
{
64
{
67
65
68
    AttributeValueTemplate* avt = new AttributeValueTemplate();
66
    AttributeValueTemplate* avt = new AttributeValueTemplate();
67
69
    Int32 size = attValue.length();
68
    Int32 size = attValue.length();
69
    if ( size == 0) return avt; //XXX should return 0, but that causes crash in lre12
70
70
    int cc = 0;
71
    int cc = 0;
72
    UNICODE_CHAR nextCh;
73
    UNICODE_CHAR ch;
71
    String buffer;
74
    String buffer;
72
    MBool inExpr    = MB_FALSE;
75
    MBool inExpr    = MB_FALSE;
73
    MBool inLiteral = MB_FALSE;
76
    MBool inLiteral = MB_FALSE;
74
    UNICODE_CHAR endLiteral = '"';
77
    UNICODE_CHAR endLiteral;
75
    UNICODE_CHAR prevCh = '\0';
76
78
77
    while ( cc < size) {
79
    nextCh = attValue.charAt(cc);
78
        UNICODE_CHAR ch = attValue.charAt(cc++);
80
    while ( cc++ < size) {
81
        ch = nextCh;
82
        nextCh = cc != size ? attValue.charAt(cc) : 0;
83
        
79
        // if in literal just add ch to buffer
84
        // if in literal just add ch to buffer
80
        if ( inLiteral && (ch != endLiteral) ) {
85
        if ( inLiteral && (ch != endLiteral) ) {
81
                buffer.append(ch);
86
                buffer.append(ch);
82
                prevCh = ch;
83
                continue;
87
                continue;
84
        }
88
        }
85
        switch ( ch ) {
89
        switch ( ch ) {
86
            case '\'' :
90
            case '\'' :
87
            case '"' :
91
            case '"' :
88
                buffer.append(ch);
92
                buffer.append(ch);
89
                if (inLiteral) inLiteral = MB_FALSE;
93
                if (inLiteral)
90
                else {
94
                    inLiteral = MB_FALSE;
95
                else if (inExpr) {
91
                    inLiteral = MB_TRUE;
96
                    inLiteral = MB_TRUE;
92
                    endLiteral = ch;
97
                    endLiteral = ch;
93
                }
98
                }
94
                break;
99
                break;
95
            case  '{' :
100
            case  '{' :
96
                // Ignore case where we find two { without a }
97
                if (!inExpr) {
101
                if (!inExpr) {
98
                    //-- clear buffer
102
                    // Ignore case where we find two {
99
                    if ( buffer.length() > 0) {
103
                    if ( nextCh == ch ) {
100
                        avt->addExpr(new StringExpr(buffer));
104
                        buffer.append(ch); //-- append '{'
105
                        cc++;
106
                        nextCh = cc != size ? attValue.charAt(cc) : 0;
107
                    }
108
                    else {
109
                        if ( buffer.length() > 0)
110
                            avt->addExpr(new StringExpr(buffer));
101
                        buffer.clear();
111
                        buffer.clear();
112
                        inExpr = MB_TRUE;
102
                    }
113
                    }
103
                    inExpr = MB_TRUE;
104
                }
114
                }
105
                else if (prevCh == ch) {
115
                else
106
                    inExpr = MB_FALSE;
107
                    buffer.append(ch);
108
                }
109
                else {
110
                    buffer.append(ch); //-- simply append '{'
116
                    buffer.append(ch); //-- simply append '{'
111
                    ch = '\0';
112
                }
113
                break;
117
                break;
114
            case '}':
118
            case '}':
115
                if (inExpr) {
119
                if (inExpr) {
116
                    inExpr = MB_FALSE;
120
                    inExpr = MB_FALSE;
117
                    avt->addExpr(createExpr(buffer));
121
                    Expr* expr = createExpr(buffer);
122
                    if (!expr) {
123
                        delete avt;
124
                        return 0;
125
                    }
126
                    avt->addExpr(expr);
118
                    buffer.clear();
127
                    buffer.clear();
119
                    //-- change in case another '}' follows
120
                    ch = '\0';
121
                }
128
                }
122
                else if (prevCh != ch) {
129
                else if (nextCh == ch) {
123
                    if ( buffer.length() > 0) buffer.append('}');
130
                    buffer.append(ch);
124
                    else avt->addExpr(new StringExpr(R_CURLY_BRACE));
131
                    cc++;
132
                    nextCh = cc != size ? attValue.charAt(cc) : 0;
125
                }
133
                }
134
                else {
135
                    //XXX ErrorReport: unmatched '}' found
136
                    delete avt;
137
                    return 0;
138
                }
126
                break;
139
                break;
127
            default:
140
            default:
128
                buffer.append(ch);
141
                buffer.append(ch);
129
                break;
142
                break;
130
        }
143
        }
131
        prevCh = ch;
132
    }
144
    }
133
    if ( buffer.length() > 0) {
145
134
        if ( inExpr ) {
146
    if ( inExpr ) {
135
            //-- error
147
        //XXX ErrorReport: ending '}' missing
136
            String errMsg("#error evaluating AttributeValueTemplate. ");
148
        delete avt;
137
            errMsg.append("Missing '}' after: ");
149
        return 0;
138
            errMsg.append(buffer);
139
            avt->addExpr(new StringExpr(errMsg));
140
        }
141
        else avt->addExpr(new StringExpr(buffer));
142
    }
150
    }
151
152
    if ( buffer.length() > 0)
153
        avt->addExpr(new StringExpr(buffer));
154
143
    return avt;
155
    return avt;
144
156
145
} //-- createAttributeValueTemplate
157
} //-- createAttributeValueTemplate
 Lines 149-157    Link Here 
149
    return createExpr(lexer);
161
    return createExpr(lexer);
150
} //-- createExpr
162
} //-- createExpr
151
163
152
PatternExpr* ExprParser::createPatternExpr(const String& pattern) {
164
Expr* ExprParser::createPatternExpr(const String& pattern) {
153
    ExprLexer lexer(pattern);
165
    ExprLexer lexer(pattern);
154
    return createUnionExpr(lexer);
166
    Expr* expr = createUnionExpr(lexer);
167
    return expr;
155
} //-- createPatternExpr
168
} //-- createPatternExpr
156
169
157
LocationStep* ExprParser::createLocationStep(const String& path) {
170
LocationStep* ExprParser::createLocationStep(const String& path) {
 Lines 216-222    Link Here 
216
} //-- createBinaryExpr
229
} //-- createBinaryExpr
217
230
218
231
219
Expr*  ExprParser::createExpr(ExprLexer& lexer) {
232
Expr* ExprParser::createExpr(ExprLexer& lexer) {
220
233
221
    MBool done = MB_FALSE;
234
    MBool done = MB_FALSE;
222
235
 Lines 224-291    Link Here 
224
237
225
    Stack exprs;
238
    Stack exprs;
226
    Stack ops;
239
    Stack ops;
240
    
241
    while ( !done ) {
227
242
228
    while ( lexer.hasMoreTokens() && (!done)) {
243
        MBool unary = MB_FALSE;
244
        while( lexer.peek()->type == Token::SUBTRACTION_OP ) {
245
            unary = !unary;
246
            lexer.nextToken();
247
        }
248
249
        expr = createUnionExpr(lexer);
250
        if ( !expr )
251
            break;
252
253
        if ( unary )
254
            expr = new UnaryExpr(expr);
229
255
230
        Token* tok = lexer.nextToken();
256
        Token* tok = lexer.nextToken();
231
        switch ( tok->type ) {
257
        switch ( tok->type ) {
232
            case Token::L_BRACKET: // Predicate starts here
233
            case Token::R_BRACKET:
234
            case Token::R_PAREN:
235
            case Token::COMMA :
236
                lexer.pushBack();
237
                done = MB_TRUE;
238
                break;
239
            case Token::L_PAREN: //-- Grouping Expression
240
                expr = createExpr(lexer);
241
                //-- look for end ')'
242
                if ( lexer.hasMoreTokens() &&
243
                        ( lexer.nextToken()->type == Token::R_PAREN ) ) break;
244
                else {
245
                    //-- error
246
                    delete expr;
247
                    expr = new StringExpr("missing ')' in expression");
248
                }
249
                break;
250
            case Token::ANCESTOR_OP:
251
            case Token::PARENT_OP:
252
                lexer.pushBack();
253
                if ( !expr ) expr = createPathExpr(lexer);
254
                else {
255
                    PathExpr* pathExpr = createPathExpr(lexer);
256
                    pathExpr->addPatternExpr(0, (PatternExpr*)expr,
257
                                                 PathExpr::RELATIVE_OP);
258
                    expr = pathExpr;
259
                }
260
                //done = MB_TRUE;
261
                break;
262
            case Token::UNION_OP :
263
            {
264
                UnionExpr* unionExpr = createUnionExpr(lexer);
265
                unionExpr->addPathExpr(0, (PathExpr*)expr );
266
                expr = unionExpr;
267
                done = MB_TRUE;
268
                break;
269
            }
270
            case Token::LITERAL :
271
                expr = new StringExpr(tok->value);
272
                break;
273
            case Token::NUMBER:
274
            {
275
                StringResult str(tok->value);
276
                expr = new NumberExpr(str.numberValue());
277
                break;
278
            }
279
            case Token::FUNCTION_NAME:
280
            {
281
                lexer.pushBack();
282
                expr = createFunctionCall(lexer);
283
                break;
284
            }
285
            case Token::VAR_REFERENCE:
286
                expr = new VariableRefExpr(tok->value);
287
                break;
288
            //-- additive ops
289
            case Token::ADDITION_OP:
258
            case Token::ADDITION_OP:
290
            case Token::DIVIDE_OP:
259
            case Token::DIVIDE_OP:
291
            //-- boolean ops
260
            //-- boolean ops
 Lines 304-331    Link Here 
304
            case Token::MULTIPLY_OP:
273
            case Token::MULTIPLY_OP:
305
            case Token::SUBTRACTION_OP:
274
            case Token::SUBTRACTION_OP:
306
            {
275
            {
307
                if ( !exprs.empty() ) {
276
                while ( !exprs.empty() &&
308
                    short ttype = ((Token*)ops.peek())->type;
277
                        precedenceLevel(tok->type) <= precedenceLevel(((Token*)ops.peek())->type)) {
309
                    if (precedenceLevel(tok->type) < precedenceLevel(ttype)) {
278
                    expr = createBinaryExpr((Expr*)exprs.pop(),
310
                        expr = createBinaryExpr((Expr*)exprs.pop(), expr,
279
                                             expr,
311
                            (Token*)ops.pop());
280
                                             (Token*)ops.pop());
312
                    }
313
                }
281
                }
314
                exprs.push(expr);
282
                exprs.push(expr);
315
                ops.push(tok);
283
                ops.push(tok);
316
                expr = 0; // OG, prevent reuse of expr
317
                break;
284
                break;
318
            }
285
            }
319
            default:
286
            default:
320
                lexer.pushBack();
287
                lexer.pushBack();
321
                expr = createPatternExpr(lexer);
288
                done = MB_TRUE;
322
                break;
289
                break;
323
        }
290
        }
324
    }
291
    }
325
292
326
    // make sure expr != 0, will this happen?
293
    // make sure expr != 0
327
    if (( expr == 0 ) && (!exprs.empty()))
294
    if ( expr == 0 ) {
328
        expr = (Expr*) exprs.pop();
295
        while (!exprs.empty() ) {
296
            delete (Expr*)exprs.pop();
297
        }
298
        return 0;
299
    }
329
300
330
    while (!exprs.empty() ) {
301
    while (!exprs.empty() ) {
331
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
302
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
 Lines 335-401    Link Here 
335
306
336
} //-- createExpr
307
} //-- createExpr
337
308
338
FilterExpr*  ExprParser::createFilterExpr(ExprLexer& lexer) {
309
Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
339
310
340
    FilterExpr* filterExpr = new FilterExpr();
341
    Token* tok = lexer.nextToken();
311
    Token* tok = lexer.nextToken();
342
    if ( !tok ) return filterExpr;
343
312
344
    Expr* expr = 0;
313
    Expr* expr = 0;
345
    switch ( tok->type ) {
314
    switch ( tok->type ) {
346
        case Token::FUNCTION_NAME :
315
        case Token::FUNCTION_NAME :
316
            lexer.pushBack();
347
            expr = createFunctionCall(lexer);
317
            expr = createFunctionCall(lexer);
348
            filterExpr->setExpr(expr);
349
            break;
318
            break;
350
        case Token::VAR_REFERENCE :
319
        case Token::VAR_REFERENCE :
351
            expr = new VariableRefExpr(tok->value);
320
            expr = new VariableRefExpr(tok->value);
352
            filterExpr->setExpr(expr);
353
            break;
321
            break;
354
        case Token::L_PAREN:
322
        case Token::L_PAREN:
355
            //-- primary group expr:
356
            expr = createExpr(lexer);
323
            expr = createExpr(lexer);
357
            tok = lexer.nextToken();
324
            if(!expr) return 0;
358
            if ( (!tok) || (tok->type != Token::R_PAREN ) ) {
325
359
                String errMsg("error: ");
326
            if ( lexer.nextToken()->type != Token::R_PAREN ) {
360
                expr->toString(errMsg);
327
                lexer.pushBack();
361
                errMsg.append(" - missing ')'");
328
                //XXX ErrorReport: right parenthesis expected
362
                delete expr; //-- free up current expr
329
                delete expr;
363
                expr = new ErrorFunctionCall(errMsg);
330
                return 0;
364
            }
331
            }
365
            filterExpr->setExpr(expr);
366
            break;
332
            break;
367
        case Token::PARENT_NODE :
333
        case Token::LITERAL :
368
            expr = new ParentExpr();
334
            expr = new StringExpr(tok->value);
369
            filterExpr->setExpr(expr);
370
            break;
335
            break;
371
        case Token::SELF_NODE :
336
        case Token::NUMBER:
372
            expr = new IdentityExpr();
337
        {
373
            filterExpr->setExpr(expr);
338
            StringResult str(tok->value);
339
            expr = new NumberExpr(str.numberValue());
374
            break;
340
            break;
341
        }
375
        default:
342
        default:
343
            // this should never ever happen.
344
            lexer.pushBack();
345
            //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
346
            return 0;
376
            break;
347
            break;
377
    }
348
    }
349
    if(!expr) return 0;
378
350
379
    //-- handle predicates
351
    if ( lexer.peek()->type == Token::L_BRACKET ) {
380
    parsePredicates(filterExpr, lexer);
381
352
382
    return filterExpr;
353
        FilterExpr* filterExpr = new FilterExpr();
354
        filterExpr->setExpr(expr);
383
355
356
        //-- handle predicates
357
        if(!parsePredicates(filterExpr, lexer)) {
358
            delete filterExpr;
359
            return 0;
360
        }
361
        expr = filterExpr;
362
    }
363
364
    return expr;
365
384
} //-- createFilterExpr
366
} //-- createFilterExpr
385
367
386
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
368
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
387
369
388
    if ( !lexer.hasMoreTokens() ) {
389
        //-- should never see this, I hope
390
        return new ErrorFunctionCall("no tokens, invalid function call");
391
    }
392
393
    FunctionCall* fnCall = 0;
370
    FunctionCall* fnCall = 0;
394
371
395
    Token* tok = lexer.nextToken();
372
    Token* tok = lexer.nextToken();
396
397
    if ( tok->type != Token::FUNCTION_NAME ) {
373
    if ( tok->type != Token::FUNCTION_NAME ) {
398
        return new ErrorFunctionCall("invalid function call");
374
        //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
375
        return 0;
399
    }
376
    }
400
377
401
    String fnName = tok->value;
378
    String fnName = tok->value;
 Lines 491-512    Link Here 
491
        //-- not our job to report an invalid function call here
468
        //-- not our job to report an invalid function call here
492
        fnCall = new ExtensionFunctionCall(fnName);
469
        fnCall = new ExtensionFunctionCall(fnName);
493
    }
470
    }
471
    
494
    //-- handle parametes
472
    //-- handle parametes
495
    List params;
473
    if(!parseParameters(fnCall, lexer)) {
496
    String* errMsg = parseParameters(&params, lexer);
474
        delete fnCall;
497
    if (errMsg) {
475
        return 0;
498
        String err("error with function call, \"");
499
        err.append(fnName);
500
        err.append("\" : ");
501
        err.append(*errMsg);
502
        fnCall = new ErrorFunctionCall(err);
503
        delete errMsg;
504
    }
505
    // copy params
506
    else if (params.getLength() > 0) {
507
        ListIterator* iter = params.iterator();
508
        while ( iter->hasNext() ) fnCall->addParam( (Expr*)iter->next() );
509
        delete iter;
510
    }
476
    }
511
    return fnCall;
477
    return fnCall;
512
} //-- createFunctionCall
478
} //-- createFunctionCall
 Lines 514-522    Link Here 
514
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
480
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
515
481
516
    LocationStep* lstep = new LocationStep();
482
    LocationStep* lstep = new LocationStep();
483
484
    //-- child axis is default
517
    short axisIdentifier = LocationStep::CHILD_AXIS;
485
    short axisIdentifier = LocationStep::CHILD_AXIS;
486
    NodeExpr* nodeExpr = 0;
518
487
519
    //-- get Axis Identifier, if present
488
    //-- get Axis Identifier or AbbreviatedStep, if present
520
    Token* tok = lexer.peek();
489
    Token* tok = lexer.peek();
521
    switch (tok->type) {
490
    switch (tok->type) {
522
        case Token::AXIS_IDENTIFIER:
491
        case Token::AXIS_IDENTIFIER:
 Lines 550-560    Link Here 
550
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
519
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
551
            else if ( SELF_AXIS.isEqual(tok->value) )
520
            else if ( SELF_AXIS.isEqual(tok->value) )
552
                axisIdentifier = LocationStep::SELF_AXIS;
521
                axisIdentifier = LocationStep::SELF_AXIS;
553
            //-- child axis is default
522
            else {
554
            else if (!CHILD_AXIS.isEqual(tok->value)) {
523
                delete lstep;
555
                //-- handle error gracefully, simply ignore invalid axis and
524
                //XXX ErrorReport: unknow axis
556
                //-- use default. Add error message when message observer
525
                return 0;
557
                //-- is implemented
558
            }
526
            }
559
            break;
527
            break;
560
        }
528
        }
 Lines 563-611    Link Here 
563
            lexer.nextToken();
531
            lexer.nextToken();
564
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
532
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
565
            break;
533
            break;
534
        case Token::PARENT_NODE :
535
            //-- eat token
536
            lexer.nextToken();
537
            axisIdentifier = LocationStep::PARENT_AXIS;
538
            nodeExpr = new BasicNodeExpr();
539
            break;
540
        case Token::SELF_NODE :
541
            //-- eat token
542
            lexer.nextToken();
543
            axisIdentifier = LocationStep::SELF_AXIS;
544
            nodeExpr = new BasicNodeExpr();
545
            break;
566
        default:
546
        default:
567
            break;
547
            break;
568
    }
548
    }
569
549
570
    lstep->setAxisIdentifier(axisIdentifier);
550
    //-- get NodeTest unless AbbreviatedStep was found
571
551
    if ( !nodeExpr ) {
572
552
        tok = lexer.nextToken();
573
    NodeExpr* nodeExpr = 0;
553
574
554
        switch(tok->type) {
575
    tok = lexer.peek();
555
            case Token::CNAME :
576
    if (!tok) {
556
                // NameTest
577
        ///XXXXX We need to create an ErrorExpr or something to
557
                // XXX Namespace: handle namespaces here
578
        ///XXXXX handle errors
558
                if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
579
    }
559
                    nodeExpr = new AttributeExpr(tok->value);
580
    // NameTest
560
                else
581
    else if (tok->type == Token::CNAME) {
561
                    nodeExpr = new ElementExpr(tok->value);
582
        //-- handle NameTest
562
                break;
583
        //-- eat token
563
            default:
584
        lexer.nextToken();
564
                lexer.pushBack();
585
        if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
565
                nodeExpr = createNodeExpr(lexer);
586
            nodeExpr = new AttributeExpr(tok->value);
566
                if(!nodeExpr) {
587
        else
567
                    delete lstep;
588
            nodeExpr = new ElementExpr(tok->value);
568
                    return 0;
589
569
                }
590
    }
570
        }
591
    // NodeType
592
    else {
593
       nodeExpr = createNodeExpr(lexer);
594
    }
571
    }
595
572
    
573
    lstep->setAxisIdentifier(axisIdentifier);
596
    lstep->setNodeExpr(nodeExpr);
574
    lstep->setNodeExpr(nodeExpr);
597
575
598
599
600
    //-- handle predicates
576
    //-- handle predicates
601
577
    if(!parsePredicates(lstep, lexer)) {
602
    parsePredicates(lstep, lexer);
578
        delete lstep;
603
579
        return 0;
604
    //<debug>
580
    }
605
    //String tmp;
606
    //lstep->toString(tmp);
607
    //cout << "returning LocationStep: "<< tmp <<endl;
608
    //</debug>
609
581
610
    return lstep;
582
    return lstep;
611
} //-- createLocationPath
583
} //-- createLocationPath
 Lines 616-663    Link Here 
616
**/
588
**/
617
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
589
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
618
590
619
    //cout << "creating NodeExpr: "<<endl;
620
    if (!lexer.hasMoreTokens() )  cout << "Lexer has no Tokens"<<endl;
621
622
    if (!lexer.hasMoreTokens() )  return 0;
623
624
    NodeExpr* nodeExpr = 0;
591
    NodeExpr* nodeExpr = 0;
625
626
    Token* tok = lexer.nextToken();
627
    //cout << "Token #" << tok->type <<endl;
628
    List params;
629
592
630
    String* errMsg = 0;
593
    Token* nodeTok = lexer.nextToken();
631
594
632
    switch ( tok->type ) {
595
    switch ( nodeTok->type ) {
633
        case Token::COMMENT:
596
        case Token::COMMENT:
634
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
597
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
635
            errMsg = parseParameters(&params, lexer);
636
            //-- ignore errMsg for now
637
            delete errMsg;
638
            break;
598
            break;
639
        case Token::NODE :
599
        case Token::NODE :
640
            nodeExpr = new BasicNodeExpr();
600
            nodeExpr = new BasicNodeExpr();
641
            errMsg = parseParameters(&params, lexer);
642
            //-- ignore errMsg for now
643
            delete errMsg;
644
            break;
601
            break;
645
        case Token::PROC_INST :
602
        case Token::PROC_INST :
646
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
603
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
647
            errMsg = parseParameters(&params, lexer);
648
            //-- ignore errMsg for now
649
            delete errMsg;
650
            break;
604
            break;
651
        case Token::TEXT :
605
        case Token::TEXT :
652
            nodeExpr = new TextExpr();
606
            nodeExpr = new TextExpr();
653
            errMsg = parseParameters(&params, lexer);
654
            //-- ignore errMsg for now
655
            delete errMsg;
656
            break;
607
            break;
657
        default:
608
        default:
658
            //XXXX ignore error for now
609
            lexer.pushBack();
610
            // XXX ErrorReport: unexpected token
611
            return 0;
659
            break;
612
            break;
660
    }
613
    }
614
615
    if ( lexer.nextToken()->type != Token::L_PAREN ) {
616
        lexer.pushBack();
617
        //XXX ErrorReport: left parenthesis expected
618
        delete nodeExpr;
619
        return 0;
620
    }
621
    if ( nodeTok->type == Token::PROC_INST &&
622
         lexer.peek()->type == Token::LITERAL ) {
623
        Token* tok = lexer.nextToken();
624
        ((BasicNodeExpr*)nodeExpr)->setNodeName(tok->value);
625
    }
626
    if ( lexer.nextToken()->type != Token::R_PAREN ) {
627
        lexer.pushBack();
628
        //XXX ErrorReport: right parenthesis expected (or literal for pi)
629
        delete nodeExpr;
630
        return 0;
631
    }
632
661
    return nodeExpr;
633
    return nodeExpr;
662
} //-- createNodeExpr
634
} //-- createNodeExpr
663
635
 Lines 665-701    Link Here 
665
 * Creates a PathExpr using the given ExprLexer
637
 * Creates a PathExpr using the given ExprLexer
666
 * @param lexer the ExprLexer for retrieving Tokens
638
 * @param lexer the ExprLexer for retrieving Tokens
667
**/
639
**/
668
PathExpr* ExprParser::createPathExpr(ExprLexer& lexer) {
640
Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
641
642
    Expr* expr = 0;
669
643
644
    Token* tok = lexer.peek();
670
645
671
    //-- check for RootExpr
646
    // is this a root expression?
672
    if ( lexer.countRemainingTokens() == 1 ) {
647
    if ( tok->type == Token::PARENT_OP ) {
673
        if ( lexer.peek()->type == Token::PARENT_OP ) {
648
        lexer.nextToken();
674
            lexer.nextToken(); //-- eat token
649
        if ( !isLocationStepToken(lexer.peek()) )
675
            return new RootExpr();
650
            return new RootExpr;
676
        }
651
652
        lexer.pushBack();
677
    }
653
    }
678
654
679
    PathExpr* pathExpr = new PathExpr();
655
    // parse first step (possibly a FilterExpr)
680
    short ancestryOp = PathExpr::RELATIVE_OP;
656
    if ( tok->type != Token::PARENT_OP &&
657
         tok->type != Token::ANCESTOR_OP ) {
658
        if ( isFilterExprToken(tok) ) {
659
            expr = createFilterExpr(lexer);
660
        }
661
        else
662
            expr = createLocationStep(lexer);
681
663
682
    while ( lexer.hasMoreTokens() ) {
664
        if ( !expr ) {
683
        Token* tok = lexer.nextToken();
665
            return 0;
684
        if ( lexer.isOperatorToken(tok) ) {
685
            lexer.pushBack();
686
            return pathExpr;
687
        }
666
        }
667
        
668
        // is this a singlestep path expression?
669
        tok = lexer.peek();
670
        if ( tok->type != Token::PARENT_OP &&
671
             tok->type != Token::ANCESTOR_OP)
672
            return expr;
673
    }
674
    
675
    //we have a pathexpression containing several steps
676
    PathExpr* pathExpr = new PathExpr();
677
    if(expr)
678
        pathExpr->addExpr(expr, PathExpr::RELATIVE_OP);
679
680
    // this is ugly
681
    while (1) {
682
        short ancestryOp;
683
        tok = lexer.nextToken();
688
        switch ( tok->type ) {
684
        switch ( tok->type ) {
689
            case Token::R_PAREN:
690
            case Token::R_BRACKET:
691
            case Token::UNION_OP:
692
                //Marina, addition start
693
                // When parsing a list of parameters for a function comma should signal a spot
694
                // without it further processing pathExpr was causing "invalid token" error
695
            case Token::COMMA:
696
                // Marina, addition ends
697
                lexer.pushBack();
698
                return pathExpr;
699
            case Token::ANCESTOR_OP :
685
            case Token::ANCESTOR_OP :
700
                ancestryOp = PathExpr::ANCESTOR_OP;
686
                ancestryOp = PathExpr::ANCESTOR_OP;
701
                break;
687
                break;
 Lines 704-786    Link Here 
704
                break;
690
                break;
705
            default:
691
            default:
706
                lexer.pushBack();
692
                lexer.pushBack();
707
                pathExpr->addPatternExpr(createPatternExpr(lexer), ancestryOp);
693
                return pathExpr;
708
                ancestryOp = PathExpr::RELATIVE_OP;
694
        }
709
                break;
695
        
696
        expr = createLocationStep(lexer);
697
        if ( !expr ) {
698
            delete pathExpr;
699
            return 0;
710
        }
700
        }
701
        
702
        pathExpr->addExpr(expr, ancestryOp);
711
    }
703
    }
712
704
713
    /* <debug> *
714
    String tmp;
715
    pathExpr->toString(tmp);
716
    cout << "creating pathExpr: " << tmp << endl;
717
    /* </debug> */
718
719
    return pathExpr;
705
    return pathExpr;
720
} //-- createPathExpr
706
} //-- createPathExpr
721
707
722
/**
708
/**
723
 * Creates a PatternExpr using the given ExprLexer
709
 * Creates a PathExpr using the given ExprLexer
710
 * XXX temporary use as top of XSLT Pattern
724
 * @param lexer the ExprLexer for retrieving Tokens
711
 * @param lexer the ExprLexer for retrieving Tokens
725
**/
712
**/
726
PatternExpr* ExprParser::createPatternExpr(ExprLexer& lexer) {
713
Expr* ExprParser::createUnionExpr(ExprLexer& lexer) {
727
714
728
    PatternExpr* pExpr = 0;
715
    Expr* expr = createPathExpr(lexer);
729
    Token* tok = lexer.peek();
716
    if(!expr)
730
    if ( isLocationStepToken(tok) ) {
717
        return 0;
731
        pExpr = createLocationStep(lexer);
718
    
732
    }
719
    if ( lexer.peek()->type != Token::UNION_OP )
733
    else if ( isFilterExprToken(tok) ) {
720
        return expr;
734
        pExpr = createFilterExpr(lexer);
735
    }
736
    else {
737
        cout << "invalid token: " << tok->value << endl;
738
        //-- eat token for now
739
        lexer.nextToken();
740
    }
741
    return pExpr;
742
} //-- createPatternExpr
743
721
744
/**
745
 * Creates a PathExpr using the given ExprLexer
746
 * @param lexer the ExprLexer for retrieving Tokens
747
**/
748
UnionExpr* ExprParser::createUnionExpr(ExprLexer& lexer) {
749
    UnionExpr* unionExpr = new UnionExpr();
722
    UnionExpr* unionExpr = new UnionExpr();
723
    unionExpr->addExpr(expr);
750
724
751
    while ( lexer.hasMoreTokens() ) {
725
    while ( lexer.peek()->type == Token::UNION_OP ) {
752
        Token* tok = lexer.nextToken();
726
        lexer.nextToken(); //-- eat token
753
        switch ( tok->type ) {
754
727
755
            case Token::R_PAREN:
728
        expr = createPathExpr(lexer);
756
            case Token::R_BRACKET:
729
        if ( !expr ) {
757
                lexer.pushBack();
730
            delete unionExpr;
758
                return unionExpr;
731
            return 0;
759
            case Token::UNION_OP :
760
                //-- eat token
761
                break;
762
            default:
763
                lexer.pushBack();
764
                unionExpr->addPathExpr(createPathExpr(lexer));
765
                break;
766
        }
732
        }
733
        unionExpr->addExpr(expr);
767
    }
734
    }
768
    //String tmp;
735
769
    //unionExpr->toString(tmp);
770
    //cout << "creating UnionExpr: " << tmp << endl;
771
    return unionExpr;
736
    return unionExpr;
772
} //-- createUnionExpr
737
} //-- createUnionExpr
773
738
774
MBool ExprParser::isFilterExprToken(Token* token) {
739
MBool ExprParser::isFilterExprToken(Token* token) {
775
    if ( !token ) return MB_FALSE;
776
    switch (token->type) {
740
    switch (token->type) {
777
        case Token::LITERAL:
741
        case Token::LITERAL:
778
        case Token::NUMBER:
742
        case Token::NUMBER:
779
        case Token::FUNCTION_NAME:
743
        case Token::FUNCTION_NAME:
780
        case Token::VAR_REFERENCE:
744
        case Token::VAR_REFERENCE:
781
        case Token::L_PAREN:            // grouping expr
745
        case Token::L_PAREN:            // grouping expr
782
        case Token::PARENT_NODE:
783
        case Token::SELF_NODE :
784
            return MB_TRUE;
746
            return MB_TRUE;
785
        default:
747
        default:
786
            return MB_FALSE;
748
            return MB_FALSE;
 Lines 788-802    Link Here 
788
} //-- isFilterExprToken
750
} //-- isFilterExprToken
789
751
790
MBool ExprParser::isLocationStepToken(Token* token) {
752
MBool ExprParser::isLocationStepToken(Token* token) {
791
    if (!token) return MB_FALSE;
753
    switch (token->type) {
792
    return ((token->type == Token::AXIS_IDENTIFIER) || isNodeTypeToken(token));
754
        case Token::AXIS_IDENTIFIER :
755
        case Token::AT_SIGN :
756
        case Token::PARENT_NODE :
757
        case Token::SELF_NODE :
758
            return MB_TRUE;
759
        default:
760
            return isNodeTypeToken(token);
761
    }
793
} //-- isLocationStepToken
762
} //-- isLocationStepToken
794
763
795
MBool ExprParser::isNodeTypeToken(Token* token) {
764
MBool ExprParser::isNodeTypeToken(Token* token) {
796
    if (!token) return MB_FALSE;
797
798
    switch ( token->type ) {
765
    switch ( token->type ) {
799
        case Token::AT_SIGN:
800
        case Token::CNAME:
766
        case Token::CNAME:
801
        case Token::COMMENT:
767
        case Token::COMMENT:
802
        case Token::NODE :
768
        case Token::NODE :
 Lines 806-812    Link Here 
806
        default:
772
        default:
807
            return MB_FALSE;
773
            return MB_FALSE;
808
    }
774
    }
809
} //-- isLocationStepToken
775
} //-- isNodeTypeToken
810
776
811
/**
777
/**
812
 * Using the given lexer, parses the tokens if they represent a predicate list
778
 * Using the given lexer, parses the tokens if they represent a predicate list
 Lines 816-858    Link Here 
816
 * @param lexer the ExprLexer to use for parsing tokens
782
 * @param lexer the ExprLexer to use for parsing tokens
817
 * @return 0 if successful, or a String pointer to the error message
783
 * @return 0 if successful, or a String pointer to the error message
818
**/
784
**/
819
String* ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
785
MBool ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
820
786
821
    String* errorMsg = 0;
787
    String* errorMsg = 0;
822
823
    Token* tok = lexer.peek();
824
825
    if ( !tok ) return 0; //-- no predicates
826
    if ( tok->type != Token::L_BRACKET ) return 0; //-- not start of predicate list
827
788
828
    lexer.nextToken();
789
    while ( lexer.peek()->type == Token::L_BRACKET ) {
790
        //-- eat Token
791
        lexer.nextToken();
829
792
830
    while ( lexer.hasMoreTokens() ) {
793
        Expr* expr = createExpr(lexer);
831
        tok = lexer.peek();
794
        if(!expr)
832
        if(!tok) {
795
            return MB_FALSE;
833
            //-- error missing ']'
834
            errorMsg = new String("missing close of predicate expression ']'");
835
            break;
836
        }
837
        if ( tok->type == Token::R_BRACKET) {
838
            lexer.nextToken(); //-- eat ']'
839
796
797
        predicateList->add(expr);
840
798
841
            //-- Fix: look ahead at next token for mulitple predicates - Marina M.
799
        if(lexer.nextToken()->type != Token::R_BRACKET) {
842
            tok = lexer.peek();
800
            lexer.pushBack();
843
            if ((!tok) || ( tok->type != Token::L_BRACKET )) break;
801
            //XXX ErrorReport: right bracket expected
844
            //-- /Fix
802
            return MB_FALSE;
845
        }
803
        }
846
804
847
        //-- Fix: handle multiple predicates - Marina M.
848
        if (tok->type == Token::L_BRACKET)
849
            lexer.nextToken(); //-- swallow '['
850
        //-- /Fix
851
852
        Expr* expr = createExpr(lexer);
853
        predicateList->add(expr);
854
    }
805
    }
855
    return errorMsg;
806
    return MB_TRUE;
856
807
857
} //-- parsePredicates
808
} //-- parsePredicates
858
809
 Lines 863-910    Link Here 
863
 * error message.
814
 * error message.
864
 * @param list, the List to add parameter expressions to
815
 * @param list, the List to add parameter expressions to
865
 * @param lexer the ExprLexer to use for parsing tokens
816
 * @param lexer the ExprLexer to use for parsing tokens
866
 * @return 0 if successful, or a String pointer to the error message
817
 * @return MB_TRUE if successful, or a MB_FALSE otherwise
867
**/
818
**/
868
String* ExprParser::parseParameters(List* list, ExprLexer& lexer) {
819
MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer) {
869
870
    String* errorMsg = 0;
871
820
872
    Token* tok = lexer.peek();
821
    if ( lexer.nextToken()->type != Token::L_PAREN ) {
873
822
        lexer.pushBack();
874
    if ( !tok ) return 0; //-- no params
823
        //XXX ErrorReport: left parenthesis expected
875
    if ( tok->type != Token::L_PAREN ) return 0; //-- not start of param list
824
        return MB_FALSE;
825
    }
876
826
877
    lexer.nextToken(); //-- eat L_PAREN
827
    if( lexer.peek()->type == Token::R_PAREN ) {
828
        lexer.nextToken();
829
        return MB_TRUE;
830
    }
878
831
879
    MBool done     = MB_FALSE;
832
    while ( 1 ) {
880
    MBool foundSep = MB_FALSE;
833
        Expr* expr = createExpr(lexer);
834
        if(!expr)
835
            return MB_FALSE;
881
836
882
    while ( lexer.hasMoreTokens() && !done) {
837
        fnCall->addParam(expr);
883
        tok = lexer.peek();
838
            
884
        switch ( tok->type ) {
839
        switch ( lexer.nextToken()->type ) {
885
            case Token::R_PAREN :
840
            case Token::R_PAREN :
886
                if (foundSep) errorMsg = new String("missing expression after ','");
841
                return MB_TRUE;
887
                lexer.nextToken(); //-- eat R_PAREN
888
                done = MB_TRUE;
889
                break;
890
            case Token::COMMA: //-- param separator
842
            case Token::COMMA: //-- param separator
891
                //-- eat COMMA
892
                lexer.nextToken();
893
                foundSep = MB_TRUE;
894
                break;
843
                break;
895
            default:
844
            default:
896
                if ((list->getLength() > 0) && (!foundSep)) {
845
                lexer.pushBack();
897
                    errorMsg = new String("missing ',' or ')'");
846
                //XXX ErrorReport: right parenthesis or comma expected
898
                    done = MB_TRUE;
847
                return MB_FALSE;
899
                    break;
900
                }
901
                foundSep = MB_FALSE;
902
                Expr* expr = createExpr(lexer);
903
                list->add(expr);
904
                break;
905
        }
848
        }
906
    }
849
    }
907
    return errorMsg;
850
851
    return MB_FALSE;
908
852
909
} //-- parseParameters
853
} //-- parseParameters
910
854
(-)ExprParser.h (-11 / +7 lines)
Line     Link Here 
 Lines 1-4    Link Here 
1
/*
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * The contents of this file are subject to the Mozilla Public
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
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
4
 * except in compliance with the License. You may obtain a copy of
 Lines 44-52    Link Here 
44
44
45
public:
45
public:
46
46
47
    static const String R_CURLY_BRACE;
48
    static const String L_CURLY_BRACE;
49
50
    /**
47
    /**
51
     * Creates a new ExprParser
48
     * Creates a new ExprParser
52
    **/
49
    **/
 Lines 58-64    Link Here 
58
    ~ExprParser();
55
    ~ExprParser();
59
56
60
    Expr*          createExpr        (const String& pattern);
57
    Expr*          createExpr        (const String& pattern);
61
    PatternExpr*   createPatternExpr (const String& pattern);
58
    Expr*          createPatternExpr (const String& pattern);
62
    LocationStep*  createLocationStep(const String& path);
59
    LocationStep*  createLocationStep(const String& path);
63
60
64
    /**
61
    /**
 Lines 72-84    Link Here 
72
69
73
    Expr*          createBinaryExpr   (Expr* left, Expr* right, Token* op);
70
    Expr*          createBinaryExpr   (Expr* left, Expr* right, Token* op);
74
    Expr*          createExpr         (ExprLexer& lexer);
71
    Expr*          createExpr         (ExprLexer& lexer);
75
    FilterExpr*    createFilterExpr   (ExprLexer& lexer);
72
    Expr*          createFilterExpr   (ExprLexer& lexer);
76
    FunctionCall*  createFunctionCall (ExprLexer& lexer);
73
    FunctionCall*  createFunctionCall (ExprLexer& lexer);
77
    LocationStep*  createLocationStep (ExprLexer& lexer);
74
    LocationStep*  createLocationStep (ExprLexer& lexer);
78
    NodeExpr*      createNodeExpr     (ExprLexer& lexer);
75
    NodeExpr*      createNodeExpr     (ExprLexer& lexer);
79
    PathExpr*      createPathExpr     (ExprLexer& lexer);
76
    Expr*          createPathExpr     (ExprLexer& lexer);
80
    PatternExpr*   createPatternExpr  (ExprLexer& lexer);
77
    Expr*          createUnionExpr    (ExprLexer& lexer);
81
    UnionExpr*     createUnionExpr    (ExprLexer& lexer);
82
78
83
    MBool          isFilterExprToken   (Token* tok);
79
    MBool          isFilterExprToken   (Token* tok);
84
    MBool          isLocationStepToken (Token* tok);
80
    MBool          isLocationStepToken (Token* tok);
 Lines 94-101    Link Here 
94
     * @param lexer the ExprLexer to use for parsing tokens
90
     * @param lexer the ExprLexer to use for parsing tokens
95
     * @return 0 if successful, or a String pointer to the error message
91
     * @return 0 if successful, or a String pointer to the error message
96
    **/
92
    **/
97
    String* parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
93
    MBool parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
98
    String* parseParameters(List* list, ExprLexer& lexer);
94
    MBool parseParameters(FunctionCall* fnCall, ExprLexer& lexer);
99
95
100
96
101
}; //-- ExprParser
97
}; //-- ExprParser
(-)FunctionCall.cpp (+25 lines)
Line     Link Here 
 Lines 101-106    Link Here 
101
} //-- addParam
101
} //-- addParam
102
102
103
/**
103
/**
104
 * Returns the default priority of this Expr based on the given Node,
105
 * context Node, and ContextState.
106
**/
107
double FunctionCall::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
108
    return 0.5;
109
} //-- getDefaultPriority
110
111
/**
112
 * Determines whether this Expr matches the given node within
113
 * the given context
114
**/
115
MBool FunctionCall::matches(Node* node, Node* context, ContextState* cs) {
116
117
    MBool result = MB_FALSE;
118
    ExprResult* exprResult = evaluate(node, cs);
119
    if ( exprResult->getResultType() == ExprResult::NODESET ) {
120
        NodeSet* nodes = (NodeSet*)exprResult;
121
        result = (nodes->contains(node));
122
    }
123
    delete exprResult;
124
    return result;
125
126
} //-- matches
127
128
/**
104
 * Evaluates the given Expression and converts it's result to a String.
129
 * Evaluates the given Expression and converts it's result to a String.
105
 * The value is appended to the given destination String
130
 * The value is appended to the given destination String
106
**/
131
**/
(-)Makefile.in (-2 / +3 lines)
Line     Link Here 
 Lines 40-51    Link Here 
40
        BooleanResult.cpp \
40
        BooleanResult.cpp \
41
        ElementExpr.cpp \
41
        ElementExpr.cpp \
42
        ErrorFunctionCall.cpp \
42
        ErrorFunctionCall.cpp \
43
        Expr.cpp \
43
        ExprLexer.cpp \
44
        ExprLexer.cpp \
45
        ExprLexerChars.cpp \
44
        ExprParser.cpp \
46
        ExprParser.cpp \
45
        ExtensionFunctionCall.cpp \
47
        ExtensionFunctionCall.cpp \
46
        FilterExpr.cpp \
48
        FilterExpr.cpp \
47
        FunctionCall.cpp \
49
        FunctionCall.cpp \
48
        IdentityExpr.cpp \
49
        LocationStep.cpp \
50
        LocationStep.cpp \
50
        MultiplicativeExpr.cpp \
51
        MultiplicativeExpr.cpp \
51
        NodeSet.cpp \
52
        NodeSet.cpp \
 Lines 53-59    Link Here 
53
        NumberExpr.cpp \
54
        NumberExpr.cpp \
54
        NumberFunctionCall.cpp \
55
        NumberFunctionCall.cpp \
55
        NumberResult.cpp \
56
        NumberResult.cpp \
56
        ParentExpr.cpp \
57
        PathExpr.cpp \
57
        PathExpr.cpp \
58
        PredicateList.cpp \
58
        PredicateList.cpp \
59
        RelationalExpr.cpp \
59
        RelationalExpr.cpp \
 Lines 63-68    Link Here 
63
        StringResult.cpp \
63
        StringResult.cpp \
64
        TextExpr.cpp \
64
        TextExpr.cpp \
65
        UnionExpr.cpp \
65
        UnionExpr.cpp \
66
        UnaryExpr.cpp \
66
        VariableRefExpr.cpp \
67
        VariableRefExpr.cpp \
67
        XPathNames.cpp
68
        XPathNames.cpp
68
ifndef TX_EXE
69
ifndef TX_EXE
(-)PathExpr.cpp (-30 / +30 lines)
Line     Link Here 
 Lines 48-88    Link Here 
48
}
48
}
49
49
50
/**
50
/**
51
 * Destructor, will delete all Pattern Expressions
51
 * Destructor, will delete all Expressions
52
**/
52
**/
53
PathExpr::~PathExpr() {
53
PathExpr::~PathExpr() {
54
    ListIterator* iter = expressions.iterator();
54
    ListIterator* iter = expressions.iterator();
55
    while ( iter->hasNext() ) {
55
    while ( iter->hasNext() ) {
56
         iter->next();
56
         iter->next();
57
         PathExprItem* pxi = (PathExprItem*)iter->remove();
57
         PathExprItem* pxi = (PathExprItem*)iter->remove();
58
         delete pxi->pExpr;
58
         delete pxi->expr;
59
         delete pxi;
59
         delete pxi;
60
    }
60
    }
61
    delete iter;
61
    delete iter;
62
} //-- ~PathExpr
62
} //-- ~PathExpr
63
63
64
/**
64
/**
65
 * Adds the PatternExpr to this PathExpr
65
 * Adds the Expr to this PathExpr
66
 * @param expr the Expr to add to this PathExpr
66
 * @param expr the Expr to add to this PathExpr
67
 * @param index the index at which to add the given Expr
67
 * @param index the index at which to add the given Expr
68
**/
68
**/
69
void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp) {
69
void PathExpr::addExpr(int index, Expr* expr, short ancestryOp) {
70
    if (expr) {
70
    if (expr) {
71
        PathExprItem* pxi = new PathExprItem;
71
        PathExprItem* pxi = new PathExprItem;
72
        pxi->pExpr = expr;
72
        pxi->expr = expr;
73
        pxi->ancestryOp = ancestryOp;
73
        pxi->ancestryOp = ancestryOp;
74
        expressions.insert(index, pxi);
74
        expressions.insert(index, pxi);
75
    }
75
    }
76
} //-- addPattenExpr
76
} //-- addPattenExpr
77
77
78
/**
78
/**
79
 * Adds the PatternExpr to this PathExpr
79
 * Adds the Expr to this PathExpr
80
 * @param expr the Expr to add to this PathExpr
80
 * @param expr the Expr to add to this PathExpr
81
**/
81
**/
82
void PathExpr::addPatternExpr(PatternExpr* expr, short ancestryOp) {
82
void PathExpr::addExpr(Expr* expr, short ancestryOp) {
83
    if (expr) {
83
    if (expr) {
84
        PathExprItem* pxi = new PathExprItem;
84
        PathExprItem* pxi = new PathExprItem;
85
        pxi->pExpr = expr;
85
        pxi->expr = expr;
86
        pxi->ancestryOp = ancestryOp;
86
        pxi->ancestryOp = ancestryOp;
87
        expressions.add(pxi);
87
        expressions.add(pxi);
88
    }
88
    }
 Lines 98-106    Link Here 
98
    return MB_FALSE;
98
    return MB_FALSE;
99
} //-- isAbsolute
99
} //-- isAbsolute
100
100
101
    //------------------------------------/
101
    //-----------------------------/
102
  //- Virtual methods from PatternExpr -/
102
  //- Virtual methods from Expr -/
103
//------------------------------------/
103
//-----------------------------/
104
104
105
/**
105
/**
106
 * Evaluates this Expr based on the given context node and processor state
106
 * Evaluates this Expr based on the given context node and processor state
 Lines 136-145    Link Here 
136
            NodeSet* resNodes;
136
            NodeSet* resNodes;
137
            if ( pxi->ancestryOp == ANCESTOR_OP) {
137
            if ( pxi->ancestryOp == ANCESTOR_OP) {
138
                resNodes = new NodeSet;
138
                resNodes = new NodeSet;
139
                evalDescendants(pxi->pExpr, node, cs, resNodes);
139
                evalDescendants(pxi->expr, node, cs, resNodes);
140
            }
140
            }
141
            else {
141
            else {
142
                ExprResult *res = pxi->pExpr->evaluate(node, cs);
142
                ExprResult *res = pxi->expr->evaluate(node, cs);
143
                if (!res || res->getResultType() != ExprResult::NODESET) {
143
                if (!res || res->getResultType() != ExprResult::NODESET) {
144
                    //XXX ErrorReport: report nonnodeset error
144
                    //XXX ErrorReport: report nonnodeset error
145
                    delete res;
145
                    delete res;
 Lines 168-180    Link Here 
168
168
169
/**
169
/**
170
 * Selects from the descendants of the context node
170
 * Selects from the descendants of the context node
171
 * all nodes that match the PatternExpr
171
 * all nodes that match the Expr
172
 * -- this will be moving to a Utility class
172
 * -- this will be moving to a Utility class
173
**/
173
**/
174
void PathExpr::evalDescendants
174
void PathExpr::evalDescendants
175
    (PatternExpr* pExpr, Node* context, ContextState* cs, NodeSet* resNodes)
175
    (Expr* expr, Node* context, ContextState* cs, NodeSet* resNodes)
176
{
176
{
177
    ExprResult *res = pExpr->evaluate(context, cs);
177
    ExprResult *res = expr->evaluate(context, cs);
178
    if (!res || res->getResultType() != ExprResult::NODESET) {
178
    if (!res || res->getResultType() != ExprResult::NODESET) {
179
        //XXX ErrorReport: report nonnodeset error
179
        //XXX ErrorReport: report nonnodeset error
180
    }
180
    }
 Lines 188-194    Link Here 
188
    while(child) {
188
    while(child) {
189
        if(!(filterWS && child->getNodeType() == Node::TEXT_NODE &&
189
        if(!(filterWS && child->getNodeType() == Node::TEXT_NODE &&
190
             XMLUtils::shouldStripTextnode(child->getNodeValue())))
190
             XMLUtils::shouldStripTextnode(child->getNodeValue())))
191
            evalDescendants(pExpr, child, cs, resNodes);
191
            evalDescendants(expr, child, cs, resNodes);
192
        child = child->getNextSibling();
192
        child = child->getNextSibling();
193
    }
193
    }
194
} //-- evalDescendants
194
} //-- evalDescendants
 Lines 207-213    Link Here 
207
            ListIterator* iter = expressions.iterator();
207
            ListIterator* iter = expressions.iterator();
208
            PathExprItem* pxi = (PathExprItem*)iter->next();
208
            PathExprItem* pxi = (PathExprItem*)iter->next();
209
            delete iter;
209
            delete iter;
210
            return pxi->pExpr->getDefaultPriority(node, context, cs);
210
            return pxi->expr->getDefaultPriority(node, context, cs);
211
        }
211
        }
212
        else if ( size > 1 ) {
212
        else if ( size > 1 ) {
213
            return 0.5;
213
            return 0.5;
 Lines 217-223    Link Here 
217
} //-- getDefaultPriority
217
} //-- getDefaultPriority
218
218
219
/**
219
/**
220
 * Determines whether this PatternExpr matches the given node within
220
 * Determines whether this Expr matches the given node within
221
 * the given context
221
 * the given context
222
**/
222
**/
223
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
223
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
 Lines 241-247    Link Here 
241
            {
241
            {
242
                Node* ancestor = node;
242
                Node* ancestor = node;
243
                while (ancestor = cs->getParentNode(ancestor))  {
243
                while (ancestor = cs->getParentNode(ancestor))  {
244
                    if (pxi->pExpr->matches(node, ancestor, cs))
244
                    if (pxi->expr->matches(node, ancestor, cs))
245
                        return MB_TRUE;
245
                        return MB_TRUE;
246
                }
246
                }
247
                break;
247
                break;
 Lines 252-263    Link Here 
252
                if (parent) {
252
                if (parent) {
253
                    //-- make sure node is Document node
253
                    //-- make sure node is Document node
254
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
254
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
255
                        return pxi->pExpr->matches(node, parent, cs);
255
                        return pxi->expr->matches(node, parent, cs);
256
                }
256
                }
257
                break;
257
                break;
258
            }
258
            }
259
            default:
259
            default:
260
                return pxi->pExpr->matches(node, context, cs);
260
                return pxi->expr->matches(node, context, cs);
261
261
262
        }
262
        }
263
263
 Lines 290-296    Link Here 
290
                {
290
                {
291
                    Node* parent = tnode;
291
                    Node* parent = tnode;
292
                    while (parent = cs->getParentNode(parent))  {
292
                    while (parent = cs->getParentNode(parent))  {
293
                        if (pxi->pExpr->matches(tnode, parent, cs))
293
                        if (pxi->expr->matches(tnode, parent, cs))
294
                            tmpNodes.add(parent);
294
                            tmpNodes.add(parent);
295
                    }
295
                    }
296
                    break;
296
                    break;
 Lines 304-310    Link Here 
304
                        if ( !iter->hasNext() )
304
                        if ( !iter->hasNext() )
305
                            if (parent->getNodeType() != Node::DOCUMENT_NODE) break;
305
                            if (parent->getNodeType() != Node::DOCUMENT_NODE) break;
306
306
307
                        if (pxi->pExpr->matches(tnode, parent, cs))
307
                        if (pxi->expr->matches(tnode, parent, cs))
308
                            tmpNodes.add(parent);
308
                            tmpNodes.add(parent);
309
                    }
309
                    }
310
                    break;
310
                    break;
 Lines 313-327    Link Here 
313
                    if ( !iter->hasNext() ) {
313
                    if ( !iter->hasNext() ) {
314
314
315
                        /*
315
                        /*
316
                          // PREVIOUS // result = pxi->pExpr->matches(tnode, context, cs);
316
                          // PREVIOUS // result = pxi->expr->matches(tnode, context, cs);
317
                          // result was being overwritten if there was more than one
317
                          // result was being overwritten if there was more than one
318
                          // node in nodes during the final iteration  (Marina)
318
                          // node in nodes during the final iteration  (Marina)
319
319
320
                          result = result || pxi->pExpr->matches(tnode, context, cs)
320
                          result = result || pxi->expr->matches(tnode, context, cs)
321
                        */
321
                        */
322
322
323
                        //-- Just return true if we match here
323
                        //-- Just return true if we match here
324
                        if (pxi->pExpr->matches(tnode, context, cs)) {
324
                        if (pxi->expr->matches(tnode, context, cs)) {
325
                            delete iter;
325
                            delete iter;
326
                            return MB_TRUE;
326
                            return MB_TRUE;
327
                        }
327
                        }
 Lines 362-373    Link Here 
362
362
363
363
364
/**
364
/**
365
 * Returns the String representation of this PatternExpr.
365
 * Returns the String representation of this Expr.
366
 * @param dest the String to use when creating the String
366
 * @param dest the String to use when creating the String
367
 * representation. The String representation will be appended to
367
 * representation. The String representation will be appended to
368
 *  any data in the destination String, to allow cascading calls to
368
 *  any data in the destination String, to allow cascading calls to
369
 * other #toString() methods for Expressions.
369
 * other #toString() methods for Expressions.
370
 * @return the String representation of this PatternExpr.
370
 * @return the String representation of this Expr.
371
**/
371
**/
372
void PathExpr::toString(String& dest) {
372
void PathExpr::toString(String& dest) {
373
    ListIterator* iter = expressions.iterator();
373
    ListIterator* iter = expressions.iterator();
 Lines 384-390    Link Here 
384
            default:
384
            default:
385
                break;
385
                break;
386
        }
386
        }
387
        pxi->pExpr->toString(dest);
387
        pxi->expr->toString(dest);
388
    }
388
    }
389
    delete iter;
389
    delete iter;
390
} //-- toString
390
} //-- toString
(-)StringExpr.cpp (-2 / +5 lines)
Line     Link Here 
 Lines 77-84    Link Here 
77
 * @return the String representation of this Expr.
77
 * @return the String representation of this Expr.
78
**/
78
**/
79
void StringExpr::toString(String& str) {
79
void StringExpr::toString(String& str) {
80
    str.append('\'');
80
    UNICODE_CHAR ch = '\'';
81
    if ( value.indexOf(ch) != NOT_FOUND )
82
        ch = '\"';
83
    str.append(ch);
81
    str.append(value);
84
    str.append(value);
82
    str.append('\'');
85
    str.append(ch);
83
} //-- toString
86
} //-- toString
84
87
(-)source/xpath/UnaryExpr.cpp (+71 lines)
Added Link Here 
Added Link Here 
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 Initial Developer of the Original Code is Jonas Sicking.
13
 * Portions created by Jonas Sicking are Copyright (C) 2001, Jonas Sicking.
14
 * All rights reserved.
15
 *
16
 * Contributor(s):
17
 * Jonas Sicking, sicking@bigfoot.com
18
 *   -- original author.
19
 */
20
21
#include "Expr.h"
22
23
  //-------------/
24
 //- UnaryExpr -/
25
//-------------/
26
27
UnaryExpr::UnaryExpr() {
28
    expr = 0;
29
}
30
31
UnaryExpr::UnaryExpr(Expr* expr) {
32
    this->expr = expr;
33
}
34
35
UnaryExpr::~UnaryExpr() {
36
    delete expr;
37
}
38
39
void UnaryExpr::setExpr(Expr* expr) {
40
    delete this->expr;
41
    this->expr = expr;
42
}
43
44
/**
45
 * Evaluates this Expr based on the given context node and processor state
46
 * @param context the context node for evaluation of this Expr
47
 * @param ps the ContextState containing the stack information needed
48
 * for evaluation
49
 * @return the result of the evaluation
50
**/
51
ExprResult* UnaryExpr::evaluate(Node* context, ContextState* cs) {
52
    ExprResult* exprRes = expr->evaluate(context, cs);
53
    double value = exprRes->numberValue();
54
    delete exprRes;
55
    return new NumberResult(-value);
56
}
57
58
/**
59
 * Returns the String representation of this Expr.
60
 * @param dest the String to use when creating the String
61
 * representation. The String representation will be appended to
62
 * any data in the destination String, to allow cascading calls to
63
 * other #toString() methods for Expressions.
64
 * @return the String representation of this Expr.
65
**/
66
void UnaryExpr::toString(String& str) {
67
    if (!expr) return;
68
    str.append('-');
69
    expr->toString(str);
70
}
71
(-)UnionExpr.cpp (-25 / +24 lines)
Line     Link Here 
 Lines 45-73    Link Here 
45
    ListIterator* iter = expressions.iterator();
45
    ListIterator* iter = expressions.iterator();
46
    while ( iter->hasNext() ) {
46
    while ( iter->hasNext() ) {
47
         iter->next();
47
         iter->next();
48
         delete  (PathExpr*)iter->remove();
48
         delete  (Expr*)iter->remove();
49
    }
49
    }
50
    delete iter;
50
    delete iter;
51
} //-- ~UnionExpr
51
} //-- ~UnionExpr
52
52
53
/**
53
/**
54
 * Adds the PathExpr to this UnionExpr
54
 * Adds the Expr to this UnionExpr
55
 * @param pathExpr the PathExpr to add to this UnionExpr
55
 * @param expr the Expr to add to this UnionExpr
56
**/
56
**/
57
void UnionExpr::addPathExpr(PathExpr* pathExpr) {
57
void UnionExpr::addExpr(Expr* expr) {
58
    if (pathExpr) expressions.add(pathExpr);
58
    if (expr) expressions.add(expr);
59
} //-- addPathExpr
59
} //-- addExpr
60
60
61
/**
61
/**
62
 * Adds the PathExpr to this UnionExpr
62
 * Adds the Expr to this UnionExpr
63
 * @param pathExpr the PathExpr to add to this UnionExpr
63
 * @param expr the Expr to add to this UnionExpr
64
**/
64
**/
65
void UnionExpr::addPathExpr(int index, PathExpr* pathExpr) {
65
void UnionExpr::addExpr(int index, Expr* expr) {
66
    if (pathExpr) expressions.insert(index, pathExpr);
66
    if (expr) expressions.insert(index, expr);
67
} //-- addPathExpr
67
} //-- addExpr
68
68
69
    //------------------------------------/
69
    //------------------------------------/
70
  //- Virtual methods from PatternExpr -/
70
  //- Virtual methods from Expr -/
71
//------------------------------------/
71
//------------------------------------/
72
72
73
/**
73
/**
 Lines 88-99    Link Here 
88
88
89
    while ( iter->hasNext() ) {
89
    while ( iter->hasNext() ) {
90
90
91
        PathExpr* pExpr = (PathExpr*)iter->next();
91
        Expr* expr = (Expr*)iter->next();
92
        NodeSet* tmpNodes = (NodeSet*)pExpr->evaluate(context, cs);
92
        ExprResult* exprResult = expr->evaluate(context, cs);
93
        for (int j = 0; j < tmpNodes->size(); j++) {
93
        if ( exprResult->getResultType() == ExprResult::NODESET ) {
94
            nodes->add(tmpNodes->get(j));
94
            ((NodeSet*)exprResult)->copyInto(*nodes);
95
        }
95
        }
96
        delete tmpNodes;
97
    }
96
    }
98
97
99
    delete iter;
98
    delete iter;
 Lines 112-120    Link Here 
112
    double priority = Double::NEGATIVE_INFINITY;
111
    double priority = Double::NEGATIVE_INFINITY;
113
    ListIterator* iter = expressions.iterator();
112
    ListIterator* iter = expressions.iterator();
114
    while ( iter->hasNext() ) {
113
    while ( iter->hasNext() ) {
115
        PathExpr* pExpr = (PathExpr*)iter->next();
114
        Expr* expr = (Expr*)iter->next();
116
        if ( pExpr->matches(node, context, cs) ) {
115
        if ( expr->matches(node, context, cs) ) {
117
            double tmpPriority = pExpr->getDefaultPriority(node, context, cs);
116
            double tmpPriority = expr->getDefaultPriority(node, context, cs);
118
            priority = (tmpPriority > priority) ? tmpPriority : priority;
117
            priority = (tmpPriority > priority) ? tmpPriority : priority;
119
        }
118
        }
120
    }
119
    }
 Lines 132-139    Link Here 
132
    ListIterator* iter = expressions.iterator();
131
    ListIterator* iter = expressions.iterator();
133
132
134
    while ( iter->hasNext() ) {
133
    while ( iter->hasNext() ) {
135
        PathExpr* pExpr = (PathExpr*)iter->next();
134
        Expr* expr = (Expr*)iter->next();
136
        if ( pExpr->matches(node, context, cs) ) {
135
        if ( expr->matches(node, context, cs) ) {
137
             delete iter;
136
             delete iter;
138
             return MB_TRUE;
137
             return MB_TRUE;
139
        }
138
        }
 Lines 144-155    Link Here 
144
143
145
144
146
/**
145
/**
147
 * Returns the String representation of this PatternExpr.
146
 * Returns the String representation of this Expr.
148
 * @param dest the String to use when creating the String
147
 * @param dest the String to use when creating the String
149
 * representation. The String representation will be appended to
148
 * representation. The String representation will be appended to
150
 *  any data in the destination String, to allow cascading calls to
149
 *  any data in the destination String, to allow cascading calls to
151
 * other #toString() methods for Expressions.
150
 * other #toString() methods for Expressions.
152
 * @return the String representation of this PatternExpr.
151
 * @return the String representation of this Expr.
153
**/
152
**/
154
void UnionExpr::toString(String& dest) {
153
void UnionExpr::toString(String& dest) {
155
    ListIterator* iter = expressions.iterator();
154
    ListIterator* iter = expressions.iterator();
 Lines 158-164    Link Here 
158
    while ( iter->hasNext() ) {
157
    while ( iter->hasNext() ) {
159
        //-- set operator
158
        //-- set operator
160
        if (count > 0) dest.append(" | ");
159
        if (count > 0) dest.append(" | ");
161
        ((PathExpr*)iter->next())->toString(dest);
160
        ((Expr*)iter->next())->toString(dest);
162
        ++count;
161
        ++count;
163
    }
162
    }
164
    delete iter;
163
    delete iter;
(-)makefile.win (-4 / +6 lines)
Line     Link Here 
 Lines 36-47    Link Here 
36
	BooleanResult.cpp		\
36
	BooleanResult.cpp		\
37
	ElementExpr.cpp			\
37
	ElementExpr.cpp			\
38
	ErrorFunctionCall.cpp		\
38
	ErrorFunctionCall.cpp		\
39
	Expr.cpp			\
39
	ExprLexer.cpp			\
40
	ExprLexer.cpp			\
41
	ExprLexerChars.cpp		\
40
	ExprParser.cpp			\
42
	ExprParser.cpp			\
41
	ExtensionFunctionCall.cpp	\
43
	ExtensionFunctionCall.cpp	\
42
	FilterExpr.cpp			\
44
	FilterExpr.cpp			\
43
	FunctionCall.cpp		\
45
	FunctionCall.cpp		\
44
	IdentityExpr.cpp		\
45
	LocationStep.cpp		\
46
	LocationStep.cpp		\
46
	MultiplicativeExpr.cpp		\
47
	MultiplicativeExpr.cpp		\
47
	NodeSet.cpp			\
48
	NodeSet.cpp			\
 Lines 49-55    Link Here 
49
	NumberExpr.cpp			\
50
	NumberExpr.cpp			\
50
	NumberFunctionCall.cpp		\
51
	NumberFunctionCall.cpp		\
51
	NumberResult.cpp		\
52
	NumberResult.cpp		\
52
	ParentExpr.cpp			\
53
	PathExpr.cpp			\
53
	PathExpr.cpp			\
54
	PredicateList.cpp		\
54
	PredicateList.cpp		\
55
	RelationalExpr.cpp		\
55
	RelationalExpr.cpp		\
 Lines 59-64    Link Here 
59
	StringResult.cpp		\
59
	StringResult.cpp		\
60
	TextExpr.cpp			\
60
	TextExpr.cpp			\
61
	UnionExpr.cpp			\
61
	UnionExpr.cpp			\
62
	UnaryExpr.cpp			\
62
	VariableRefExpr.cpp		\
63
	VariableRefExpr.cpp		\
63
	XPathNames.cpp			\
64
	XPathNames.cpp			\
64
!if !defined(TX_EXE)
65
!if !defined(TX_EXE)
 Lines 77-88    Link Here 
77
	.\$(OBJDIR)\BooleanResult.obj			\
78
	.\$(OBJDIR)\BooleanResult.obj			\
78
	.\$(OBJDIR)\ElementExpr.obj			\
79
	.\$(OBJDIR)\ElementExpr.obj			\
79
	.\$(OBJDIR)\ErrorFunctionCall.obj		\
80
	.\$(OBJDIR)\ErrorFunctionCall.obj		\
81
	.\$(OBJDIR)\Expr.obj				\
80
	.\$(OBJDIR)\ExprLexer.obj			\
82
	.\$(OBJDIR)\ExprLexer.obj			\
83
	.\$(OBJDIR)\ExprLexerChars.obj			\
81
	.\$(OBJDIR)\ExprParser.obj			\
84
	.\$(OBJDIR)\ExprParser.obj			\
82
	.\$(OBJDIR)\ExtensionFunctionCall.obj		\
85
	.\$(OBJDIR)\ExtensionFunctionCall.obj		\
83
	.\$(OBJDIR)\FilterExpr.obj			\
86
	.\$(OBJDIR)\FilterExpr.obj			\
84
	.\$(OBJDIR)\FunctionCall.obj			\
87
	.\$(OBJDIR)\FunctionCall.obj			\
85
	.\$(OBJDIR)\IdentityExpr.obj			\
86
	.\$(OBJDIR)\LocationStep.obj			\
88
	.\$(OBJDIR)\LocationStep.obj			\
87
	.\$(OBJDIR)\MultiplicativeExpr.obj		\
89
	.\$(OBJDIR)\MultiplicativeExpr.obj		\
88
	.\$(OBJDIR)\NodeSet.obj				\
90
	.\$(OBJDIR)\NodeSet.obj				\
 Lines 90-96    Link Here 
90
	.\$(OBJDIR)\NumberExpr.obj			\
92
	.\$(OBJDIR)\NumberExpr.obj			\
91
	.\$(OBJDIR)\NumberFunctionCall.obj		\
93
	.\$(OBJDIR)\NumberFunctionCall.obj		\
92
	.\$(OBJDIR)\NumberResult.obj			\
94
	.\$(OBJDIR)\NumberResult.obj			\
93
	.\$(OBJDIR)\ParentExpr.obj			\
94
	.\$(OBJDIR)\PathExpr.obj			\
95
	.\$(OBJDIR)\PathExpr.obj			\
95
	.\$(OBJDIR)\PredicateList.obj			\
96
	.\$(OBJDIR)\PredicateList.obj			\
96
	.\$(OBJDIR)\RelationalExpr.obj			\
97
	.\$(OBJDIR)\RelationalExpr.obj			\
 Lines 100-105    Link Here 
100
	.\$(OBJDIR)\StringResult.obj			\
101
	.\$(OBJDIR)\StringResult.obj			\
101
	.\$(OBJDIR)\TextExpr.obj			\
102
	.\$(OBJDIR)\TextExpr.obj			\
102
	.\$(OBJDIR)\UnionExpr.obj			\
103
	.\$(OBJDIR)\UnionExpr.obj			\
104
	.\$(OBJDIR)\UnaryExpr.obj			\
103
	.\$(OBJDIR)\VariableRefExpr.obj			\
105
	.\$(OBJDIR)\VariableRefExpr.obj			\
104
	.\$(OBJDIR)\XPathNames.obj			\
106
	.\$(OBJDIR)\XPathNames.obj			\
105
!if !defined(TX_EXE)
107
!if !defined(TX_EXE)
(-)ProcessorState.cpp (-2 / +4 lines)
Line     Link Here 
 Lines 196-203    Link Here 
196
        namedTemplates.put(name,mObj);
196
        namedTemplates.put(name,mObj);
197
        if ( oldObj ) delete oldObj;
197
        if ( oldObj ) delete oldObj;
198
    }
198
    }
199
    patternExprHash.put(match, exprParser.createPatternExpr(match));
199
    if ( match.length() > 0 ) {
200
    templates.add(xslTemplate);
200
        patternExprHash.put(match, exprParser.createPatternExpr(match));
201
        templates.add(xslTemplate);
202
    }
201
} //-- addTempalte
203
} //-- addTempalte
202
204
203
/**
205
/**

Return to bug 75102