Attachment #40618: XPathLexerParser20010629.patch, diff -u -N, addresses comments by jst for bug #75102

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

(-)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 (-17 / +33 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 65-71    Link Here 
65
**/
76
**/
66
ExprResult* BasicNodeExpr::evaluate(Node* context, ContextState* cs) {
77
ExprResult* BasicNodeExpr::evaluate(Node* context, ContextState* cs) {
67
    NodeSet* nodeSet = new NodeSet();
78
    NodeSet* nodeSet = new NodeSet();
68
    if ( !context ) return nodeSet;
79
    if (!context)
80
        return nodeSet;
69
    Node* node = context->getFirstChild();
81
    Node* node = context->getFirstChild();
70
    while (node) {
82
    while (node) {
71
        if (matches(node, context, cs))
83
        if (matches(node, context, cs))
 Lines 75-91    Link Here 
75
    return nodeSet;
87
    return nodeSet;
76
} //-- evaluate
88
} //-- evaluate
77
89
78
  //-----------------------------/
79
 //- Methods from NodeExpr.cpp -/
80
//-----------------------------/
81
82
/**
90
/**
83
 * Returns the default priority of this Pattern based on the given Node,
91
 * Returns the default priority of this Expr based on the given Node,
84
 * context Node, and ContextState.
92
 * 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
**/
93
**/
88
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
94
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context,
95
                                         ContextState* cs) {
96
    if (nodeNameSet)
97
        return 0;
89
    return -0.5;
98
    return -0.5;
90
} //-- getDefaultPriority
99
} //-- getDefaultPriority
91
100
 Lines 102-121    Link Here 
102
 * the given context
111
 * the given context
103
**/
112
**/
104
MBool BasicNodeExpr::matches(Node* node, Node* context, ContextState* cs) {
113
MBool BasicNodeExpr::matches(Node* node, Node* context, ContextState* cs) {
105
    if ( !node ) return MB_FALSE;
114
    if (!node)
106
    switch ( type ) {
115
        return MB_FALSE;
116
    switch (type) {
107
        case NodeExpr::COMMENT_EXPR:
117
        case NodeExpr::COMMENT_EXPR:
108
            return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
118
            return (MBool)(node->getNodeType() == Node::COMMENT_NODE);
109
        case NodeExpr::PI_EXPR :
119
        case NodeExpr::PI_EXPR :
110
            return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE);
120
            return (MBool)(node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE &&
121
                            !nodeNameSet || nodeName.isEqual(node->getNodeName()));
111
        default: //-- node()
122
        default: //-- node()
112
            if(node->getNodeType() == Node::TEXT_NODE)
123
            if (node->getNodeType() == Node::TEXT_NODE)
113
                return !cs->isStripSpaceAllowed(node);
124
                return !cs->isStripSpaceAllowed(node);
114
            return MB_TRUE;
125
            return MB_TRUE;
115
            break;
126
            break;
116
    }
127
    }
117
    return MB_TRUE;
128
    return MB_TRUE;
118
119
} //-- matches
129
} //-- matches
120
130
121
131
 Lines 128-139    Link Here 
128
 * @return the String representation of this NodeExpr.
138
 * @return the String representation of this NodeExpr.
129
**/
139
**/
130
void BasicNodeExpr::toString(String& dest) {
140
void BasicNodeExpr::toString(String& dest) {
131
    switch ( type ) {
141
    switch (type) {
132
        case NodeExpr::COMMENT_EXPR:
142
        case NodeExpr::COMMENT_EXPR:
133
            dest.append("comment()");
143
            dest.append("comment()");
134
            break;
144
            break;
135
        case NodeExpr::PI_EXPR :
145
        case NodeExpr::PI_EXPR :
136
            dest.append("processing-instruction()");
146
            dest.append("processing-instruction(");
147
            if (nodeNameSet) {
148
                dest.append('\'');
149
                dest.append(nodeName);
150
                dest.append('\'');
151
            }
152
            dest.append(')');
137
            break;
153
            break;
138
        default: //-- node()
154
        default: //-- node()
139
            dest.append("node()");
155
            dest.append("node()");
(-)Expr.h (-642 / +115 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 59-65    Link Here 
59
66
60
public:
67
public:
61
68
62
     
63
     /**
69
     /**
64
      * Returns the value of a given variable binding within the current scope
70
      * Returns the value of a given variable binding within the current scope
65
      * @param the name to which the desired variable value has been bound
71
      * @param the name to which the desired variable value has been bound
 Lines 82-91    Link Here 
82
    **/
88
    **/
83
    virtual Node* getParentNode(Node* node) = 0;
89
    virtual Node* getParentNode(Node* node) = 0;
84
90
85
86
    virtual MBool isStripSpaceAllowed(Node* node) = 0;
91
    virtual MBool isStripSpaceAllowed(Node* node) = 0;
87
92
88
89
    /**
93
    /**
90
     * Returns a call to the function that has the given name.
94
     * Returns a call to the function that has the given name.
91
     * This method is used for XPath Extension Functions.
95
     * This method is used for XPath Extension Functions.
 Lines 101-107    Link Here 
101
    **/
105
    **/
102
    virtual void sortByDocumentOrder(NodeSet* nodes) = 0;
106
    virtual void sortByDocumentOrder(NodeSet* nodes) = 0;
103
107
104
105
}; //-- ContextState
108
}; //-- ContextState
106
109
107
110
 Lines 115-121    Link Here 
115
    /**
118
    /**
116
     * Virtual destructor, important for subclasses
119
     * Virtual destructor, important for subclasses
117
    **/
120
    **/
118
    virtual ~Expr() {};
121
    virtual ~Expr();
119
122
120
    /**
123
    /**
121
     * Evaluates this Expr based on the given context node and processor state
124
     * 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;
130
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
128
131
129
    /**
132
    /**
133
     * Determines whether this Expr matches the given node within
134
     * the given context
135
    **/
136
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
137
138
    /**
139
     * Returns the default priority of this Expr based on the given Node,
140
     * context Node, and ContextState.
141
    **/
142
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
143
144
    /**
130
     * Returns the String representation of this Expr.
145
     * Returns the String representation of this Expr.
131
     * @param dest the String to use when creating the String
146
     * @param dest the String to use when creating the String
132
     * representation. The String representation will be appended to
147
     * representation. The String representation will be appended to
 Lines 138-144    Link Here 
138
153
139
}; //-- Expr
154
}; //-- Expr
140
155
141
142
/**
156
/**
143
 * This class represents a FunctionCall as defined by the XPath 1.0
157
 * This class represents a FunctionCall as defined by the XPath 1.0
144
 * Recommendation.
158
 * Recommendation.
 Lines 149-171    Link Here 
149
163
150
    static const String INVALID_PARAM_COUNT;
164
    static const String INVALID_PARAM_COUNT;
151
165
152
153
    virtual ~FunctionCall();
166
    virtual ~FunctionCall();
154
167
155
    /**
168
    /**
156
     * Adds the given parameter to this FunctionCall's parameter list
169
     * Virtual methods from Expr 
157
     * @param expr the Expr to add to this FunctionCall's parameter list
158
    **/
170
    **/
159
    void addParam(Expr* expr);
171
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
172
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
173
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
174
    virtual void toString(String& dest);
160
175
161
    /**
176
    /**
162
     * Evaluates this Expr based on the given context node and processor state
177
     * Adds the given parameter to this FunctionCall's parameter list
163
     * @param context the context node for evaluation of this Expr
178
     * @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
    **/
179
    **/
168
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
180
    void addParam(Expr* expr);
169
181
170
    /**
182
    /**
171
     * Returns the name of this FunctionCall
183
     * Returns the name of this FunctionCall
 Lines 184-198    Link Here 
184
     * @param name the name of this Function
196
     * @param name the name of this Function
185
    **/
197
    **/
186
    void setName(const String& name);
198
    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
199
197
200
198
protected:
201
protected:
 Lines 203-209    Link Here 
203
    FunctionCall(const String& name);
206
    FunctionCall(const String& name);
204
    FunctionCall(const String& name, List* parameters);
207
    FunctionCall(const String& name, List* parameters);
205
208
206
207
    /**
209
    /**
208
     * Evaluates the given Expression and converts it's result to a String.
210
     * Evaluates the given Expression and converts it's result to a String.
209
     * The value is appended to the given destination String
211
     * The value is appended to the given destination String
 Lines 221-317    Link Here 
221
    String name;
223
    String name;
222
}; //-- FunctionCall
224
}; //-- FunctionCall
223
225
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
226
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
263
264
/**
227
/**
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
228
 * Represents an AttributeValueTemplate
316
**/
229
**/
317
class AttributeValueTemplate: public Expr {
230
class AttributeValueTemplate: public Expr {
 Lines 328-349    Link Here 
328
    void addExpr(Expr* expr);
241
    void addExpr(Expr* expr);
329
242
330
    /**
243
    /**
331
     * Evaluates this Expr based on the given context node and processor state
244
     * 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
    **/
245
    **/
337
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
246
    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);
247
    virtual void toString(String& str);
348
248
349
private:
249
private:
 Lines 355-361    Link Here 
355
 * This class represents a NodeTestExpr as defined by the XSL
255
 * This class represents a NodeTestExpr as defined by the XSL
356
 * Working Draft
256
 * Working Draft
357
**/
257
**/
358
class NodeExpr : public PatternExpr {
258
class NodeExpr : public Expr {
359
259
360
public:
260
public:
361
261
 Lines 379-411    Link Here 
379
    //------------------/
279
    //------------------/
380
280
381
    /**
281
    /**
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
282
     * Returns the type of this NodeExpr
391
     * @return the type of this NodeExpr
283
     * @return the type of this NodeExpr
392
    **/
284
    **/
393
    virtual short getType() = 0;
285
    virtual short getType() = 0;
394
286
395
    /**
287
    /**
396
     * Determines whether this NodeExpr matches the given node within
288
     * Virtual methods from Expr 
397
     * the given context
398
    **/
289
    **/
399
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
290
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
400
291
    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;
292
    virtual void toString(String& dest) = 0;
410
293
411
}; //-- NodeExpr
294
}; //-- NodeExpr
 Lines 440-486    Link Here 
440
    **/
323
    **/
441
    void setName(const String& name);
324
    void setName(const String& name);
442
325
443
    //-----------------------------------/
444
   //- Method signatures from NodeExpr -/
445
  //-----------------------------------/
446
447
    /**
326
    /**
448
     * Returns the default priority of this Pattern based on the given Node,
327
     * 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
    **/
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
    **/
328
    **/
462
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
329
    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();
330
    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);
331
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
475
332
    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);
333
    virtual void toString(String& dest);
485
334
486
private:
335
private:
 Lines 492-498    Link Here 
492
    MBool  isNameWild;
341
    MBool  isNameWild;
493
    MBool  isNamespaceWild;
342
    MBool  isNamespaceWild;
494
343
495
496
}; //-- AttributeExpr
344
}; //-- AttributeExpr
497
345
498
/**
346
/**
 Lines 521-572    Link Here 
521
     * Destroys this BasicNodeExpr
369
     * Destroys this BasicNodeExpr
522
    **/
370
    **/
523
    virtual ~BasicNodeExpr();
371
    virtual ~BasicNodeExpr();
524
372
    
525
    //-----------------------------------/
526
   //- Method signatures from NodeExpr -/
527
  //-----------------------------------/
528
529
    /**
373
    /**
530
     * Returns the default priority of this Pattern based on the given Node,
374
     * 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
    **/
375
    **/
535
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
376
    void setNodeName(const String& name);
536
377
537
    /**
378
    /**
538
     * Evaluates this Expr based on the given context node and processor state
379
     * 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
    **/
380
    **/
544
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
381
    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();
382
    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);
383
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
557
384
    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);
385
    virtual void toString(String& dest);
567
386
568
private:
387
private:
569
    NodeExprType type;
388
    NodeExprType type;
389
    String nodeName;
390
    MBool nodeNameSet;
570
}; //-- BasicNodeExpr
391
}; //-- BasicNodeExpr
571
392
572
/**
393
/**
 Lines 597-643    Link Here 
597
    **/
418
    **/
598
    void setName(const String& name);
419
    void setName(const String& name);
599
420
600
    //-----------------------------------/
601
   //- Method signatures from NodeExpr -/
602
  //-----------------------------------/
603
604
    /**
421
    /**
605
     * Evaluates this Expr based on the given context node and processor state
422
     * 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
    **/
423
    **/
611
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
424
    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();
425
    short getType();
626
426
    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);
427
    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);
428
    virtual void toString(String& dest);
642
429
643
private:
430
private:
 Lines 655-727    Link Here 
655
}; //-- ElementExpr
442
}; //-- ElementExpr
656
443
657
/**
444
/**
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
445
 * This class represents a TextExpr, which only matches any text node
726
**/
446
**/
727
class TextExpr : public NodeExpr {
447
class TextExpr : public NodeExpr {
 Lines 729-775    Link Here 
729
public:
449
public:
730
450
731
      //------------------/
451
      //------------------/
732
     //- Public Methods -/
452
     //- Public Methods -/
733
    //------------------/
453
    //------------------/
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
764
454
765
    /**
455
    /**
766
     * Returns the String representation of this NodeExpr.
456
     * 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
    **/
457
    **/
458
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
459
    virtual short getType();
460
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
461
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
773
    virtual void toString(String& dest);
462
    virtual void toString(String& dest);
774
463
775
}; //-- TextExpr
464
}; //-- TextExpr
 Lines 827-833    Link Here 
827
    List predicates;
516
    List predicates;
828
}; //-- PredicateList
517
}; //-- PredicateList
829
518
830
class LocationStep : public PredicateList, public PatternExpr {
519
class LocationStep : public PredicateList, public Expr {
831
520
832
public:
521
public:
833
522
 Lines 849-855    Link Here 
849
        SELF_AXIS
538
        SELF_AXIS
850
    };
539
    };
851
540
852
853
    /**
541
    /**
854
     * Creates a new LocationStep using the default Axis Identifier and no
542
     * Creates a new LocationStep using the default Axis Identifier and no
855
     * NodeExpr (which matches nothing)
543
     * NodeExpr (which matches nothing)
 Lines 887-933    Link Here 
887
    **/
575
    **/
888
    void setNodeExpr(NodeExpr* nodeExpr);
576
    void setNodeExpr(NodeExpr* nodeExpr);
889
577
890
      //------------------------------------/
891
     //- Virtual methods from PatternExpr -/
892
    //------------------------------------/
893
894
    /**
578
    /**
895
     * Evaluates this Expr based on the given context node and processor state
579
     * 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
    **/
580
    **/
901
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
581
    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);
582
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
916
583
    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);
584
    virtual void toString(String& dest);
926
585
927
private:
586
private:
928
587
929
  NodeExpr* nodeExpr;
588
    NodeExpr* nodeExpr;
930
  short     axisIdentifier;
589
    short     axisIdentifier;
931
590
932
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
591
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
933
    void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
592
    void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
 Lines 935-941    Link Here 
935
}; //-- LocationStep
594
}; //-- LocationStep
936
595
937
596
938
class FilterExpr : public PredicateList, public PatternExpr {
597
class FilterExpr : public PredicateList, public Expr {
939
598
940
public:
599
public:
941
600
 Lines 962-1007    Link Here 
962
    **/
621
    **/
963
    void setExpr(Expr* expr);
622
    void setExpr(Expr* expr);
964
623
965
      //------------------------------------/
966
     //- Virtual methods from PatternExpr -/
967
    //------------------------------------/
968
969
    /**
624
    /**
970
     * Evaluates this Expr based on the given context node and processor state
625
     * 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
    **/
626
    **/
976
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
627
    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);
628
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
991
629
    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);
630
    virtual void toString(String& dest);
1001
631
1002
private:
632
private:
1003
633
1004
  Expr*     expr;
634
    Expr* expr;
1005
635
1006
}; //-- FilterExpr
636
}; //-- FilterExpr
1007
637
 Lines 1015-1036    Link Here 
1015
    ~NumberExpr();
645
    ~NumberExpr();
1016
646
1017
    /**
647
    /**
1018
     * Evaluates this Expr based on the given context node and processor state
648
     * 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
    **/
649
    **/
1024
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
650
    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);
651
    virtual void toString(String& str);
1035
652
1036
private:
653
private:
 Lines 1052-1073    Link Here 
1052
    ~StringExpr();
669
    ~StringExpr();
1053
670
1054
    /**
671
    /**
1055
     * Evaluates this Expr based on the given context node and processor state
672
     * 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
    **/
673
    **/
1061
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
674
    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);
675
    virtual void toString(String& str);
1072
676
1073
private:
677
private:
 Lines 1106-1131    Link Here 
1106
710
1107
711
1108
    /**
712
    /**
1109
     * Evaluates this Expr based on the given context node and processor state
713
     * 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
    **/
714
    **/
1115
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
715
    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);
716
    virtual void toString(String& str);
1126
717
1127
1128
1129
private:
718
private:
1130
    short op;
719
    short op;
1131
    Expr* leftExpr;
720
    Expr* leftExpr;
 Lines 1133-1138    Link Here 
1133
}; //-- AdditiveExpr
722
}; //-- AdditiveExpr
1134
723
1135
/**
724
/**
725
 * Represents an UnaryExpr. Returns the negative value of it's expr.
726
**/
727
class UnaryExpr : public Expr {
728
729
public:
730
731
     UnaryExpr();
732
     UnaryExpr(Expr* expr);
733
     ~UnaryExpr();
734
735
    /**
736
     * Sets the expression to negate
737
    **/
738
    void setExpr(Expr* expr);
739
740
    /**
741
     * Virtual methods from Expr 
742
    **/
743
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
744
    virtual void toString(String& str);
745
746
private:
747
    Expr* expr;
748
}; //-- UnaryExpr
749
750
/**
1136
 * Represents a BooleanExpr, a binary expression that
751
 * Represents a BooleanExpr, a binary expression that
1137
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
752
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
1138
**/
753
**/
 Lines 1148-1184    Link Here 
1148
     ~BooleanExpr();
763
     ~BooleanExpr();
1149
764
1150
    /**
765
    /**
1151
     * Sets the left side of this AdditiveExpr
766
     * Sets the left side of this BooleanExpr
1152
    **/
767
    **/
1153
    void setLeftExpr(Expr* leftExpr);
768
    void setLeftExpr(Expr* leftExpr);
1154
769
1155
    /**
770
    /**
1156
     * Sets the right side of this AdditiveExpr
771
     * Sets the right side of this BooleanExpr
1157
    **/
772
    **/
1158
    void setRightExpr(Expr* rightExpr);
773
    void setRightExpr(Expr* rightExpr);
1159
774
1160
775
1161
    /**
776
    /**
1162
     * Evaluates this Expr based on the given context node and processor state
777
     * 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
    **/
778
    **/
1168
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
779
    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);
780
    virtual void toString(String& str);
1179
781
1180
1181
1182
private:
782
private:
1183
    short op;
783
    short op;
1184
    Expr* leftExpr;
784
    Expr* leftExpr;
 Lines 1215-1242    Link Here 
1215
    **/
815
    **/
1216
    void setRightExpr(Expr* rightExpr);
816
    void setRightExpr(Expr* rightExpr);
1217
817
1218
1219
    /**
818
    /**
1220
     * Evaluates this Expr based on the given context node and processor state
819
     * 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
    **/
820
    **/
1226
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
821
    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);
822
    virtual void toString(String& str);
1237
823
1238
1239
1240
private:
824
private:
1241
    short op;
825
    short op;
1242
    Expr* leftExpr;
826
    Expr* leftExpr;
 Lines 1273-1298    Link Here 
1273
     ~RelationalExpr();
857
     ~RelationalExpr();
1274
858
1275
    /**
859
    /**
1276
     * Evaluates this Expr based on the given context node and processor state
860
     * 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
    **/
861
    **/
1282
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
862
    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);
863
    virtual void toString(String& str);
1293
864
1294
1295
1296
private:
865
private:
1297
    short op;
866
    short op;
1298
    Expr* leftExpr;
867
    Expr* leftExpr;
 Lines 1320-1341    Link Here 
1320
    void setName(const String& name);
889
    void setName(const String& name);
1321
890
1322
    /**
891
    /**
1323
     * Evaluates this Expr based on the given context node and processor state
892
     * 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
    **/
893
    **/
1329
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
894
    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);
895
    virtual void toString(String& str);
1340
896
1341
private:
897
private:
 Lines 1346-1352    Link Here 
1346
/**
902
/**
1347
 *  Represents a PathExpr
903
 *  Represents a PathExpr
1348
**/
904
**/
1349
class PathExpr : public PatternExpr {
905
class PathExpr : public Expr {
1350
906
1351
public:
907
public:
1352
908
 Lines 1361-1426    Link Here 
1361
    PathExpr();
917
    PathExpr();
1362
918
1363
    /**
919
    /**
1364
     * Destructor, will delete all Pattern Expressions
920
     * Destructor, will delete all Expressions
1365
    **/
921
    **/
1366
    virtual ~PathExpr();
922
    virtual ~PathExpr();
1367
923
1368
    /**
924
    /**
1369
     * Adds the PatternExpr to this PathExpr
925
     * Adds the Expr to this PathExpr
1370
     * @param expr the Expr to add to this PathExpr
926
     * @param expr the Expr to add to this PathExpr
1371
     * @param index the index at which to add the given Expr
927
     * @param index the index at which to add the given Expr
1372
    **/
928
    **/
1373
    void addPatternExpr(int index, PatternExpr* expr, short ancestryOp);
929
    void addExpr(int index, Expr* expr, short ancestryOp);
1374
930
1375
    /**
931
    /**
1376
     * Adds the PatternExpr to this PathExpr
932
     * Adds the Expr to this PathExpr
1377
     * @param expr the Expr to add to this PathExpr
933
     * @param expr the Expr to add to this PathExpr
1378
    **/
934
    **/
1379
    void addPatternExpr(PatternExpr* expr, short ancestryOp);
935
    void addExpr(Expr* expr, short ancestryOp);
1380
936
1381
    virtual MBool isAbsolute();
937
    virtual MBool isAbsolute();
1382
938
1383
      //------------------------------------/
1384
     //- Virtual methods from PatternExpr -/
1385
    //------------------------------------/
1386
1387
    /**
939
    /**
1388
     * Evaluates this Expr based on the given context node and processor state
940
     * 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
    **/
941
    **/
1394
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
942
    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);
943
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1409
944
    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);
945
    virtual void toString(String& dest);
1419
946
1420
private:
947
private:
1421
948
1422
    struct PathExprItem {
949
    struct PathExprItem {
1423
        PatternExpr* pExpr;
950
        Expr* expr;
1424
        short ancestryOp;
951
        short ancestryOp;
1425
    };
952
    };
1426
953
 Lines 1428-1440    Link Here 
1428
955
1429
   /**
956
   /**
1430
    * Selects from the descendants of the context node
957
    * Selects from the descendants of the context node
1431
    * all nodes that match the PatternExpr
958
    * all nodes that match the Expr
1432
    * -- this will be moving to a Utility class
959
    * -- this will be moving to a Utility class
1433
   **/
960
   **/
1434
   void evalDescendants(PatternExpr* pExpr,
961
   void evalDescendants(Expr* expr,
1435
                        Node* context,
962
                        Node* context,
1436
                        ContextState* cs,
963
                        ContextState* cs,
1437
                        NodeSet* nodes);
964
                        NodeSet* resNodes);
1438
965
1439
}; //-- PathExpr
966
}; //-- PathExpr
1440
967
 Lines 1450-1496    Link Here 
1450
    //------------------/
977
    //------------------/
1451
978
1452
    /**
979
    /**
1453
     * Evaluates this Expr based on the given context node and processor state
980
     * 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
    **/
981
    **/
1459
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
982
    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);
983
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1476
984
    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);
985
    virtual void toString(String& dest);
1486
986
987
    virtual MBool isAbsolute();
988
1487
989
1488
}; //-- RootExpr
990
}; //-- RootExpr
1489
991
1490
/**
992
/**
1491
 *  Represents a UnionExpr
993
 *  Represents a UnionExpr
1492
**/
994
**/
1493
class UnionExpr : public PatternExpr {
995
class UnionExpr : public Expr {
1494
996
1495
public:
997
public:
1496
998
 Lines 1508-1556    Link Here 
1508
     * Adds the PathExpr to this UnionExpr
1010
     * Adds the PathExpr to this UnionExpr
1509
     * @param expr the Expr to add to this UnionExpr
1011
     * @param expr the Expr to add to this UnionExpr
1510
    **/
1012
    **/
1511
    void addPathExpr(PathExpr* expr);
1013
    void addExpr(Expr* expr);
1512
1014
1513
    /**
1015
    /**
1514
     * Adds the PathExpr to this UnionExpr at the specified index
1016
     * Adds the PathExpr to this UnionExpr at the specified index
1515
     * @param expr the Expr to add to this UnionExpr
1017
     * @param expr the Expr to add to this UnionExpr
1516
    **/
1018
    **/
1517
    void addPathExpr(int index, PathExpr* expr);
1019
    void addExpr(int index, Expr* expr);
1518
1519
      //------------------------------------/
1520
     //- Virtual methods from PatternExpr -/
1521
    //------------------------------------/
1522
1020
1523
    /**
1021
    /**
1524
     * Evaluates this Expr based on the given context node and processor state
1022
     * 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
    **/
1023
    **/
1530
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1024
    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);
1025
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1545
1026
    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);
1027
    virtual void toString(String& dest);
1555
1028
1556
private:
1029
private:
(-)ExprLexer.cpp (-585 / +370 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 28-41    Link Here 
28
 * Marina Mechtcheriakova, mmarina@mindspring.com
28
 * Marina Mechtcheriakova, mmarina@mindspring.com
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
 *
32
 * Axel Hecht <axel@pike.org>
33
 *   -- big beating, general overhaul
31
 *
34
 *
32
 * $Id: ExprLexer.cpp,v 1.14 2001/06/26 14:07:49 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
35
/**
38
/**
36
 * Lexical analyzer for XPath expressions
39
 * Lexical analyzer for XPath expressions
37
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
40
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
38
 * @version $Revision: 1.14 $ $Date: 2001/06/26 14:07:49 $
41
 * @version $Revision: 1.13 $ $Date: 2001/05/12 11:59:44 $
39
**/
42
**/
40
43
41
#include "ExprLexer.h"
44
#include "ExprLexer.h"
 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
  else 
192
    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
225
Token* ExprLexer::lookAhead(int offset) {
226
    Token* token = 0;
227
    TokenListItem* tlItem = currentItem;
228
    //-- advance to proper offset
229
    for ( int i = 0; i < offset; i++ )
230
        if ( tlItem ) tlItem = currentItem->next;
231
232
    if (tlItem) token = tlItem->token;
233
    return token;
234
} //-- lookAhead
235
201
236
void ExprLexer::addToken(Token* token) {
202
void ExprLexer::addToken(Token* token)
237
    TokenListItem* tlItem = new TokenListItem;
203
{
238
    tlItem->token = token;
204
  TokenListItem* tlItem = new TokenListItem;
239
    tlItem->next  = 0;
205
  tlItem->token = token;
240
    if (lastItem) {
206
  tlItem->next  = 0;
241
        tlItem->previous = lastItem;
207
  if (lastItem) {
242
        lastItem->next = tlItem;
208
    tlItem->previous = lastItem;
243
    }
209
    lastItem->next = tlItem;
244
    if (!firstItem) firstItem = tlItem;
210
  }
245
    lastItem = tlItem;
211
  if (!firstItem)
246
    prevToken = token;
212
    firstItem = tlItem;
247
    ++tokenCount;
213
  lastItem = tlItem;
214
  prevToken = token;
215
  ++tokenCount;
248
} //-- addToken
216
} //-- addToken
249
217
250
/**
218
/**
251
 * Returns true if the given character represents an Alpha letter
219
 * Returns true if the following Token should be an operator.
252
**/
220
 * This is a helper for the first bullet of [XPath 3.7]
253
MBool ExprLexer::isAlphaChar(PRInt32 ch) {
221
 *  Lexical Structure
254
    if ((ch >= 'a' ) && (ch <= 'z' )) return MB_TRUE;
222
**/
255
    if ((ch >= 'A' ) && (ch <= 'Z' )) return MB_TRUE;
223
MBool ExprLexer::nextIsOperatorToken(Token* token)
224
{
225
  if (!token || token->type == Token::NULL_TOKEN)
256
    return MB_FALSE;
226
    return MB_FALSE;
257
} //-- isAlphaChar
227
  /* This relies on the tokens having the right order in ExprLexer.h */
258
228
  if (token->type >= Token::COMMA && 
259
/**
229
      token->type <= Token::UNION_OP)
260
 * Returns true if the given character represents a numeric letter (digit)
261
**/
262
MBool ExprLexer::isDigit(PRInt32 ch) {
263
    if ((ch >= '0') && (ch <= '9'))   return MB_TRUE;
264
    return MB_FALSE;
230
    return MB_FALSE;
265
} //-- isDigit
231
  return MB_TRUE;
232
} //-- nextIsOperatorToken
266
233
267
/**
234
/**
268
 * Returns true if the given character is an allowable NCName character
235
 *  Parses the given String into the set of Tokens
269
**/
270
MBool ExprLexer::isNCNameChar(PRInt32 ch) {
271
    if (isDigit(ch) || isAlphaChar(ch)) return MB_TRUE;
272
    return (MBool) ((ch == '.') || (ch == '_') || (ch == '-'));
273
} //-- isNCNameChar
274
275
/**
276
 * Returns true if the given character is an allowable QName character
277
**/
278
MBool ExprLexer::isQNameChar(PRInt32 ch) {
279
    return (MBool) (( ch == ':') || isNCNameChar(ch));
280
} //-- isQNameChar
281
282
/**
283
 * Returns true if the given String is a valid XML QName
284
**/
236
**/
285
MBool ExprLexer::isValidQName(String& name) {
237
void ExprLexer::parse(const String& pattern)
286
238
{
287
    int size = name.length();
239
  String tokenBuffer;
288
    if ( size == 0 ) return MB_FALSE;
240
  PRInt32 iter = 0, start;
289
    else if ( !isAlphaChar(name.charAt(0))) return MB_FALSE;
241
  PRInt32 size = pattern.length();
290
    else {
242
  short defType;
291
        for ( int i = 1; i < size; i++) {
243
  UNICODE_CHAR ch;
292
            if ( ! isQNameChar(name.charAt(i))) return MB_FALSE;
244
  if (size==0)
245
    return;
246
247
  //-- initialize previous token, this will automatically get
248
  //-- deleted when it goes out of scope
249
  Token nullToken('\0', Token::NULL_TOKEN);
250
251
  prevToken = &nullToken;
252
253
  while (iter < size) {
254
255
    ch = pattern.charAt(iter);
256
    defType = Token::CNAME;
257
258
    if (ch==DOLLAR_SIGN) {
259
      if (++iter == size || !isLetter(ch=pattern.charAt(iter))) {
260
        // Error, VariableReference expected
261
        errorPos = iter;
262
        errorCode = ERROR_UNRESOLVED_VAR_REFERENCE;
263
        if (firstItem)
264
          firstItem->token->type=Token::ERROR;
265
        else
266
          addToken(new Token('\0',Token::ERROR));
267
        iter=size; // bail
268
      }
269
      else
270
        defType = Token::VAR_REFERENCE;
271
    } 
272
    // just reuse the QName parsing, which will use defType 
273
    // the token to construct
274
275
    if (isLetter(ch)) {
276
      // NCName, can get QName or OperatorName;
277
      //  FunctionName, NodeName, and AxisSpecifier may want whitespace,
278
      //  and are dealt with below
279
      start = iter;
280
      while (++iter < size && 
281
             isNCNameChar(pattern.charAt(iter))) /* just go */ ;
282
      PRInt32 end = iter;
283
      if (pattern.charAt(iter)==COLON) {
284
        // try QName or wildcard, might need to step back for axis
285
        if (++iter < size)
286
          if (isLetter(pattern.charAt(iter)))
287
            while (++iter < size && 
288
                  isNCNameChar(pattern.charAt(iter))) /* just go */ ;
289
          else if (pattern.charAt(iter)=='*' 
290
                   && defType != Token::VAR_REFERENCE)
291
            ++iter; /* eat wildcard for NameTest, bail for var ref at COLON */
292
          else 
293
            iter--; // step back
294
      }
295
      if (nextIsOperatorToken(prevToken)) {
296
        if (pattern.subString(start,end,subStr).isEqual(AND))
297
          defType = Token::AND_OP;
298
        else if (pattern.subString(start,end,subStr).isEqual(OR))
299
          defType = Token::OR_OP;
300
        else if (pattern.subString(start,end,subStr).isEqual(MODULUS))
301
          defType = Token::MODULUS_OP;
302
        else if (pattern.subString(start,end,subStr).isEqual(DIVIDE))
303
          defType = Token::DIVIDE_OP;
304
        else {
305
          // Error "operator expected"
306
          // XXX QUESTION: spec is not too precise
307
          // badops is sure an error, but is bad:ops, too? We say yes!
308
          errorPos = iter;
309
          errorCode = ERROR_OP_EXPECTED;
310
          if (firstItem)
311
            firstItem->token->type=Token::ERROR;
312
          else
313
            addToken(new Token('\0',Token::ERROR));
314
          iter=size; // bail
293
        }
315
        }
316
      }
317
      addToken(new Token(pattern.subString(start,iter,subStr),defType));
294
    }
318
    }
295
    return MB_TRUE;
319
    else if (isDigit(ch)) {
296
} //-- isValidQName
320
      start = iter;
297
321
      while (++iter < size && 
298
MBool ExprLexer::isOperatorToken(Token* token) {
322
             isDigit(pattern.charAt(iter))) /* just go */;
299
    if ( !token ) return MB_FALSE;
323
      if (pattern.charAt(iter)=='.')
300
    switch ( token->type ) {
324
        while (++iter < size && 
301
        //-- boolean operators
325
               isDigit(pattern.charAt(iter))) /* just go */;
302
        case Token::AND_OP:
326
      addToken(new Token(pattern.subString(start,iter,subStr),Token::NUMBER));
303
        case Token::OR_OP:
304
        //-- relational operators
305
        case Token::EQUAL_OP:
306
        case Token::NOT_EQUAL_OP:
307
        case Token::LESS_THAN_OP:
308
        case Token::GREATER_THAN_OP:
309
        case Token::LESS_OR_EQUAL_OP:
310
        case Token::GREATER_OR_EQUAL_OP:
311
        //-- additive operators
312
        case Token::ADDITION_OP:
313
        case Token::SUBTRACTION_OP:
314
        //-- multiplicative operators
315
        case Token::DIVIDE_OP:
316
        case Token::MODULUS_OP:
317
        case Token::MULTIPLY_OP:
318
            return MB_TRUE;
319
        default:
320
            break;
321
    }
322
323
    return MB_FALSE;
324
} //-- isOperatorToken
325
326
MBool ExprLexer::matchDelimiter(UNICODE_CHAR ch) {
327
328
    short tokenType = 0;
329
    MBool addChar = MB_TRUE;
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
    }
327
    }
380
    Token* token = 0;
328
    else {
381
    if ( addChar ) token = new Token(ch, tokenType);
329
      switch (ch) {
382
    else token = new Token(tokenType);
330
        //-- ignore whitespace
383
331
      case SPACE:
384
    addToken(token);
332
      case TX_TAB:
385
    return MB_TRUE;
333
      case TX_CR:
386
} //-- matchDelimiter
334
      case TX_LF:
387
335
        ++iter;
388
/**
336
        break;
389
 * Returns true if the value of the given String matches
337
      case S_QUOTE :
390
 * an OperatorName
338
      case D_QUOTE :
391
**/
339
        start=iter;
392
MBool ExprLexer::matchesOperator(String& buffer) {
340
        iter = pattern.indexOf(ch,start+1);
393
341
        if (iter==NOT_FOUND) {
394
    int index = 0;
342
          // XXX Error reporting "unclosed literal"
395
    while (index < NUMBER_OF_TOKENS) {
343
          errorPos = start;
396
        Token tok = TOKENS[index++];
344
          errorCode = ERROR_UNCLOSED_LITERAL;
397
        if ( tok.value.isEqual(buffer) ) {
345
          if (firstItem)
398
            if (isOperatorToken( &tok )) return MB_TRUE;
346
            firstItem->token->type=Token::ERROR;
347
          else
348
            addToken(new Token('\0',Token::ERROR));
349
          iter=size; // bail
399
        }
350
        }
400
    }
351
        else {
401
    return MB_FALSE;
352
          addToken(new Token(pattern.subString(start+1,iter,subStr),
402
353
                             Token::LITERAL));
403
} //-- matchesOperator
354
          ++iter;
404
355
        }
405
/**
356
        break;
406
 * Matches the given String to the appropriate Token
357
      case PERIOD:
407
 * @param buffer the current StringBuffer representing the value of the Token
358
        // period can be .., .(DIGITS)+ or ., check next
408
 * @param ch, the current delimiter token
359
        if (++iter < size) {
409
**/
360
          ch=pattern.charAt(iter);
410
void ExprLexer::matchToken(String& buffer, UNICODE_CHAR ch) {
361
          if (isDigit(ch)) {
411
362
            start=iter-1;
412
    if ( buffer.length() == 0) return;
363
            while (++iter < size && 
413
364
                   isDigit(pattern.charAt(iter))) /* just go */;
414
    Token* match = new Token();
365
            addToken(new Token(pattern.subString(start,iter,subStr),
415
    MBool foundMatch = MB_FALSE;
366
                               Token::NUMBER));
416
    int index = 0;
367
          }
417
368
          else if (ch==PERIOD) {
418
    //-- check previous token
369
            addToken(new Token(pattern.subString(iter-1,iter++,subStr),
419
    switch(prevToken->type) {
370
                               Token::PARENT_NODE));
420
        case Token::VAR_REFERENCE :
371
          }
421
            if ( prevToken->value.length() == 0) {
372
          else
422
                prevToken->value.append(buffer);
373
            addToken(new Token(PERIOD, Token::SELF_NODE));
423
                buffer.clear();
424
                return;
425
            }
426
            break;
427
        default:
428
            break;
429
    }
430
431
    //-- look for next match
432
    while ( !foundMatch && (index < NUMBER_OF_TOKENS) ) {
433
434
        Token tok = TOKENS[index++];
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
    PRInt32 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
        }
533
        else if ( inNumber ) {
534
            if (isDigit(ch) || (ch == '.')) {
535
                tokenBuffer.append(ch);
536
            }
537
            else {
538
                inNumber = MB_FALSE;
539
                addToken(new Token(tokenBuffer, Token::NUMBER));
540
                tokenBuffer.clear();
541
                //-- push back last char
542
                --currentPos;
543
            }
544
        }
545
        else if (isDigit(ch)) {
546
            if  ((tokenBuffer.length() == 0 ) || matchesOperator(tokenBuffer) ) {
547
                //-- match operator and free up token buffer
548
                matchToken(tokenBuffer, ch);
549
                inNumber = MB_TRUE;
550
            }
551
            else if (( tokenBuffer.length() == 1 ) && (prevCh = '-')) {
552
                inNumber = MB_TRUE;
553
            }
554
            tokenBuffer.append(ch);
555
        }
374
        }
375
        else
376
          addToken(new Token(ch, Token::SELF_NODE));
377
        // iter++ is already in the number test
378
        
379
        break;
380
      case COLON: // QNames are dealt above, must be axis ident
381
        if (++iter < size && pattern.charAt(iter)==COLON &&
382
            prevToken->type == Token::CNAME) {
383
          prevToken->type = Token::AXIS_IDENTIFIER;
384
          ++iter;
385
        }
556
        else {
386
        else {
557
            switch (ch) {
387
          // XXX Error report "colon is neither QName nor axis"
558
                //-- ignore whitespace
388
          errorPos = iter;
559
                case SPACE:
389
          errorCode = ERROR_COLON;
560
                case TX_TAB:
390
          if (firstItem)
561
                case TX_CR:
391
            firstItem->token->type=Token::ERROR;
562
                case TX_LF:
392
          else
563
                    break;
393
            addToken(new Token('\0',Token::ERROR));
564
                case S_QUOTE :
394
          iter=size; // bail
565
                case D_QUOTE :
566
                    matchToken(tokenBuffer, ch);
567
                    inLiteral = ch;
568
                    break;
569
                case PERIOD:
570
                    if ( inNumber ) tokenBuffer.append(ch);
571
                    else if ( prevToken->type == Token::SELF_NODE ) {
572
                        prevToken->type = Token::PARENT_NODE;
573
                    }
574
                    else if ( tokenBuffer.length() > 0 )
575
                        tokenBuffer.append(ch);
576
                    else matchDelimiter(ch);
577
                    break;
578
                case COLON:
579
                    if ( prevCh == ch) {
580
                        PRInt32 bufSize = tokenBuffer.length();
581
                        tokenBuffer.setLength(bufSize-1);
582
                        addToken(new Token(tokenBuffer, Token::AXIS_IDENTIFIER));
583
                        tokenBuffer.clear();
584
                    }
585
                    else tokenBuffer.append(ch);
586
                    break;
587
                case FORWARD_SLASH :
588
                    matchToken(tokenBuffer, ch);
589
                    if ( prevToken->type == Token::PARENT_OP ) {
590
                        prevToken->type = Token::ANCESTOR_OP;
591
                        prevToken->value.append(ch);
592
                    }
593
                    //-- handle possible error in using /
594
                    else if ( prevToken->type == Token::NUMBER ) {
595
                        prevToken->type = Token::ERROR;
596
                        prevToken->value = "Error in expression, misuse of '/', try 'div' instead.";
597
                    }
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
        }
395
        }
714
        ++currentPos;
396
        break;
715
    }
397
      case FORWARD_SLASH :
716
    //-- end lexical parsing of current token
398
        if (++iter < size && pattern.charAt(iter)==ch) {
717
    //-- freeBuffer if needed
399
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
718
400
                             Token::ANCESTOR_OP));
719
    if ( inNumber ) {
401
        }
720
        addToken(new Token(tokenBuffer, Token::NUMBER));
402
        else {
403
          addToken(new Token(ch, Token::PARENT_OP));
404
        }
405
        break;
406
      case BANG : // can only be !=
407
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
408
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
409
                             Token::NOT_EQUAL_OP));
410
        }
411
        else {
412
          // Error ! is not not()
413
          errorPos = iter;
414
          errorCode = ERROR_BANG;
415
          if (firstItem)
416
            firstItem->token->type=Token::ERROR;
417
          else
418
            addToken(new Token('\0',Token::ERROR));
419
          iter=size; // bail
420
        }
421
        break;
422
      case EQUAL:
423
        addToken(new Token(ch,Token::EQUAL_OP));
424
        ++iter;
425
        break;
426
      case L_ANGLE:
427
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
428
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
429
                             Token::LESS_OR_EQUAL_OP));
430
        }
431
        else
432
          addToken(new Token(ch,Token::LESS_THAN_OP));
433
        break;
434
      case R_ANGLE:
435
        if (++iter < size && pattern.charAt(iter)==EQUAL) {
436
          addToken(new Token(pattern.subString(iter-1,++iter,subStr),
437
                             Token::GREATER_OR_EQUAL_OP));
438
        }
439
        else
440
          addToken(new Token(ch,Token::GREATER_THAN_OP));
441
        break;
442
      case HYPHEN :
443
        addToken(new Token(ch,Token::SUBTRACTION_OP));
444
        ++iter;
445
        break;
446
      case ASTERIX:
447
        if (nextIsOperatorToken(prevToken))
448
          addToken(new Token(ch,Token::MULTIPLY_OP));
449
        else
450
          addToken(new Token(ch,Token::CNAME));
451
        ++iter;
452
        break;
453
      case L_PAREN:
454
        if (prevToken->type == Token::CNAME) {
455
          if (prevToken->value.isEqual(COMMENT))
456
            prevToken->type = Token::COMMENT;
457
          else if (prevToken->value.isEqual(NODE))
458
            prevToken->type = Token::NODE;
459
          else if (prevToken->value.isEqual(PROC_INST))
460
            prevToken->type = Token::PROC_INST;
461
          else if (prevToken->value.isEqual(TEXT))
462
            prevToken->type = Token::TEXT;
463
          else
464
            prevToken->type = Token::FUNCTION_NAME;
465
        }
466
        ++iter;
467
        addToken(new Token(ch,Token::L_PAREN));
468
        break;
469
      case R_PAREN:
470
        ++iter;
471
        addToken(new Token(ch,Token::R_PAREN));
472
        break;
473
      case L_BRACKET:
474
        ++iter;
475
        addToken(new Token(ch,Token::L_BRACKET));
476
        break;
477
      case R_BRACKET:
478
        ++iter;
479
        addToken(new Token(ch,Token::R_BRACKET));
480
        break;
481
      case COMMA:
482
        ++iter;
483
        addToken(new Token(ch,Token::COMMA));
484
        break;
485
      case AT_SIGN :
486
        ++iter;
487
        addToken(new Token(ch,Token::AT_SIGN));
488
        break;
489
      case PLUS:
490
        ++iter;
491
        addToken(new Token(ch,Token::ADDITION_OP));
492
        break;
493
      case VERT_BAR:
494
        ++iter;
495
        addToken(new Token(ch,Token::UNION_OP));
496
        break;
497
      default:
498
        // Error, don't grok character :-(
499
        errorPos = iter;
500
        errorCode = ERROR_UNKNOWN_CHAR;
501
        if (firstItem)
502
          firstItem->token->type=Token::ERROR;
503
        else
504
          addToken(new Token('\0',Token::ERROR));
505
        iter=size; // bail       
506
      }
721
    }
507
    }
722
    else matchToken(tokenBuffer, ch);
508
  }    
723
    prevToken = 0;
724
} //-- parse
509
} //-- parse
725
510
(-)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.8 2001/06/26 14:07:54 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.8 $ $Date: 2001/06/26 14:07:54 $
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
    PRInt32 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(PRInt32 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(PRInt32 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(PRInt32 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(PRInt32 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
(-)ExprParser.cpp (-422 / +374 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 30-36    Link Here 
30
 *   -- fixed bug in ::parsePredicates,
30
 *   -- fixed bug in ::parsePredicates,
31
 *      made sure we continue looking for more predicates.
31
 *      made sure we continue looking for more predicates.
32
 *
32
 *
33
 * $Id: ExprParser.cpp,v 1.13 2001/06/26 14:07:58 peterv%netscape.com Exp $
33
 * $Id: ExprParser.cpp,v 1.12 2001/06/20 06:00:32 margaret.chan%sun.com Exp $
34
 */
34
 */
35
35
36
/**
36
/**
 Lines 38-53    Link Here 
38
 * This class is used to parse XSL Expressions
38
 * This class is used to parse XSL Expressions
39
 * @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
39
 * @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
40
 * @see ExprLexer
40
 * @see ExprLexer
41
 * @version $Revision: 1.13 $ $Date: 2001/06/26 14:07:58 $
41
 * @version $Revision: 1.12 $ $Date: 2001/06/20 06:00:32 $
42
**/
42
**/
43
43
44
#include "ExprParser.h"
44
#include "ExprParser.h"
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
    PRInt32 size = attValue.length();
68
    PRInt32 size = attValue.length();
69
    if (size == 0)
70
        return avt; //XXX should return 0, but that causes crash in lre12
71
70
    int cc = 0;
72
    int cc = 0;
73
    UNICODE_CHAR nextCh;
74
    UNICODE_CHAR ch;
71
    String buffer;
75
    String buffer;
72
    MBool inExpr    = MB_FALSE;
76
    MBool inExpr    = MB_FALSE;
73
    MBool inLiteral = MB_FALSE;
77
    MBool inLiteral = MB_FALSE;
74
    UNICODE_CHAR endLiteral = '"';
78
    UNICODE_CHAR endLiteral;
75
    UNICODE_CHAR prevCh = '\0';
76
79
77
    while ( cc < size) {
80
    nextCh = attValue.charAt(cc);
78
        UNICODE_CHAR ch = attValue.charAt(cc++);
81
    while (cc++ < size) {
82
        ch = nextCh;
83
        nextCh = cc != size ? attValue.charAt(cc) : 0;
84
        
79
        // if in literal just add ch to buffer
85
        // if in literal just add ch to buffer
80
        if ( inLiteral && (ch != endLiteral) ) {
86
        if (inLiteral && (ch != endLiteral)) {
81
                buffer.append(ch);
87
                buffer.append(ch);
82
                prevCh = ch;
83
                continue;
88
                continue;
84
        }
89
        }
85
        switch ( ch ) {
90
        switch ( ch ) {
86
            case '\'' :
91
            case '\'' :
87
            case '"' :
92
            case '"' :
88
                buffer.append(ch);
93
                buffer.append(ch);
89
                if (inLiteral) inLiteral = MB_FALSE;
94
                if (inLiteral)
90
                else {
95
                    inLiteral = MB_FALSE;
96
                else if (inExpr) {
91
                    inLiteral = MB_TRUE;
97
                    inLiteral = MB_TRUE;
92
                    endLiteral = ch;
98
                    endLiteral = ch;
93
                }
99
                }
94
                break;
100
                break;
95
            case  '{' :
101
            case  '{' :
96
                // Ignore case where we find two { without a }
97
                if (!inExpr) {
102
                if (!inExpr) {
98
                    //-- clear buffer
103
                    // Ignore case where we find two {
99
                    if ( buffer.length() > 0) {
104
                    if (nextCh == ch) {
100
                        avt->addExpr(new StringExpr(buffer));
105
                        buffer.append(ch); //-- append '{'
106
                        cc++;
107
                        nextCh = cc != size ? attValue.charAt(cc) : 0;
108
                    }
109
                    else {
110
                        if (buffer.length() > 0)
111
                            avt->addExpr(new StringExpr(buffer));
101
                        buffer.clear();
112
                        buffer.clear();
113
                        inExpr = MB_TRUE;
102
                    }
114
                    }
103
                    inExpr = MB_TRUE;
104
                }
105
                else if (prevCh == ch) {
106
                    inExpr = MB_FALSE;
107
                    buffer.append(ch);
108
                }
115
                }
109
                else {
116
                else
110
                    buffer.append(ch); //-- simply append '{'
117
                    buffer.append(ch); //-- simply append '{'
111
                    ch = '\0';
112
                }
113
                break;
118
                break;
114
            case '}':
119
            case '}':
115
                if (inExpr) {
120
                if (inExpr) {
116
                    inExpr = MB_FALSE;
121
                    inExpr = MB_FALSE;
117
                    avt->addExpr(createExpr(buffer));
122
                    Expr* expr = createExpr(buffer);
123
                    if (!expr) {
124
                        delete avt;
125
                        return 0;
126
                    }
127
                    avt->addExpr(expr);
118
                    buffer.clear();
128
                    buffer.clear();
119
                    //-- change in case another '}' follows
120
                    ch = '\0';
121
                }
129
                }
122
                else if (prevCh != ch) {
130
                else if (nextCh == ch) {
123
                    if ( buffer.length() > 0) buffer.append('}');
131
                    buffer.append(ch);
124
                    else avt->addExpr(new StringExpr(R_CURLY_BRACE));
132
                    cc++;
133
                    nextCh = cc != size ? attValue.charAt(cc) : 0;
134
                }
135
                else {
136
                    //XXX ErrorReport: unmatched '}' found
137
                    delete avt;
138
                    return 0;
125
                }
139
                }
126
                break;
140
                break;
127
            default:
141
            default:
128
                buffer.append(ch);
142
                buffer.append(ch);
129
                break;
143
                break;
130
        }
144
        }
131
        prevCh = ch;
132
    }
145
    }
133
    if ( buffer.length() > 0) {
146
134
        if ( inExpr ) {
147
    if (inExpr) {
135
            //-- error
148
        //XXX ErrorReport: ending '}' missing
136
            String errMsg("#error evaluating AttributeValueTemplate. ");
149
        delete avt;
137
            errMsg.append("Missing '}' after: ");
150
        return 0;
138
            errMsg.append(buffer);
139
            avt->addExpr(new StringExpr(errMsg));
140
        }
141
        else avt->addExpr(new StringExpr(buffer));
142
    }
151
    }
152
153
    if (buffer.length() > 0)
154
        avt->addExpr(new StringExpr(buffer));
155
143
    return avt;
156
    return avt;
144
157
145
} //-- createAttributeValueTemplate
158
} //-- createAttributeValueTemplate
 Lines 149-157    Link Here 
149
    return createExpr(lexer);
162
    return createExpr(lexer);
150
} //-- createExpr
163
} //-- createExpr
151
164
152
PatternExpr* ExprParser::createPatternExpr(const String& pattern) {
165
Expr* ExprParser::createPatternExpr(const String& pattern) {
153
    ExprLexer lexer(pattern);
166
    ExprLexer lexer(pattern);
154
    return createUnionExpr(lexer);
167
    Expr* expr = createUnionExpr(lexer);
168
    return expr;
155
} //-- createPatternExpr
169
} //-- createPatternExpr
156
170
157
LocationStep* ExprParser::createLocationStep(const String& path) {
171
LocationStep* ExprParser::createLocationStep(const String& path) {
 Lines 168-177    Link Here 
168
 * Creates a binary Expr for the given operator
182
 * Creates a binary Expr for the given operator
169
**/
183
**/
170
Expr* ExprParser::createBinaryExpr   (Expr* left, Expr* right, Token* op) {
184
Expr* ExprParser::createBinaryExpr   (Expr* left, Expr* right, Token* op) {
171
    if ( !op ) return 0;
185
    if (!op)
172
    switch(op->type) {
186
        return 0;
173
187
    switch (op->type) {
174
175
        //-- additive ops
188
        //-- additive ops
176
        case Token::ADDITION_OP :
189
        case Token::ADDITION_OP :
177
            return new AdditiveExpr(left, right, AdditiveExpr::ADDITION);
190
            return new AdditiveExpr(left, right, AdditiveExpr::ADDITION);
 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-333    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) 
309
                    if (precedenceLevel(tok->type) < precedenceLevel(ttype)) {
278
                       <= precedenceLevel(((Token*)ops.peek())->type)) {
310
                        expr = createBinaryExpr((Expr*)exprs.pop(), expr,
279
                    expr = createBinaryExpr((Expr*)exprs.pop(),
311
                            (Token*)ops.pop());
280
                                             expr,
312
                    }
281
                                             (Token*)ops.pop());
313
                }
282
                }
314
                exprs.push(expr);
283
                exprs.push(expr);
315
                ops.push(tok);
284
                ops.push(tok);
316
                expr = 0; // OG, prevent reuse of expr
317
                break;
285
                break;
318
            }
286
            }
319
            default:
287
            default:
320
                lexer.pushBack();
288
                lexer.pushBack();
321
                expr = createPatternExpr(lexer);
289
                done = MB_TRUE;
322
                break;
290
                break;
323
        }
291
        }
324
    }
292
    }
325
293
326
    // make sure expr != 0, will this happen?
294
    // make sure expr != 0
327
    if (( expr == 0 ) && (!exprs.empty()))
295
    if (!expr) {
328
        expr = (Expr*) exprs.pop();
296
        while (!exprs.empty()) {
297
            delete (Expr*)exprs.pop();
298
        }
299
        return 0;
300
    }
329
301
330
    while (!exprs.empty() ) {
302
    while (!exprs.empty()) {
331
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
303
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
332
    }
304
    }
333
305
 Lines 335-401    Link Here 
335
307
336
} //-- createExpr
308
} //-- createExpr
337
309
338
FilterExpr*  ExprParser::createFilterExpr(ExprLexer& lexer) {
310
Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
339
311
340
    FilterExpr* filterExpr = new FilterExpr();
341
    Token* tok = lexer.nextToken();
312
    Token* tok = lexer.nextToken();
342
    if ( !tok ) return filterExpr;
343
313
344
    Expr* expr = 0;
314
    Expr* expr = 0;
345
    switch ( tok->type ) {
315
    switch (tok->type) {
346
        case Token::FUNCTION_NAME :
316
        case Token::FUNCTION_NAME :
317
            lexer.pushBack();
347
            expr = createFunctionCall(lexer);
318
            expr = createFunctionCall(lexer);
348
            filterExpr->setExpr(expr);
349
            break;
319
            break;
350
        case Token::VAR_REFERENCE :
320
        case Token::VAR_REFERENCE :
351
            expr = new VariableRefExpr(tok->value);
321
            expr = new VariableRefExpr(tok->value);
352
            filterExpr->setExpr(expr);
353
            break;
322
            break;
354
        case Token::L_PAREN:
323
        case Token::L_PAREN:
355
            //-- primary group expr:
356
            expr = createExpr(lexer);
324
            expr = createExpr(lexer);
357
            tok = lexer.nextToken();
325
            if (!expr)
358
            if ( (!tok) || (tok->type != Token::R_PAREN ) ) {
326
                return 0;
359
                String errMsg("error: ");
327
360
                expr->toString(errMsg);
328
            if (lexer.nextToken()->type != Token::R_PAREN) {
361
                errMsg.append(" - missing ')'");
329
                lexer.pushBack();
362
                delete expr; //-- free up current expr
330
                //XXX ErrorReport: right parenthesis expected
363
                expr = new ErrorFunctionCall(errMsg);
331
                delete expr;
332
                return 0;
364
            }
333
            }
365
            filterExpr->setExpr(expr);
366
            break;
334
            break;
367
        case Token::PARENT_NODE :
335
        case Token::LITERAL :
368
            expr = new ParentExpr();
336
            expr = new StringExpr(tok->value);
369
            filterExpr->setExpr(expr);
370
            break;
337
            break;
371
        case Token::SELF_NODE :
338
        case Token::NUMBER:
372
            expr = new IdentityExpr();
339
        {
373
            filterExpr->setExpr(expr);
340
            StringResult str(tok->value);
341
            expr = new NumberExpr(str.numberValue());
374
            break;
342
            break;
343
        }
375
        default:
344
        default:
345
            // this should never ever happen.
346
            lexer.pushBack();
347
            //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
348
            return 0;
376
            break;
349
            break;
377
    }
350
    }
351
    if (!expr)
352
        return 0;
378
353
379
    //-- handle predicates
354
    if (lexer.peek()->type == Token::L_BRACKET) {
380
    parsePredicates(filterExpr, lexer);
381
355
382
    return filterExpr;
356
        FilterExpr* filterExpr = new FilterExpr();
357
        filterExpr->setExpr(expr);
358
359
        //-- handle predicates
360
        if (!parsePredicates(filterExpr, lexer)) {
361
            delete filterExpr;
362
            return 0;
363
        }
364
        expr = filterExpr;
365
    }
383
366
367
    return expr;
368
384
} //-- createFilterExpr
369
} //-- createFilterExpr
385
370
386
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
371
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
387
372
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;
373
    FunctionCall* fnCall = 0;
394
374
395
    Token* tok = lexer.nextToken();
375
    Token* tok = lexer.nextToken();
396
376
    if (tok->type != Token::FUNCTION_NAME) {
397
    if ( tok->type != Token::FUNCTION_NAME ) {
377
        //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
398
        return new ErrorFunctionCall("invalid function call");
378
        return 0;
399
    }
379
    }
400
380
401
    String fnName = tok->value;
381
    String fnName = tok->value;
 Lines 403-512    Link Here 
403
    //-- compare function names
383
    //-- compare function names
404
    //-- * we should hash these names for speed
384
    //-- * we should hash these names for speed
405
385
406
    if ( XPathNames::BOOLEAN_FN.isEqual(tok->value) ) {
386
    if (XPathNames::BOOLEAN_FN.isEqual(tok->value)) {
407
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_BOOLEAN);
387
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_BOOLEAN);
408
    }
388
    }
409
    else if ( XPathNames::CONCAT_FN.isEqual(tok->value) ) {
389
    else if (XPathNames::CONCAT_FN.isEqual(tok->value)) {
410
        fnCall = new StringFunctionCall(StringFunctionCall::CONCAT);
390
        fnCall = new StringFunctionCall(StringFunctionCall::CONCAT);
411
    }
391
    }
412
    else if ( XPathNames::CONTAINS_FN.isEqual(tok->value) ) {
392
    else if (XPathNames::CONTAINS_FN.isEqual(tok->value)) {
413
        fnCall = new StringFunctionCall(StringFunctionCall::CONTAINS);
393
        fnCall = new StringFunctionCall(StringFunctionCall::CONTAINS);
414
    }
394
    }
415
    else if ( XPathNames::COUNT_FN.isEqual(tok->value) ) {
395
    else if (XPathNames::COUNT_FN.isEqual(tok->value)) {
416
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::COUNT);
396
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::COUNT);
417
    }
397
    }
418
    else if ( XPathNames::FALSE_FN.isEqual(tok->value) ) {
398
    else if (XPathNames::FALSE_FN.isEqual(tok->value)) {
419
        fnCall = new BooleanFunctionCall();
399
        fnCall = new BooleanFunctionCall();
420
    }
400
    }
421
    else if ( XPathNames::ID_FN.isEqual(tok->value) ) {
401
    else if (XPathNames::ID_FN.isEqual(tok->value)) {
422
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::ID);
402
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::ID);
423
    }
403
    }
424
    else if ( XPathNames::LANG_FN.isEqual(tok->value) ) {
404
    else if (XPathNames::LANG_FN.isEqual(tok->value)) {
425
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_LANG);
405
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_LANG);
426
    }
406
    }
427
    else if ( XPathNames::LAST_FN.isEqual(tok->value) ) {
407
    else if (XPathNames::LAST_FN.isEqual(tok->value)) {
428
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LAST);
408
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LAST);
429
    }
409
    }
430
    else if ( XPathNames::LOCAL_NAME_FN.isEqual(tok->value) ) {
410
    else if (XPathNames::LOCAL_NAME_FN.isEqual(tok->value)) {
431
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LOCAL_NAME);
411
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LOCAL_NAME);
432
    }
412
    }
433
    else if ( XPathNames::NAME_FN.isEqual(tok->value) ) {
413
    else if (XPathNames::NAME_FN.isEqual(tok->value)) {
434
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAME);
414
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAME);
435
    }
415
    }
436
    else if ( XPathNames::NAMESPACE_URI_FN.isEqual(tok->value) ) {
416
    else if (XPathNames::NAMESPACE_URI_FN.isEqual(tok->value)) {
437
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAMESPACE_URI);
417
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAMESPACE_URI);
438
    }
418
    }
439
    else if ( XPathNames::NORMALIZE_SPACE_FN.isEqual(tok->value) ) {
419
    else if (XPathNames::NORMALIZE_SPACE_FN.isEqual(tok->value)) {
440
        fnCall = new StringFunctionCall(StringFunctionCall::NORMALIZE_SPACE);
420
        fnCall = new StringFunctionCall(StringFunctionCall::NORMALIZE_SPACE);
441
    }
421
    }
442
    else if ( XPathNames::NOT_FN.isEqual(tok->value) ) {
422
    else if (XPathNames::NOT_FN.isEqual(tok->value)) {
443
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_NOT);
423
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_NOT);
444
    }
424
    }
445
    else if ( XPathNames::POSITION_FN.isEqual(tok->value) ) {
425
    else if (XPathNames::POSITION_FN.isEqual(tok->value)) {
446
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::POSITION);
426
        fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::POSITION);
447
    }
427
    }
448
    else if ( XPathNames::STARTS_WITH_FN.isEqual(tok->value) ) {
428
    else if (XPathNames::STARTS_WITH_FN.isEqual(tok->value)) {
449
        fnCall = new StringFunctionCall(StringFunctionCall::STARTS_WITH);
429
        fnCall = new StringFunctionCall(StringFunctionCall::STARTS_WITH);
450
    }
430
    }
451
    else if ( XPathNames::STRING_FN.isEqual(tok->value) ) {
431
    else if (XPathNames::STRING_FN.isEqual(tok->value)) {
452
        fnCall = new StringFunctionCall(StringFunctionCall::STRING);
432
        fnCall = new StringFunctionCall(StringFunctionCall::STRING);
453
    }
433
    }
454
    else if ( XPathNames::STRING_LENGTH_FN.isEqual(tok->value) ) {
434
    else if (XPathNames::STRING_LENGTH_FN.isEqual(tok->value)) {
455
        fnCall = new StringFunctionCall(StringFunctionCall::STRING_LENGTH);
435
        fnCall = new StringFunctionCall(StringFunctionCall::STRING_LENGTH);
456
    }
436
    }
457
    else if ( XPathNames::SUBSTRING_FN.isEqual(tok->value) ) {
437
    else if (XPathNames::SUBSTRING_FN.isEqual(tok->value)) {
458
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING);
438
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING);
459
    }
439
    }
460
    else if ( XPathNames::SUBSTRING_AFTER_FN.isEqual(tok->value) ) {
440
    else if (XPathNames::SUBSTRING_AFTER_FN.isEqual(tok->value)) {
461
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_AFTER);
441
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_AFTER);
462
    }
442
    }
463
    else if ( XPathNames::SUBSTRING_BEFORE_FN.isEqual(tok->value) ) {
443
    else if (XPathNames::SUBSTRING_BEFORE_FN.isEqual(tok->value)) {
464
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_BEFORE);
444
        fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_BEFORE);
465
    }
445
    }
466
    else if ( XPathNames::SUM_FN.isEqual(tok->value) ) {
446
    else if (XPathNames::SUM_FN.isEqual(tok->value)) {
467
        fnCall = new NumberFunctionCall(NumberFunctionCall::SUM);
447
        fnCall = new NumberFunctionCall(NumberFunctionCall::SUM);
468
    }
448
    }
469
    else if ( XPathNames::TRANSLATE_FN.isEqual(tok->value) ) {
449
    else if (XPathNames::TRANSLATE_FN.isEqual(tok->value)) {
470
        fnCall = new StringFunctionCall(StringFunctionCall::TRANSLATE);
450
        fnCall = new StringFunctionCall(StringFunctionCall::TRANSLATE);
471
    }
451
    }
472
    else if ( XPathNames::TRUE_FN.isEqual(tok->value) ) {
452
    else if (XPathNames::TRUE_FN.isEqual(tok->value)) {
473
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_TRUE);
453
        fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_TRUE);
474
    }
454
    }
475
    // OG+
455
    else if (XPathNames::NUMBER_FN.isEqual(tok->value)) {
476
    else if ( XPathNames::NUMBER_FN.isEqual(tok->value) ) {
477
        fnCall = new NumberFunctionCall(NumberFunctionCall::NUMBER);
456
        fnCall = new NumberFunctionCall(NumberFunctionCall::NUMBER);
478
    }
457
    }
479
    else if ( XPathNames::ROUND_FN.isEqual(tok->value) ) {
458
    else if (XPathNames::ROUND_FN.isEqual(tok->value)) {
480
        fnCall = new NumberFunctionCall(NumberFunctionCall::ROUND);
459
        fnCall = new NumberFunctionCall(NumberFunctionCall::ROUND);
481
    }
460
    }
482
    else if ( XPathNames::CEILING_FN.isEqual(tok->value) ) {
461
    else if (XPathNames::CEILING_FN.isEqual(tok->value)) {
483
        fnCall = new NumberFunctionCall(NumberFunctionCall::CEILING);
462
        fnCall = new NumberFunctionCall(NumberFunctionCall::CEILING);
484
    }
463
    }
485
    else if ( XPathNames::FLOOR_FN.isEqual(tok->value) ) {
464
    else if (XPathNames::FLOOR_FN.isEqual(tok->value)) {
486
        fnCall = new NumberFunctionCall(NumberFunctionCall::FLOOR);
465
        fnCall = new NumberFunctionCall(NumberFunctionCall::FLOOR);
487
    }
466
    }
488
    // OG-
489
    else {
467
    else {
490
        //-- Most likely an Extension Function, or error, but it's
468
        //-- Most likely an Extension Function, or error, but it's
491
        //-- not our job to report an invalid function call here
469
        //-- not our job to report an invalid function call here
492
        fnCall = new ExtensionFunctionCall(fnName);
470
        fnCall = new ExtensionFunctionCall(fnName);
493
    }
471
    }
472
    
494
    //-- handle parametes
473
    //-- handle parametes
495
    List params;
474
    if (!parseParameters(fnCall, lexer)) {
496
    String* errMsg = parseParameters(&params, lexer);
475
        delete fnCall;
497
    if (errMsg) {
476
        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
    }
477
    }
511
    return fnCall;
478
    return fnCall;
512
} //-- createFunctionCall
479
} //-- createFunctionCall
 Lines 514-522    Link Here 
514
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
481
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
515
482
516
    LocationStep* lstep = new LocationStep();
483
    LocationStep* lstep = new LocationStep();
484
485
    //-- child axis is default
517
    short axisIdentifier = LocationStep::CHILD_AXIS;
486
    short axisIdentifier = LocationStep::CHILD_AXIS;
487
    NodeExpr* nodeExpr = 0;
518
488
519
    //-- get Axis Identifier, if present
489
    //-- get Axis Identifier or AbbreviatedStep, if present
520
    Token* tok = lexer.peek();
490
    Token* tok = lexer.peek();
521
    switch (tok->type) {
491
    switch (tok->type) {
522
        case Token::AXIS_IDENTIFIER:
492
        case Token::AXIS_IDENTIFIER:
 Lines 524-560    Link Here 
524
            //-- eat token
494
            //-- eat token
525
            lexer.nextToken();
495
            lexer.nextToken();
526
            //-- should switch to a hash here for speed if necessary
496
            //-- should switch to a hash here for speed if necessary
527
            if ( ANCESTOR_AXIS.isEqual(tok->value) )
497
            if (ANCESTOR_AXIS.isEqual(tok->value)) {
528
                axisIdentifier = LocationStep::ANCESTOR_AXIS;
498
                axisIdentifier = LocationStep::ANCESTOR_AXIS;
529
            else if ( ANCESTOR_OR_SELF_AXIS.isEqual(tok->value) )
499
            }
500
            else if (ANCESTOR_OR_SELF_AXIS.isEqual(tok->value)) {
530
                axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
501
                axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
531
            else if ( ATTRIBUTE_AXIS.isEqual(tok->value) )
502
            }
503
            else if (ATTRIBUTE_AXIS.isEqual(tok->value)) {
532
                axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
504
                axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
533
            else if ( CHILD_AXIS.isEqual(tok->value) )
505
            }
506
            else if (CHILD_AXIS.isEqual(tok->value)) {
534
                axisIdentifier = LocationStep::CHILD_AXIS;
507
                axisIdentifier = LocationStep::CHILD_AXIS;
535
            else if ( DESCENDANT_AXIS.isEqual(tok->value) )
508
            }
509
            else if (DESCENDANT_AXIS.isEqual(tok->value)) {
536
                axisIdentifier = LocationStep::DESCENDANT_AXIS;
510
                axisIdentifier = LocationStep::DESCENDANT_AXIS;
537
            else if ( DESCENDANT_OR_SELF_AXIS.isEqual(tok->value) )
511
            }
512
            else if (DESCENDANT_OR_SELF_AXIS.isEqual(tok->value)) {
538
                axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
513
                axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
539
            else if ( FOLLOWING_AXIS.isEqual(tok->value) )
514
            }
515
            else if (FOLLOWING_AXIS.isEqual(tok->value)) {
540
                axisIdentifier = LocationStep::FOLLOWING_AXIS;
516
                axisIdentifier = LocationStep::FOLLOWING_AXIS;
541
            else if ( FOLLOWING_SIBLING_AXIS.isEqual(tok->value) )
517
            }
518
            else if (FOLLOWING_SIBLING_AXIS.isEqual(tok->value)) {
542
                axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
519
                axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
543
            else if ( NAMESPACE_AXIS.isEqual(tok->value) )
520
            }
521
            else if (NAMESPACE_AXIS.isEqual(tok->value)) {
544
                axisIdentifier = LocationStep::NAMESPACE_AXIS;
522
                axisIdentifier = LocationStep::NAMESPACE_AXIS;
545
            else if ( PARENT_AXIS.isEqual(tok->value) )
523
            }
524
            else if (PARENT_AXIS.isEqual(tok->value)) {
546
                axisIdentifier = LocationStep::PARENT_AXIS;
525
                axisIdentifier = LocationStep::PARENT_AXIS;
547
            else if ( PRECEDING_AXIS.isEqual(tok->value) )
526
            }
527
            else if (PRECEDING_AXIS.isEqual(tok->value)) {
548
                axisIdentifier = LocationStep::PRECEDING_AXIS;
528
                axisIdentifier = LocationStep::PRECEDING_AXIS;
549
            else if ( PRECEDING_SIBLING_AXIS.isEqual(tok->value) )
529
            }
530
            else if (PRECEDING_SIBLING_AXIS.isEqual(tok->value)) {
550
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
531
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
551
            else if ( SELF_AXIS.isEqual(tok->value) )
532
            }
533
            else if (SELF_AXIS.isEqual(tok->value)) {
552
                axisIdentifier = LocationStep::SELF_AXIS;
534
                axisIdentifier = LocationStep::SELF_AXIS;
553
            //-- child axis is default
535
            }
554
            else if (!CHILD_AXIS.isEqual(tok->value)) {
536
            else {
555
                //-- handle error gracefully, simply ignore invalid axis and
537
                delete lstep;
556
                //-- use default. Add error message when message observer
538
                //XXX ErrorReport: unknow axis
557
                //-- is implemented
539
                return 0;
558
            }
540
            }
559
            break;
541
            break;
560
        }
542
        }
 Lines 563-611    Link Here 
563
            lexer.nextToken();
545
            lexer.nextToken();
564
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
546
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
565
            break;
547
            break;
548
        case Token::PARENT_NODE :
549
            //-- eat token
550
            lexer.nextToken();
551
            axisIdentifier = LocationStep::PARENT_AXIS;
552
            nodeExpr = new BasicNodeExpr();
553
            break;
554
        case Token::SELF_NODE :
555
            //-- eat token
556
            lexer.nextToken();
557
            axisIdentifier = LocationStep::SELF_AXIS;
558
            nodeExpr = new BasicNodeExpr();
559
            break;
566
        default:
560
        default:
567
            break;
561
            break;
568
    }
562
    }
569
570
    lstep->setAxisIdentifier(axisIdentifier);
571
572
563
573
    NodeExpr* nodeExpr = 0;
564
    //-- get NodeTest unless AbbreviatedStep was found
574
565
    if (!nodeExpr) {
575
    tok = lexer.peek();
566
        tok = lexer.nextToken();
576
    if (!tok) {
567
577
        ///XXXXX We need to create an ErrorExpr or something to
568
        switch (tok->type) {
578
        ///XXXXX handle errors
569
            case Token::CNAME :
579
    }
570
                // NameTest
580
    // NameTest
571
                // XXX Namespace: handle namespaces here
581
    else if (tok->type == Token::CNAME) {
572
                if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
582
        //-- handle NameTest
573
                    nodeExpr = new AttributeExpr(tok->value);
583
        //-- eat token
574
                else
584
        lexer.nextToken();
575
                    nodeExpr = new ElementExpr(tok->value);
585
        if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
576
                break;
586
            nodeExpr = new AttributeExpr(tok->value);
577
            default:
587
        else
578
                lexer.pushBack();
588
            nodeExpr = new ElementExpr(tok->value);
579
                nodeExpr = createNodeExpr(lexer);
589
580
                if (!nodeExpr) {
590
    }
581
                    delete lstep;
591
    // NodeType
582
                    return 0;
592
    else {
583
                }
593
       nodeExpr = createNodeExpr(lexer);
584
        }
594
    }
585
    }
595
586
    
587
    lstep->setAxisIdentifier(axisIdentifier);
596
    lstep->setNodeExpr(nodeExpr);
588
    lstep->setNodeExpr(nodeExpr);
597
589
598
599
600
    //-- handle predicates
590
    //-- handle predicates
601
591
    if (!parsePredicates(lstep, lexer)) {
602
    parsePredicates(lstep, lexer);
592
        delete lstep;
603
593
        return 0;
604
    //<debug>
594
    }
605
    //String tmp;
606
    //lstep->toString(tmp);
607
    //cout << "returning LocationStep: "<< tmp <<endl;
608
    //</debug>
609
595
610
    return lstep;
596
    return lstep;
611
} //-- createLocationPath
597
} //-- createLocationPath
 Lines 615-664    Link Here 
615
 *
601
 *
616
**/
602
**/
617
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
603
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
618
#if 0
619
    // XXX DEBUG OUTPUT
620
    cout << "creating NodeExpr: "<<endl;
621
    if (!lexer.hasMoreTokens() ) cout << "Lexer has no Tokens"<<endl;
622
#endif
623
    if (!lexer.hasMoreTokens() )  return 0;
624
604
625
    NodeExpr* nodeExpr = 0;
605
    NodeExpr* nodeExpr = 0;
626
606
627
    Token* tok = lexer.nextToken();
607
    Token* nodeTok = lexer.nextToken();
628
    //cout << "Token #" << tok->type <<endl;
629
    List params;
630
608
631
    String* errMsg = 0;
609
    switch (nodeTok->type) {
632
633
    switch ( tok->type ) {
634
        case Token::COMMENT:
610
        case Token::COMMENT:
635
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
611
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
636
            errMsg = parseParameters(&params, lexer);
637
            //-- ignore errMsg for now
638
            delete errMsg;
639
            break;
612
            break;
640
        case Token::NODE :
613
        case Token::NODE :
641
            nodeExpr = new BasicNodeExpr();
614
            nodeExpr = new BasicNodeExpr();
642
            errMsg = parseParameters(&params, lexer);
643
            //-- ignore errMsg for now
644
            delete errMsg;
645
            break;
615
            break;
646
        case Token::PROC_INST :
616
        case Token::PROC_INST :
647
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
617
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
648
            errMsg = parseParameters(&params, lexer);
649
            //-- ignore errMsg for now
650
            delete errMsg;
651
            break;
618
            break;
652
        case Token::TEXT :
619
        case Token::TEXT :
653
            nodeExpr = new TextExpr();
620
            nodeExpr = new TextExpr();
654
            errMsg = parseParameters(&params, lexer);
655
            //-- ignore errMsg for now
656
            delete errMsg;
657
            break;
621
            break;
658
        default:
622
        default:
659
            //XXXX ignore error for now
623
            lexer.pushBack();
624
            // XXX ErrorReport: unexpected token
625
            return 0;
660
            break;
626
            break;
661
    }
627
    }
628
629
    if (lexer.nextToken()->type != Token::L_PAREN) {
630
        lexer.pushBack();
631
        //XXX ErrorReport: left parenthesis expected
632
        delete nodeExpr;
633
        return 0;
634
    }
635
    if (nodeTok->type == Token::PROC_INST &&
636
        lexer.peek()->type == Token::LITERAL) {
637
        Token* tok = lexer.nextToken();
638
        ((BasicNodeExpr*)nodeExpr)->setNodeName(tok->value);
639
    }
640
    if (lexer.nextToken()->type != Token::R_PAREN) {
641
        lexer.pushBack();
642
        //XXX ErrorReport: right parenthesis expected (or literal for pi)
643
        delete nodeExpr;
644
        return 0;
645
    }
646
662
    return nodeExpr;
647
    return nodeExpr;
663
} //-- createNodeExpr
648
} //-- createNodeExpr
664
649
 Lines 666-702    Link Here 
666
 * Creates a PathExpr using the given ExprLexer
651
 * Creates a PathExpr using the given ExprLexer
667
 * @param lexer the ExprLexer for retrieving Tokens
652
 * @param lexer the ExprLexer for retrieving Tokens
668
**/
653
**/
669
PathExpr* ExprParser::createPathExpr(ExprLexer& lexer) {
654
Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
670
655
656
    Expr* expr = 0;
671
657
672
    //-- check for RootExpr
658
    Token* tok = lexer.peek();
673
    if ( lexer.countRemainingTokens() == 1 ) {
659
674
        if ( lexer.peek()->type == Token::PARENT_OP ) {
660
    // is this a root expression?
675
            lexer.nextToken(); //-- eat token
661
    if (tok->type == Token::PARENT_OP) {
676
            return new RootExpr();
662
        lexer.nextToken();
677
        }
663
        if (!isLocationStepToken(lexer.peek()))
664
            return new RootExpr;
665
666
        lexer.pushBack();
678
    }
667
    }
679
668
669
    // parse first step (possibly a FilterExpr)
670
    if (tok->type != Token::PARENT_OP &&
671
        tok->type != Token::ANCESTOR_OP) {
672
        if (isFilterExprToken(tok)) {
673
            expr = createFilterExpr(lexer);
674
        }
675
        else
676
            expr = createLocationStep(lexer);
677
678
        if (!expr) 
679
            return 0;
680
681
        // is this a singlestep path expression?
682
        tok = lexer.peek();
683
        if (tok->type != Token::PARENT_OP &&
684
            tok->type != Token::ANCESTOR_OP)
685
            return expr;
686
    }
687
    
688
    //we have a pathexpression containing several steps
680
    PathExpr* pathExpr = new PathExpr();
689
    PathExpr* pathExpr = new PathExpr();
681
    short ancestryOp = PathExpr::RELATIVE_OP;
690
    if (expr)
691
        pathExpr->addExpr(expr, PathExpr::RELATIVE_OP);
682
692
683
    while ( lexer.hasMoreTokens() ) {
693
    // this is ugly
684
        Token* tok = lexer.nextToken();
694
    while (1) {
685
        if ( lexer.isOperatorToken(tok) ) {
695
        short ancestryOp;
686
            lexer.pushBack();
696
        tok = lexer.nextToken();
687
            return pathExpr;
697
        switch (tok->type) {
688
        }
689
        switch ( tok->type ) {
690
            case Token::R_PAREN:
691
            case Token::R_BRACKET:
692
            case Token::UNION_OP:
693
                //Marina, addition start
694
                // When parsing a list of parameters for a function comma should signal a spot
695
                // without it further processing pathExpr was causing "invalid token" error
696
            case Token::COMMA:
697
                // Marina, addition ends
698
                lexer.pushBack();
699
                return pathExpr;
700
            case Token::ANCESTOR_OP :
698
            case Token::ANCESTOR_OP :
701
                ancestryOp = PathExpr::ANCESTOR_OP;
699
                ancestryOp = PathExpr::ANCESTOR_OP;
702
                break;
700
                break;
 Lines 705-790    Link Here 
705
                break;
703
                break;
706
            default:
704
            default:
707
                lexer.pushBack();
705
                lexer.pushBack();
708
                pathExpr->addPatternExpr(createPatternExpr(lexer), ancestryOp);
706
                return pathExpr;
709
                ancestryOp = PathExpr::RELATIVE_OP;
707
        }
710
                break;
708
        
709
        expr = createLocationStep(lexer);
710
        if (!expr) {
711
            delete pathExpr;
712
            return 0;
711
        }
713
        }
714
        
715
        pathExpr->addExpr(expr, ancestryOp);
712
    }
716
    }
713
717
714
    /* <debug> *
715
    String tmp;
716
    pathExpr->toString(tmp);
717
    cout << "creating pathExpr: " << tmp << endl;
718
    /* </debug> */
719
720
    return pathExpr;
718
    return pathExpr;
721
} //-- createPathExpr
719
} //-- createPathExpr
722
720
723
/**
721
/**
724
 * Creates a PatternExpr using the given ExprLexer
722
 * Creates a PathExpr using the given ExprLexer
723
 * XXX temporary use as top of XSLT Pattern
725
 * @param lexer the ExprLexer for retrieving Tokens
724
 * @param lexer the ExprLexer for retrieving Tokens
726
**/
725
**/
727
PatternExpr* ExprParser::createPatternExpr(ExprLexer& lexer) {
726
Expr* ExprParser::createUnionExpr(ExprLexer& lexer) {
728
727
729
    PatternExpr* pExpr = 0;
728
    Expr* expr = createPathExpr(lexer);
730
    Token* tok = lexer.peek();
729
    if (!expr)
731
    if ( isLocationStepToken(tok) ) {
730
        return 0;
732
        pExpr = createLocationStep(lexer);
731
    
733
    }
732
    if (lexer.peek()->type != Token::UNION_OP)
734
    else if ( isFilterExprToken(tok) ) {
733
        return expr;
735
        pExpr = createFilterExpr(lexer);
736
    }
737
    else {
738
#if 0
739
        // XXX DEBUG OUTPUT
740
        cout << "invalid token: " << tok->value << endl;
741
#endif
742
        //-- eat token for now
743
        lexer.nextToken();
744
    }
745
    return pExpr;
746
} //-- createPatternExpr
747
734
748
/**
749
 * Creates a PathExpr using the given ExprLexer
750
 * @param lexer the ExprLexer for retrieving Tokens
751
**/
752
UnionExpr* ExprParser::createUnionExpr(ExprLexer& lexer) {
753
    UnionExpr* unionExpr = new UnionExpr();
735
    UnionExpr* unionExpr = new UnionExpr();
736
    unionExpr->addExpr(expr);
754
737
755
    while ( lexer.hasMoreTokens() ) {
738
    while (lexer.peek()->type == Token::UNION_OP) {
756
        Token* tok = lexer.nextToken();
739
        lexer.nextToken(); //-- eat token
757
        switch ( tok->type ) {
758
740
759
            case Token::R_PAREN:
741
        expr = createPathExpr(lexer);
760
            case Token::R_BRACKET:
742
        if (!expr) {
761
                lexer.pushBack();
743
            delete unionExpr;
762
                return unionExpr;
744
            return 0;
763
            case Token::UNION_OP :
764
                //-- eat token
765
                break;
766
            default:
767
                lexer.pushBack();
768
                unionExpr->addPathExpr(createPathExpr(lexer));
769
                break;
770
        }
745
        }
746
        unionExpr->addExpr(expr);
771
    }
747
    }
772
    //String tmp;
748
773
    //unionExpr->toString(tmp);
774
    //cout << "creating UnionExpr: " << tmp << endl;
775
    return unionExpr;
749
    return unionExpr;
776
} //-- createUnionExpr
750
} //-- createUnionExpr
777
751
778
MBool ExprParser::isFilterExprToken(Token* token) {
752
MBool ExprParser::isFilterExprToken(Token* token) {
779
    if ( !token ) return MB_FALSE;
780
    switch (token->type) {
753
    switch (token->type) {
781
        case Token::LITERAL:
754
        case Token::LITERAL:
782
        case Token::NUMBER:
755
        case Token::NUMBER:
783
        case Token::FUNCTION_NAME:
756
        case Token::FUNCTION_NAME:
784
        case Token::VAR_REFERENCE:
757
        case Token::VAR_REFERENCE:
785
        case Token::L_PAREN:            // grouping expr
758
        case Token::L_PAREN:            // grouping expr
786
        case Token::PARENT_NODE:
787
        case Token::SELF_NODE :
788
            return MB_TRUE;
759
            return MB_TRUE;
789
        default:
760
        default:
790
            return MB_FALSE;
761
            return MB_FALSE;
 Lines 792-806    Link Here 
792
} //-- isFilterExprToken
763
} //-- isFilterExprToken
793
764
794
MBool ExprParser::isLocationStepToken(Token* token) {
765
MBool ExprParser::isLocationStepToken(Token* token) {
795
    if (!token) return MB_FALSE;
766
    switch (token->type) {
796
    return ((token->type == Token::AXIS_IDENTIFIER) || isNodeTypeToken(token));
767
        case Token::AXIS_IDENTIFIER :
768
        case Token::AT_SIGN :
769
        case Token::PARENT_NODE :
770
        case Token::SELF_NODE :
771
            return MB_TRUE;
772
        default:
773
            return isNodeTypeToken(token);
774
    }
797
} //-- isLocationStepToken
775
} //-- isLocationStepToken
798
776
799
MBool ExprParser::isNodeTypeToken(Token* token) {
777
MBool ExprParser::isNodeTypeToken(Token* token) {
800
    if (!token) return MB_FALSE;
778
    switch (token->type) {
801
802
    switch ( token->type ) {
803
        case Token::AT_SIGN:
804
        case Token::CNAME:
779
        case Token::CNAME:
805
        case Token::COMMENT:
780
        case Token::COMMENT:
806
        case Token::NODE :
781
        case Token::NODE :
 Lines 810-816    Link Here 
810
        default:
785
        default:
811
            return MB_FALSE;
786
            return MB_FALSE;
812
    }
787
    }
813
} //-- isLocationStepToken
788
} //-- isNodeTypeToken
814
789
815
/**
790
/**
816
 * Using the given lexer, parses the tokens if they represent a predicate list
791
 * Using the given lexer, parses the tokens if they represent a predicate list
 Lines 820-862    Link Here 
820
 * @param lexer the ExprLexer to use for parsing tokens
795
 * @param lexer the ExprLexer to use for parsing tokens
821
 * @return 0 if successful, or a String pointer to the error message
796
 * @return 0 if successful, or a String pointer to the error message
822
**/
797
**/
823
String* ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
798
MBool ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
824
799
825
    String* errorMsg = 0;
800
    String* errorMsg = 0;
826
801
827
    Token* tok = lexer.peek();
802
    while (lexer.peek()->type == Token::L_BRACKET) {
828
803
        //-- eat Token
829
    if ( !tok ) return 0; //-- no predicates
804
        lexer.nextToken();
830
    if ( tok->type != Token::L_BRACKET ) return 0; //-- not start of predicate list
831
832
    lexer.nextToken();
833
805
834
    while ( lexer.hasMoreTokens() ) {
806
        Expr* expr = createExpr(lexer);
835
        tok = lexer.peek();
807
        if (!expr)
836
        if(!tok) {
808
            return MB_FALSE;
837
            //-- error missing ']'
838
            errorMsg = new String("missing close of predicate expression ']'");
839
            break;
840
        }
841
        if ( tok->type == Token::R_BRACKET) {
842
            lexer.nextToken(); //-- eat ']'
843
809
810
        predicateList->add(expr);
844
811
845
            //-- Fix: look ahead at next token for mulitple predicates - Marina M.
812
        if (lexer.nextToken()->type != Token::R_BRACKET) {
846
            tok = lexer.peek();
813
            lexer.pushBack();
847
            if ((!tok) || ( tok->type != Token::L_BRACKET )) break;
814
            //XXX ErrorReport: right bracket expected
848
            //-- /Fix
815
            return MB_FALSE;
849
        }
816
        }
850
851
        //-- Fix: handle multiple predicates - Marina M.
852
        if (tok->type == Token::L_BRACKET)
853
            lexer.nextToken(); //-- swallow '['
854
        //-- /Fix
855
856
        Expr* expr = createExpr(lexer);
857
        predicateList->add(expr);
858
    }
817
    }
859
    return errorMsg;
818
    return MB_TRUE;
860
819
861
} //-- parsePredicates
820
} //-- parsePredicates
862
821
 Lines 867-919    Link Here 
867
 * error message.
826
 * error message.
868
 * @param list, the List to add parameter expressions to
827
 * @param list, the List to add parameter expressions to
869
 * @param lexer the ExprLexer to use for parsing tokens
828
 * @param lexer the ExprLexer to use for parsing tokens
870
 * @return 0 if successful, or a String pointer to the error message
829
 * @return MB_TRUE if successful, or a MB_FALSE otherwise
871
**/
830
**/
872
String* ExprParser::parseParameters(List* list, ExprLexer& lexer) {
831
MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer) {
873
874
    String* errorMsg = 0;
875
876
    Token* tok = lexer.peek();
877
832
878
    if ( !tok ) return 0; //-- no params
833
    if (lexer.nextToken()->type != Token::L_PAREN) {
879
    if ( tok->type != Token::L_PAREN ) return 0; //-- not start of param list
834
        lexer.pushBack();
835
        //XXX ErrorReport: left parenthesis expected
836
        return MB_FALSE;
837
    }
880
838
881
    lexer.nextToken(); //-- eat L_PAREN
839
    if (lexer.peek()->type == Token::R_PAREN) {
840
        lexer.nextToken();
841
        return MB_TRUE;
842
    }
882
843
883
    MBool done     = MB_FALSE;
844
    while (1) {
884
    MBool foundSep = MB_FALSE;
845
        Expr* expr = createExpr(lexer);
846
        if (!expr)
847
            return MB_FALSE;
885
848
886
    while ( lexer.hasMoreTokens() && !done) {
849
        fnCall->addParam(expr);
887
        tok = lexer.peek();
850
            
888
        switch ( tok->type ) {
851
        switch (lexer.nextToken()->type) {
889
            case Token::R_PAREN :
852
            case Token::R_PAREN :
890
                if (foundSep) errorMsg = new String("missing expression after ','");
853
                return MB_TRUE;
891
                lexer.nextToken(); //-- eat R_PAREN
892
                done = MB_TRUE;
893
                break;
894
            case Token::COMMA: //-- param separator
854
            case Token::COMMA: //-- param separator
895
                //-- eat COMMA
896
                lexer.nextToken();
897
                foundSep = MB_TRUE;
898
                break;
855
                break;
899
            default:
856
            default:
900
                if ((list->getLength() > 0) && (!foundSep)) {
857
                lexer.pushBack();
901
                    errorMsg = new String("missing ',' or ')'");
858
                //XXX ErrorReport: right parenthesis or comma expected
902
                    done = MB_TRUE;
859
                return MB_FALSE;
903
                    break;
904
                }
905
                foundSep = MB_FALSE;
906
                Expr* expr = createExpr(lexer);
907
                list->add(expr);
908
                break;
909
        }
860
        }
910
    }
861
    }
911
    return errorMsg;
862
863
    return MB_FALSE;
912
864
913
} //-- parseParameters
865
} //-- parseParameters
914
866
915
short ExprParser::precedenceLevel(short tokenType) {
867
short ExprParser::precedenceLevel(short tokenType) {
916
    switch(tokenType) {
868
    switch (tokenType) {
917
        case Token::OR_OP:
869
        case Token::OR_OP:
918
            return 1;
870
            return 1;
919
        case Token::AND_OP:
871
        case Token::AND_OP:
(-)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 (-27 / +64 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 49-55    Link Here 
49
 * Note: The object references in parameters will be deleted when this
49
 * Note: The object references in parameters will be deleted when this
50
 * FunctionCall gets destroyed.
50
 * FunctionCall gets destroyed.
51
**/
51
**/
52
FunctionCall::FunctionCall(const String& name) {
52
FunctionCall::FunctionCall(const String& name)
53
{
53
    //-- copy name
54
    //-- copy name
54
    this->name = name;
55
    this->name = name;
55
} //-- FunctionCall
56
} //-- FunctionCall
 Lines 59-71    Link Here 
59
 * Note: The object references in parameters will be deleted when this
60
 * Note: The object references in parameters will be deleted when this
60
 * FunctionCall gets destroyed.
61
 * FunctionCall gets destroyed.
61
**/
62
**/
62
FunctionCall::FunctionCall(const String& name, List* parameters) {
63
FunctionCall::FunctionCall(const String& name, List* parameters)
64
{
63
    //-- copy name
65
    //-- copy name
64
    this->name = name;
66
    this->name = name;
65
67
66
    if (parameters) {
68
    if (parameters) {
67
       ListIterator* pIter = parameters->iterator();
69
       ListIterator* pIter = parameters->iterator();
68
       while ( pIter->hasNext() ) {
70
       while (pIter->hasNext()) {
69
           params.add(pIter->next());
71
           params.add(pIter->next());
70
       }
72
       }
71
       delete pIter;
73
       delete pIter;
 Lines 77-86    Link Here 
77
/**
79
/**
78
 * Destructor
80
 * Destructor
79
**/
81
**/
80
FunctionCall::~FunctionCall() {
82
FunctionCall::~FunctionCall()
81
83
{
82
    ListIterator* iter = params.iterator();
84
    ListIterator* iter = params.iterator();
83
    while ( iter->hasNext() ) {
85
    while (iter->hasNext()) {
84
        iter->next();
86
        iter->next();
85
        Expr* expr = (Expr*) iter->remove();
87
        Expr* expr = (Expr*) iter->remove();
86
        delete expr;
88
        delete expr;
 Lines 96-113    Link Here 
96
 * Adds the given parameter to this FunctionCall's parameter list
98
 * Adds the given parameter to this FunctionCall's parameter list
97
 * @param expr the Expr to add to this FunctionCall's parameter list
99
 * @param expr the Expr to add to this FunctionCall's parameter list
98
**/
100
**/
99
void FunctionCall::addParam(Expr* expr) {
101
void FunctionCall::addParam(Expr* expr)
100
    if ( expr ) params.add(expr);
102
{
103
    if (expr)
104
      params.add(expr);
101
} //-- addParam
105
} //-- addParam
102
106
103
/**
107
/**
108
 * Returns the default priority of this Expr based on the given Node,
109
 * context Node, and ContextState.
110
**/
111
double FunctionCall::getDefaultPriority(Node* node,
112
                                        Node* context,
113
                                        ContextState* cs)
114
{
115
    return 0.5;
116
} //-- getDefaultPriority
117
118
/**
119
 * Determines whether this Expr matches the given node within
120
 * the given context
121
**/
122
MBool FunctionCall::matches(Node* node, Node* context, ContextState* cs)
123
{
124
    MBool result = MB_FALSE;
125
    ExprResult* exprResult = evaluate(node, cs);
126
    if (exprResult->getResultType() == ExprResult::NODESET) {
127
        NodeSet* nodes = (NodeSet*)exprResult;
128
        result = (nodes->contains(node));
129
    }
130
    delete exprResult;
131
    return result;
132
} //-- matches
133
134
/**
104
 * Evaluates the given Expression and converts it's result to a String.
135
 * Evaluates the given Expression and converts it's result to a String.
105
 * The value is appended to the given destination String
136
 * The value is appended to the given destination String
106
**/
137
**/
107
void FunctionCall::evaluateToString
138
void FunctionCall::evaluateToString(Expr* expr, Node* context, 
108
    (Expr* expr, Node* context, ContextState* cs, String& dest)
139
                                    ContextState* cs, String& dest)
109
{
140
{
110
    if (!expr) return;
141
    if (!expr)
142
        return;
111
    ExprResult* exprResult = expr->evaluate(context, cs);
143
    ExprResult* exprResult = expr->evaluate(context, cs);
112
    exprResult->stringValue(dest);
144
    exprResult->stringValue(dest);
113
    delete exprResult;
145
    delete exprResult;
 Lines 116-126    Link Here 
116
/**
148
/**
117
 * Evaluates the given Expression and converts it's result to a number.
149
 * Evaluates the given Expression and converts it's result to a number.
118
**/
150
**/
119
double FunctionCall::evaluateToNumber
151
double FunctionCall::evaluateToNumber(Expr* expr, Node* context,
120
    (Expr* expr, Node* context, ContextState* cs)
152
                                      ContextState* cs)
121
{
153
{
122
    double result = Double::NaN;
154
    double result = Double::NaN;
123
    if (!expr) return result;
155
    if (!expr)
156
      return result;
124
    ExprResult* exprResult = expr->evaluate(context, cs);
157
    ExprResult* exprResult = expr->evaluate(context, cs);
125
    result =  exprResult->numberValue();
158
    result =  exprResult->numberValue();
126
    delete exprResult;
159
    delete exprResult;
 Lines 131-149    Link Here 
131
 * Returns the name of this FunctionCall
164
 * Returns the name of this FunctionCall
132
 * @return the name of this FunctionCall
165
 * @return the name of this FunctionCall
133
**/
166
**/
134
const String& FunctionCall::getName() {
167
const String& FunctionCall::getName()
135
    return (const String&) this->name;
168
{
169
    return (const String&)this->name;
136
} //-- getName
170
} //-- getName
137
171
138
/**
172
/**
139
 * Called to check number of parameters
173
 * Called to check number of parameters
140
**/
174
**/
141
MBool FunctionCall::requireParams
175
MBool FunctionCall::requireParams (int paramCountMin,
142
    (int paramCountMin, int paramCountMax, ContextState* cs)
176
                                   int paramCountMax,
177
                                   ContextState* cs)
143
{
178
{
144
145
    int argc = params.getLength();
179
    int argc = params.getLength();
146
    if (( argc < paramCountMin) || (argc > paramCountMax)) {
180
    if ((argc < paramCountMin) || (argc > paramCountMax)) {
147
        String err(INVALID_PARAM_COUNT);
181
        String err(INVALID_PARAM_COUNT);
148
        toString(err);
182
        toString(err);
149
        cs->recieveError(err);
183
        cs->recieveError(err);
 Lines 155-161    Link Here 
155
/**
189
/**
156
 * Called to check number of parameters
190
 * Called to check number of parameters
157
**/
191
**/
158
MBool FunctionCall::requireParams(int paramCountMin, ContextState* cs) {
192
MBool FunctionCall::requireParams(int paramCountMin, ContextState* cs)
193
{
159
    int argc = params.getLength();
194
    int argc = params.getLength();
160
    if (argc < paramCountMin) {
195
    if (argc < paramCountMin) {
161
        String err(INVALID_PARAM_COUNT);
196
        String err(INVALID_PARAM_COUNT);
 Lines 170-176    Link Here 
170
 * Sets the function name of this FunctionCall
205
 * Sets the function name of this FunctionCall
171
 * @param name the name of this Function
206
 * @param name the name of this Function
172
**/
207
**/
173
void FunctionCall::setName(const String& name) {
208
void FunctionCall::setName(const String& name)
209
{
174
    this->name.clear();
210
    this->name.clear();
175
    this->name.append(name);
211
    this->name.append(name);
176
} //-- setName
212
} //-- setName
 Lines 183-200    Link Here 
183
 * other #toString() methods for Expressions.
219
 * other #toString() methods for Expressions.
184
 * @return the String representation of this NodeExpr.
220
 * @return the String representation of this NodeExpr.
185
**/
221
**/
186
void FunctionCall::toString(String& dest) {
222
void FunctionCall::toString(String& dest)
223
{
187
    dest.append(this->name);
224
    dest.append(this->name);
188
    dest.append('(');
225
    dest.append('(');
189
    //-- add parameters
226
    //-- add parameters
190
    ListIterator* iterator = params.iterator();
227
    ListIterator* iterator = params.iterator();
191
    int argc = 0;
228
    int argc = 0;
192
    while ( iterator->hasNext() ) {
229
    while (iterator->hasNext()) {
193
        if ( argc > 0 ) dest.append(',');
230
        if (argc > 0)
231
            dest.append(',');
194
        Expr* expr = (Expr*)iterator->next();
232
        Expr* expr = (Expr*)iterator->next();
195
        expr->toString(dest);
233
        expr->toString(dest);
196
        ++argc;
234
        ++argc;
197
198
    }
235
    }
199
    delete iterator;
236
    delete iterator;
200
    dest.append(')');
237
    dest.append(')');
(-)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 (-79 / +75 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 43-95    Link Here 
43
/**
43
/**
44
 * Creates a new PathExpr
44
 * Creates a new PathExpr
45
**/
45
**/
46
PathExpr::PathExpr() {
46
PathExpr::PathExpr()
47
{
47
    //-- do nothing
48
    //-- do nothing
48
}
49
}
49
50
50
/**
51
/**
51
 * Destructor, will delete all Pattern Expressions
52
 * Destructor, will delete all Expressions
52
**/
53
**/
53
PathExpr::~PathExpr() {
54
PathExpr::~PathExpr()
55
{
54
    ListIterator* iter = expressions.iterator();
56
    ListIterator* iter = expressions.iterator();
55
    while ( iter->hasNext() ) {
57
    while (iter->hasNext()) {
56
         iter->next();
58
         iter->next();
57
         PathExprItem* pxi = (PathExprItem*)iter->remove();
59
         PathExprItem* pxi = (PathExprItem*)iter->remove();
58
         delete pxi->pExpr;
60
         delete pxi->expr;
59
         delete pxi;
61
         delete pxi;
60
    }
62
    }
61
    delete iter;
63
    delete iter;
62
} //-- ~PathExpr
64
} //-- ~PathExpr
63
65
64
/**
66
/**
65
 * Adds the PatternExpr to this PathExpr
67
 * Adds the Expr to this PathExpr
66
 * @param expr the Expr to add to this PathExpr
68
 * @param expr the Expr to add to this PathExpr
67
 * @param index the index at which to add the given Expr
69
 * @param index the index at which to add the given Expr
68
**/
70
**/
69
void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp) {
71
void PathExpr::addExpr(int index, Expr* expr, short ancestryOp)
72
{
70
    if (expr) {
73
    if (expr) {
71
        PathExprItem* pxi = new PathExprItem;
74
        PathExprItem* pxi = new PathExprItem;
72
        pxi->pExpr = expr;
75
        pxi->expr = expr;
73
        pxi->ancestryOp = ancestryOp;
76
        pxi->ancestryOp = ancestryOp;
74
        expressions.insert(index, pxi);
77
        expressions.insert(index, pxi);
75
    }
78
    }
76
} //-- addPattenExpr
79
} //-- addPattenExpr
77
80
78
/**
81
/**
79
 * Adds the PatternExpr to this PathExpr
82
 * Adds the Expr to this PathExpr
80
 * @param expr the Expr to add to this PathExpr
83
 * @param expr the Expr to add to this PathExpr
81
**/
84
**/
82
void PathExpr::addPatternExpr(PatternExpr* expr, short ancestryOp) {
85
void PathExpr::addExpr(Expr* expr, short ancestryOp)
86
{
83
    if (expr) {
87
    if (expr) {
84
        PathExprItem* pxi = new PathExprItem;
88
        PathExprItem* pxi = new PathExprItem;
85
        pxi->pExpr = expr;
89
        pxi->expr = expr;
86
        pxi->ancestryOp = ancestryOp;
90
        pxi->ancestryOp = ancestryOp;
87
        expressions.add(pxi);
91
        expressions.add(pxi);
88
    }
92
    }
89
} //-- addPattenExpr
93
} //-- addPattenExpr
90
94
91
MBool PathExpr::isAbsolute() {
95
MBool PathExpr::isAbsolute()
92
    if ( expressions.getLength() > 0 ) {
96
{
97
    if (expressions.getLength() > 0) {
93
        ListIterator* iter = expressions.iterator();
98
        ListIterator* iter = expressions.iterator();
94
        PathExprItem* pxi = (PathExprItem*)iter->next();
99
        PathExprItem* pxi = (PathExprItem*)iter->next();
95
        delete iter;
100
        delete iter;
 Lines 98-106    Link Here 
98
    return MB_FALSE;
103
    return MB_FALSE;
99
} //-- isAbsolute
104
} //-- isAbsolute
100
105
101
    //------------------------------------/
106
    //-----------------------------/
102
  //- Virtual methods from PatternExpr -/
107
  //- Virtual methods from Expr -/
103
//------------------------------------/
108
//-----------------------------/
104
109
105
/**
110
/**
106
 * Evaluates this Expr based on the given context node and processor state
111
 * Evaluates this Expr based on the given context node and processor state
 Lines 109-132    Link Here 
109
 * for evaluation
114
 * for evaluation
110
 * @return the result of the evaluation
115
 * @return the result of the evaluation
111
**/
116
**/
112
ExprResult* PathExpr::evaluate(Node* context, ContextState* cs) {
117
ExprResult* PathExpr::evaluate(Node* context, ContextState* cs)
118
{
113
    //-- add selectExpr functionality here
119
    //-- add selectExpr functionality here
114
120
115
    if ( (!context)  || (expressions.getLength() == 0))
121
    if (!context || (expressions.getLength() == 0))
116
            return new NodeSet(0);
122
            return new NodeSet(0);
117
123
118
    NodeSet* nodes = new NodeSet();
124
    NodeSet* nodes = new NodeSet();
119
125
120
    if ((isAbsolute()) && (context->getNodeType() != Node::DOCUMENT_NODE))
126
    if (isAbsolute() && (context->getNodeType() != Node::DOCUMENT_NODE))
121
        nodes->add(context->getOwnerDocument());
127
        nodes->add(context->getOwnerDocument());
122
    else
128
    else
123
        nodes->add(context);
129
        nodes->add(context);
124
130
125
126
    ListIterator* iter = expressions.iterator();
131
    ListIterator* iter = expressions.iterator();
127
128
    while ( iter->hasNext() ) {
129
132
133
    while (iter->hasNext()) {
130
        PathExprItem* pxi = (PathExprItem*)iter->next();
134
        PathExprItem* pxi = (PathExprItem*)iter->next();
131
        NodeSet* tmpNodes = 0;
135
        NodeSet* tmpNodes = 0;
132
        cs->getNodeSetStack()->push(nodes);
136
        cs->getNodeSetStack()->push(nodes);
 Lines 134-155    Link Here 
134
            Node* node = nodes->get(i);
138
            Node* node = nodes->get(i);
135
            
139
            
136
            NodeSet* resNodes;
140
            NodeSet* resNodes;
137
            if ( pxi->ancestryOp == ANCESTOR_OP) {
141
            if (pxi->ancestryOp == ANCESTOR_OP) {
138
                resNodes = new NodeSet;
142
                resNodes = new NodeSet;
139
                evalDescendants(pxi->pExpr, node, cs, resNodes);
143
                evalDescendants(pxi->expr, node, cs, resNodes);
140
            }
144
            }
141
            else {
145
            else {
142
                ExprResult *res = pxi->pExpr->evaluate(node, cs);
146
                ExprResult *res = pxi->expr->evaluate(node, cs);
143
                if (!res || res->getResultType() != ExprResult::NODESET) {
147
                if (!res || (res->getResultType() != ExprResult::NODESET)) {
144
                    //XXX ErrorReport: report nonnodeset error
148
                    //XXX ErrorReport: report nonnodeset error
145
                    delete res;
149
                    delete res;
146
                    res = new NodeSet;
150
                    res = new NodeSet;
147
                }
151
                }
148
149
                resNodes = (NodeSet*)res;
152
                resNodes = (NodeSet*)res;
150
            }
153
            }
151
154
152
            if ( tmpNodes ) {
155
            if (tmpNodes) {
153
                resNodes->copyInto(*tmpNodes);
156
                resNodes->copyInto(*tmpNodes);
154
                delete resNodes;
157
                delete resNodes;
155
            }
158
            }
 Lines 159-165    Link Here 
159
        }
162
        }
160
        delete (NodeSet*) cs->getNodeSetStack()->pop();
163
        delete (NodeSet*) cs->getNodeSetStack()->pop();
161
        nodes = tmpNodes;
164
        nodes = tmpNodes;
162
        if ( !nodes || nodes->size() == 0 ) break;
165
        if (!nodes || (nodes->size() == 0)) break;
163
    }
166
    }
164
    delete iter;
167
    delete iter;
165
168
 Lines 168-181    Link Here 
168
171
169
/**
172
/**
170
 * Selects from the descendants of the context node
173
 * Selects from the descendants of the context node
171
 * all nodes that match the PatternExpr
174
 * all nodes that match the Expr
172
 * -- this will be moving to a Utility class
175
 * -- this will be moving to a Utility class
173
**/
176
**/
174
void PathExpr::evalDescendants
177
void PathExpr::evalDescendants (Expr* expr, Node* context,
175
    (PatternExpr* pExpr, Node* context, ContextState* cs, NodeSet* resNodes)
178
                                ContextState* cs, NodeSet* resNodes)
176
{
179
{
177
    ExprResult *res = pExpr->evaluate(context, cs);
180
    ExprResult *res = expr->evaluate(context, cs);
178
    if (!res || res->getResultType() != ExprResult::NODESET) {
181
    if (!res || (res->getResultType() != ExprResult::NODESET)) {
179
        //XXX ErrorReport: report nonnodeset error
182
        //XXX ErrorReport: report nonnodeset error
180
    }
183
    }
181
    else
184
    else
 Lines 185-194    Link Here 
185
    MBool filterWS = cs->isStripSpaceAllowed(context);
188
    MBool filterWS = cs->isStripSpaceAllowed(context);
186
    
189
    
187
    Node* child = context->getFirstChild();
190
    Node* child = context->getFirstChild();
188
    while(child) {
191
    while (child) {
189
        if(!(filterWS && child->getNodeType() == Node::TEXT_NODE &&
192
        if (!(filterWS && (child->getNodeType() == Node::TEXT_NODE) &&
190
             XMLUtils::shouldStripTextnode(child->getNodeValue())))
193
             XMLUtils::shouldStripTextnode(child->getNodeValue())))
191
            evalDescendants(pExpr, child, cs, resNodes);
194
            evalDescendants(expr, child, cs, resNodes);
192
        child = child->getNextSibling();
195
        child = child->getNextSibling();
193
    }
196
    }
194
} //-- evalDescendants
197
} //-- evalDescendants
 Lines 199-229    Link Here 
199
 * If this pattern does not match the given Node under the current context Node and
202
 * If this pattern does not match the given Node under the current context Node and
200
 * ContextState then Negative Infinity is returned.
203
 * ContextState then Negative Infinity is returned.
201
**/
204
**/
202
double PathExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
205
double PathExpr::getDefaultPriority(Node* node, Node* context,
203
206
                                    ContextState* cs)
204
    if ( matches(node, context, cs) ) {
207
{
208
    if (matches(node, context, cs)) {
205
        int size = expressions.getLength();
209
        int size = expressions.getLength();
206
        if ( size == 1) {
210
        if (size == 1) {
207
            ListIterator* iter = expressions.iterator();
211
            ListIterator* iter = expressions.iterator();
208
            PathExprItem* pxi = (PathExprItem*)iter->next();
212
            PathExprItem* pxi = (PathExprItem*)iter->next();
209
            delete iter;
213
            delete iter;
210
            return pxi->pExpr->getDefaultPriority(node, context, cs);
214
            return pxi->expr->getDefaultPriority(node, context, cs);
211
        }
215
        }
212
        else if ( size > 1 ) {
216
        else if (size > 1) 
213
            return 0.5;
217
            return 0.5;
214
        }
215
    }
218
    }
216
    return Double::NEGATIVE_INFINITY;
219
    return Double::NEGATIVE_INFINITY;
217
} //-- getDefaultPriority
220
} //-- getDefaultPriority
218
221
219
/**
222
/**
220
 * Determines whether this PatternExpr matches the given node within
223
 * Determines whether this Expr matches the given node within
221
 * the given context
224
 * the given context
222
**/
225
**/
223
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
226
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs)
224
227
{
225
228
    if (!node || (expressions.getLength() == 0))
226
    if ( (!node)  || (expressions.getLength() == 0))
227
       return MB_FALSE;
229
       return MB_FALSE;
228
230
229
    //-- for performance reasons, I've duplicated some code
231
    //-- for performance reasons, I've duplicated some code
 Lines 241-247    Link Here 
241
            {
243
            {
242
                Node* ancestor = node;
244
                Node* ancestor = node;
243
                while (ancestor = cs->getParentNode(ancestor))  {
245
                while (ancestor = cs->getParentNode(ancestor))  {
244
                    if (pxi->pExpr->matches(node, ancestor, cs))
246
                    if (pxi->expr->matches(node, ancestor, cs))
245
                        return MB_TRUE;
247
                        return MB_TRUE;
246
                }
248
                }
247
                break;
249
                break;
 Lines 252-296    Link Here 
252
                if (parent) {
254
                if (parent) {
253
                    //-- make sure node is Document node
255
                    //-- make sure node is Document node
254
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
256
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
255
                        return pxi->pExpr->matches(node, parent, cs);
257
                        return pxi->expr->matches(node, parent, cs);
256
                }
258
                }
257
                break;
259
                break;
258
            }
260
            }
259
            default:
261
            default:
260
                return pxi->pExpr->matches(node, context, cs);
262
                return pxi->expr->matches(node, context, cs);
261
262
        }
263
        }
263
264
264
        return MB_FALSE;
265
        return MB_FALSE;
265
    }
266
    }
266
267
267
268
    //-- if we reach here we have subpaths...
268
    //-- if we reach here we have subpaths...
269
270
    NodeSet nodes(3);
269
    NodeSet nodes(3);
271
    NodeSet tmpNodes(3);
270
    NodeSet tmpNodes(3);
272
271
273
    nodes.add(node);
272
    nodes.add(node);
274
273
275
276
    ListIterator* iter = expressions.iterator();
274
    ListIterator* iter = expressions.iterator();
277
    iter->reverse();
275
    iter->reverse();
278
276
279
    while ( iter->hasNext() ) {
277
    while (iter->hasNext()) {
280
278
281
        PathExprItem* pxi = (PathExprItem*)iter->next();
279
        PathExprItem* pxi = (PathExprItem*)iter->next();
282
280
283
        for (int i = 0; i < nodes.size(); i++) {
281
        for (int i = 0; i < nodes.size(); i++) {
284
285
            Node* tnode = nodes.get(i);
282
            Node* tnode = nodes.get(i);
286
283
287
                //-- select node's parent or ancestors
284
            //-- select node's parent or ancestors
288
            switch (pxi->ancestryOp) {
285
            switch (pxi->ancestryOp) {
289
                case ANCESTOR_OP:
286
                case ANCESTOR_OP:
290
                {
287
                {
291
                    Node* parent = tnode;
288
                    Node* parent = tnode;
292
                    while (parent = cs->getParentNode(parent))  {
289
                    while (parent = cs->getParentNode(parent))  {
293
                        if (pxi->pExpr->matches(tnode, parent, cs))
290
                        if (pxi->expr->matches(tnode, parent, cs))
294
                            tmpNodes.add(parent);
291
                            tmpNodes.add(parent);
295
                    }
292
                    }
296
                    break;
293
                    break;
 Lines 299-327    Link Here 
299
                {
296
                {
300
                    Node* parent = cs->getParentNode(tnode);
297
                    Node* parent = cs->getParentNode(tnode);
301
                    if (parent) {
298
                    if (parent) {
302
303
                        //-- make sure we have a document node if necessary
299
                        //-- make sure we have a document node if necessary
304
                        if ( !iter->hasNext() )
300
                        if (!iter->hasNext())
305
                            if (parent->getNodeType() != Node::DOCUMENT_NODE) break;
301
                            if (parent->getNodeType() != Node::DOCUMENT_NODE)
306
302
                                break;
307
                        if (pxi->pExpr->matches(tnode, parent, cs))
303
                        if (pxi->expr->matches(tnode, parent, cs))
308
                            tmpNodes.add(parent);
304
                            tmpNodes.add(parent);
309
                    }
305
                    }
310
                    break;
306
                    break;
311
                }
307
                }
312
                default:
308
                default:
313
                    if ( !iter->hasNext() ) {
309
                    if (!iter->hasNext()) {
314
315
                        /*
310
                        /*
316
                          // PREVIOUS // result = pxi->pExpr->matches(tnode, context, cs);
311
                          // PREVIOUS // result = pxi->expr->matches(tnode, context, cs);
317
                          // result was being overwritten if there was more than one
312
                          // result was being overwritten if there was more than one
318
                          // node in nodes during the final iteration  (Marina)
313
                          // node in nodes during the final iteration  (Marina)
319
314
320
                          result = result || pxi->pExpr->matches(tnode, context, cs)
315
                          result = result || pxi->expr->matches(tnode, context, cs)
321
                        */
316
                        */
322
317
323
                        //-- Just return true if we match here
318
                        //-- Just return true if we match here
324
                        if (pxi->pExpr->matches(tnode, context, cs)) {
319
                        if (pxi->expr->matches(tnode, context, cs)) {
325
                            delete iter;
320
                            delete iter;
326
                            return MB_TRUE;
321
                            return MB_TRUE;
327
                        }
322
                        }
 Lines 353-380    Link Here 
353
            doc = node;
348
            doc = node;
354
        else
349
        else
355
            doc = node->getOwnerDocument();
350
            doc = node->getOwnerDocument();
356
        return (MBool) nodes.contains(doc);
351
        return (MBool)nodes.contains(doc);
357
    }
352
    }
358
353
359
    return (MBool) (nodes.size() > 0);
354
    return (MBool)(nodes.size() > 0);
360
355
361
} //-- matches
356
} //-- matches
362
357
363
358
364
/**
359
/**
365
 * Returns the String representation of this PatternExpr.
360
 * Returns the String representation of this Expr.
366
 * @param dest the String to use when creating the String
361
 * @param dest the String to use when creating the String
367
 * representation. The String representation will be appended to
362
 * representation. The String representation will be appended to
368
 *  any data in the destination String, to allow cascading calls to
363
 *  any data in the destination String, to allow cascading calls to
369
 * other #toString() methods for Expressions.
364
 * other #toString() methods for Expressions.
370
 * @return the String representation of this PatternExpr.
365
 * @return the String representation of this Expr.
371
**/
366
**/
372
void PathExpr::toString(String& dest) {
367
void PathExpr::toString(String& dest)
368
{
373
    ListIterator* iter = expressions.iterator();
369
    ListIterator* iter = expressions.iterator();
374
    while ( iter->hasNext() ) {
370
    while (iter->hasNext()) {
375
        //-- set operator
371
        //-- set operator
376
        PathExprItem* pxi = (PathExprItem*)iter->next();
372
        PathExprItem* pxi = (PathExprItem*)iter->next();
377
        switch ( pxi->ancestryOp ) {
373
        switch (pxi->ancestryOp) {
378
            case ANCESTOR_OP:
374
            case ANCESTOR_OP:
379
                dest.append("//");
375
                dest.append("//");
380
                break;
376
                break;
 Lines 384-390    Link Here 
384
            default:
380
            default:
385
                break;
381
                break;
386
        }
382
        }
387
        pxi->pExpr->toString(dest);
383
        pxi->expr->toString(dest);
388
    }
384
    }
389
    delete iter;
385
    delete iter;
390
} //-- toString
386
} //-- 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
(-)UnionExpr.cpp (-39 / +39 lines)
Line     Link Here 
 Lines 43-73    Link Here 
43
**/
43
**/
44
UnionExpr::~UnionExpr() {
44
UnionExpr::~UnionExpr() {
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)
59
} //-- addPathExpr
59
      expressions.add(expr);
60
} //-- addExpr
61
62
/**
63
 * Adds the Expr to this UnionExpr
64
 * @param expr the Expr to add to this UnionExpr
65
**/
66
void UnionExpr::addExpr(int index, Expr* expr) {
67
    if (expr)
68
      expressions.insert(index, expr);
69
} //-- addExpr
60
70
61
/**
62
 * Adds the PathExpr to this UnionExpr
63
 * @param pathExpr the PathExpr to add to this UnionExpr
64
**/
65
void UnionExpr::addPathExpr(int index, PathExpr* pathExpr) {
66
    if (pathExpr) expressions.insert(index, pathExpr);
67
} //-- addPathExpr
68
69
    //------------------------------------/
71
    //------------------------------------/
70
  //- Virtual methods from PatternExpr -/
72
  //- Virtual methods from Expr -/
71
//------------------------------------/
73
//------------------------------------/
72
74
73
/**
75
/**
 Lines 79-99    Link Here 
79
**/
81
**/
80
ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs) {
82
ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs) {
81
83
82
    if ( (!context)  || (expressions.getLength() == 0))
84
    if (!context || (expressions.getLength() == 0))
83
            return new NodeSet(0);
85
            return new NodeSet(0);
84
86
85
    NodeSet* nodes = new NodeSet();
87
    NodeSet* nodes = new NodeSet();
86
88
87
    ListIterator* iter = expressions.iterator();
89
    ListIterator* iter = expressions.iterator();
88
90
89
    while ( iter->hasNext() ) {
91
    while (iter->hasNext()) {
90
92
        Expr* expr = (Expr*)iter->next();
91
        PathExpr* pExpr = (PathExpr*)iter->next();
93
        ExprResult* exprResult = expr->evaluate(context, cs);
92
        NodeSet* tmpNodes = (NodeSet*)pExpr->evaluate(context, cs);
94
        if (exprResult->getResultType() == ExprResult::NODESET) {
93
        for (int j = 0; j < tmpNodes->size(); j++) {
95
            ((NodeSet*)exprResult)->copyInto(*nodes);
94
            nodes->add(tmpNodes->get(j));
95
        }
96
        }
96
        delete tmpNodes;
97
    }
97
    }
98
98
99
    delete iter;
99
    delete iter;
 Lines 106-126    Link Here 
106
 * If this pattern does not match the given Node under the current context Node and
106
 * If this pattern does not match the given Node under the current context Node and
107
 * ContextState then Negative Infinity is returned.
107
 * ContextState then Negative Infinity is returned.
108
**/
108
**/
109
double UnionExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
109
double UnionExpr::getDefaultPriority(Node* node, Node* context,
110
110
				     ContextState* cs) {
111
    //-- find highest priority
111
    //-- find highest priority
112
    double priority = Double::NEGATIVE_INFINITY;
112
    double priority = Double::NEGATIVE_INFINITY;
113
    ListIterator* iter = expressions.iterator();
113
    ListIterator* iter = expressions.iterator();
114
    while ( iter->hasNext() ) {
114
    while (iter->hasNext()) {
115
        PathExpr* pExpr = (PathExpr*)iter->next();
115
        Expr* expr = (Expr*)iter->next();
116
        if ( pExpr->matches(node, context, cs) ) {
116
        if (expr->matches(node, context, cs)) {
117
            double tmpPriority = pExpr->getDefaultPriority(node, context, cs);
117
            double tmpPriority = expr->getDefaultPriority(node, context, cs);
118
            priority = (tmpPriority > priority) ? tmpPriority : priority;
118
            priority = (tmpPriority > priority) ? tmpPriority : priority;
119
        }
119
        }
120
    }
120
    }
121
    delete iter;
121
    delete iter;
122
    return priority;
122
    return priority;
123
124
} //-- getDefaultPriority
123
} //-- getDefaultPriority
125
124
126
/**
125
/**
 Lines 131-139    Link Here 
131
130
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-164    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();
156
155
157
    short count = 0;
156
    short count = 0;
158
    while ( iter->hasNext() ) {
157
    while (iter->hasNext()) {
159
        //-- set operator
158
        //-- set operator
160
        if (count > 0) dest.append(" | ");
159
        if (count > 0)
161
        ((PathExpr*)iter->next())->toString(dest);
160
	  dest.append(" | ");
161
        ((Expr*)iter->next())->toString(dest);
162
        ++count;
162
        ++count;
163
    }
163
    }
164
    delete iter;
164
    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 195-202    Link Here 
195
        namedTemplates.put(name,mObj);
195
        namedTemplates.put(name,mObj);
196
        if ( oldObj ) delete oldObj;
196
        if ( oldObj ) delete oldObj;
197
    }
197
    }
198
    patternExprHash.put(match, exprParser.createPatternExpr(match));
198
    if (match.length() > 0) {
199
    templates.add(xslTemplate);
199
        patternExprHash.put(match, exprParser.createPatternExpr(match));
200
        templates.add(xslTemplate);
201
    }
200
} //-- addTempalte
202
} //-- addTempalte
201
203
202
/**
204
/**

Return to bug 75102