Attachment #30266: parser, lexer, + stuff needed, needs following extra files for bug #75102

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

(-)Makefile.in (-2 / +2 lines)
Line     Link Here 
 Lines 75-86    Link Here 
75
  ../source/xpath/BooleanResult.o \
75
  ../source/xpath/BooleanResult.o \
76
  ../source/xpath/ElementExpr.o \
76
  ../source/xpath/ElementExpr.o \
77
  ../source/xpath/ErrorFunctionCall.o \
77
  ../source/xpath/ErrorFunctionCall.o \
78
  ../source/xpath/Expr.o \
78
  ../source/xpath/ExprLexer.o \
79
  ../source/xpath/ExprLexer.o \
79
  ../source/xpath/ExprParser.o \
80
  ../source/xpath/ExprParser.o \
80
  ../source/xpath/ExtensionFunctionCall.o \
81
  ../source/xpath/ExtensionFunctionCall.o \
81
  ../source/xpath/FilterExpr.o \
82
  ../source/xpath/FilterExpr.o \
82
  ../source/xpath/FunctionCall.o \
83
  ../source/xpath/FunctionCall.o \
83
  ../source/xpath/IdentityExpr.o \
84
  ../source/xpath/LocationStep.o \
84
  ../source/xpath/LocationStep.o \
85
  ../source/xpath/MultiplicativeExpr.o \
85
  ../source/xpath/MultiplicativeExpr.o \
86
  ../source/xpath/NodeSet.o \
86
  ../source/xpath/NodeSet.o \
 Lines 89-95    Link Here 
89
  ../source/xpath/NumberExpr.o \
89
  ../source/xpath/NumberExpr.o \
90
  ../source/xpath/NumberFunctionCall.o \
90
  ../source/xpath/NumberFunctionCall.o \
91
  ../source/xpath/NumberResult.o \
91
  ../source/xpath/NumberResult.o \
92
  ../source/xpath/ParentExpr.o \
93
  ../source/xpath/PathExpr.o \
92
  ../source/xpath/PathExpr.o \
94
  ../source/xpath/PredicateList.o \
93
  ../source/xpath/PredicateList.o \
95
  ../source/xpath/RelationalExpr.o \
94
  ../source/xpath/RelationalExpr.o \
 Lines 99-104    Link Here 
99
  ../source/xpath/StringResult.o \
98
  ../source/xpath/StringResult.o \
100
  ../source/xpath/TextExpr.o \
99
  ../source/xpath/TextExpr.o \
101
  ../source/xpath/UnionExpr.o \
100
  ../source/xpath/UnionExpr.o \
101
  ../source/xpath/UnaryExpr.o \
102
  ../source/xpath/VariableRefExpr.o \
102
  ../source/xpath/VariableRefExpr.o \
103
  ../source/xpath/XPathNames.o \
103
  ../source/xpath/XPathNames.o \
104
  ../source/xpath/XPathProcessor.o \
104
  ../source/xpath/XPathProcessor.o \
(-)makefile.win (-2 / +2 lines)
Line     Link Here 
 Lines 76-87    Link Here 
76
	..\source\xpath\$(OBJDIR)\BooleanResult.obj \
76
	..\source\xpath\$(OBJDIR)\BooleanResult.obj \
77
	..\source\xpath\$(OBJDIR)\ElementExpr.obj \
77
	..\source\xpath\$(OBJDIR)\ElementExpr.obj \
78
	..\source\xpath\$(OBJDIR)\ErrorFunctionCall.obj \
78
	..\source\xpath\$(OBJDIR)\ErrorFunctionCall.obj \
79
	..\source\xpath\$(OBJDIR)\Expr.obj \
79
	..\source\xpath\$(OBJDIR)\ExprLexer.obj \
80
	..\source\xpath\$(OBJDIR)\ExprLexer.obj \
80
	..\source\xpath\$(OBJDIR)\ExprParser.obj \
81
	..\source\xpath\$(OBJDIR)\ExprParser.obj \
81
	..\source\xpath\$(OBJDIR)\ExtensionFunctionCall.obj \
82
	..\source\xpath\$(OBJDIR)\ExtensionFunctionCall.obj \
82
	..\source\xpath\$(OBJDIR)\FilterExpr.obj \
83
	..\source\xpath\$(OBJDIR)\FilterExpr.obj \
83
	..\source\xpath\$(OBJDIR)\FunctionCall.obj \
84
	..\source\xpath\$(OBJDIR)\FunctionCall.obj \
84
	..\source\xpath\$(OBJDIR)\IdentityExpr.obj \
85
	..\source\xpath\$(OBJDIR)\LocationStep.obj \
85
	..\source\xpath\$(OBJDIR)\LocationStep.obj \
86
	..\source\xpath\$(OBJDIR)\MultiplicativeExpr.obj \
86
	..\source\xpath\$(OBJDIR)\MultiplicativeExpr.obj \
87
	..\source\xpath\$(OBJDIR)\NodeSet.obj \
87
	..\source\xpath\$(OBJDIR)\NodeSet.obj \
 Lines 90-96    Link Here 
90
	..\source\xpath\$(OBJDIR)\NumberExpr.obj \
90
	..\source\xpath\$(OBJDIR)\NumberExpr.obj \
91
	..\source\xpath\$(OBJDIR)\NumberFunctionCall.obj \
91
	..\source\xpath\$(OBJDIR)\NumberFunctionCall.obj \
92
	..\source\xpath\$(OBJDIR)\NumberResult.obj \
92
	..\source\xpath\$(OBJDIR)\NumberResult.obj \
93
	..\source\xpath\$(OBJDIR)\ParentExpr.obj \
94
	..\source\xpath\$(OBJDIR)\PathExpr.obj \
93
	..\source\xpath\$(OBJDIR)\PathExpr.obj \
95
	..\source\xpath\$(OBJDIR)\PredicateList.obj \
94
	..\source\xpath\$(OBJDIR)\PredicateList.obj \
96
	..\source\xpath\$(OBJDIR)\RelationalExpr.obj \
95
	..\source\xpath\$(OBJDIR)\RelationalExpr.obj \
 Lines 100-105    Link Here 
100
	..\source\xpath\$(OBJDIR)\StringResult.obj \
99
	..\source\xpath\$(OBJDIR)\StringResult.obj \
101
	..\source\xpath\$(OBJDIR)\TextExpr.obj \
100
	..\source\xpath\$(OBJDIR)\TextExpr.obj \
102
	..\source\xpath\$(OBJDIR)\UnionExpr.obj \
101
	..\source\xpath\$(OBJDIR)\UnionExpr.obj \
102
	..\source\xpath\$(OBJDIR)\UnaryExpr.obj \
103
	..\source\xpath\$(OBJDIR)\VariableRefExpr.obj \
103
	..\source\xpath\$(OBJDIR)\VariableRefExpr.obj \
104
	..\source\xpath\$(OBJDIR)\XPathNames.obj \
104
	..\source\xpath\$(OBJDIR)\XPathNames.obj \
105
	..\source\xpath\$(OBJDIR)\XPathProcessor.obj \
105
	..\source\xpath\$(OBJDIR)\XPathProcessor.obj \
(-)Makefile.in (-2 / +2 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 \
74
  ../xpath/ExprParser.o \
75
  ../xpath/ExprParser.o \
75
  ../xpath/ExtensionFunctionCall.o \
76
  ../xpath/ExtensionFunctionCall.o \
76
  ../xpath/FilterExpr.o \
77
  ../xpath/FilterExpr.o \
77
  ../xpath/FunctionCall.o \
78
  ../xpath/FunctionCall.o \
78
  ../xpath/IdentityExpr.o \
79
  ../xpath/LocationStep.o \
79
  ../xpath/LocationStep.o \
80
  ../xpath/MultiplicativeExpr.o \
80
  ../xpath/MultiplicativeExpr.o \
81
  ../xpath/NodeSet.o \
81
  ../xpath/NodeSet.o \
 Lines 83-89    Link Here 
83
  ../xpath/NumberExpr.o \
83
  ../xpath/NumberExpr.o \
84
  ../xpath/NumberFunctionCall.o \
84
  ../xpath/NumberFunctionCall.o \
85
  ../xpath/NumberResult.o \
85
  ../xpath/NumberResult.o \
86
  ../xpath/ParentExpr.o \
87
  ../xpath/PathExpr.o \
86
  ../xpath/PathExpr.o \
88
  ../xpath/PredicateList.o \
87
  ../xpath/PredicateList.o \
89
  ../xpath/RelationalExpr.o \
88
  ../xpath/RelationalExpr.o \
 Lines 93-98    Link Here 
93
  ../xpath/StringResult.o \
92
  ../xpath/StringResult.o \
94
  ../xpath/TextExpr.o \
93
  ../xpath/TextExpr.o \
95
  ../xpath/UnionExpr.o \
94
  ../xpath/UnionExpr.o \
95
  ../xpath/UnaryExpr.o \
96
  ../xpath/VariableRefExpr.o \
96
  ../xpath/VariableRefExpr.o \
97
  ../xpath/XPathNames.o \
97
  ../xpath/XPathNames.o \
98
  ../xml/XMLUtils.o \
98
  ../xml/XMLUtils.o \
(-)makefile.win (-2 / +2 lines)
Line     Link Here 
 Lines 67-78    Link Here 
67
  ../xpath/$(OBJDIR)/BooleanResult.obj \
67
  ../xpath/$(OBJDIR)/BooleanResult.obj \
68
  ../xpath/$(OBJDIR)/ElementExpr.obj \
68
  ../xpath/$(OBJDIR)/ElementExpr.obj \
69
  ../xpath/$(OBJDIR)/ErrorFunctionCall.obj \
69
  ../xpath/$(OBJDIR)/ErrorFunctionCall.obj \
70
  ../xpath/$(OBJDIR)/Expr.obj \
70
  ../xpath/$(OBJDIR)/ExprLexer.obj \
71
  ../xpath/$(OBJDIR)/ExprLexer.obj \
71
  ../xpath/$(OBJDIR)/ExprParser.obj \
72
  ../xpath/$(OBJDIR)/ExprParser.obj \
72
  ../xpath/$(OBJDIR)/ExtensionFunctionCall.obj \
73
  ../xpath/$(OBJDIR)/ExtensionFunctionCall.obj \
73
  ../xpath/$(OBJDIR)/FilterExpr.obj \
74
  ../xpath/$(OBJDIR)/FilterExpr.obj \
74
  ../xpath/$(OBJDIR)/FunctionCall.obj \
75
  ../xpath/$(OBJDIR)/FunctionCall.obj \
75
  ../xpath/$(OBJDIR)/IdentityExpr.obj \
76
  ../xpath/$(OBJDIR)/LocationStep.obj \
76
  ../xpath/$(OBJDIR)/LocationStep.obj \
77
  ../xpath/$(OBJDIR)/MultiplicativeExpr.obj \
77
  ../xpath/$(OBJDIR)/MultiplicativeExpr.obj \
78
  ../xpath/$(OBJDIR)/NodeSet.obj \
78
  ../xpath/$(OBJDIR)/NodeSet.obj \
 Lines 80-86    Link Here 
80
  ../xpath/$(OBJDIR)/NumberExpr.obj \
80
  ../xpath/$(OBJDIR)/NumberExpr.obj \
81
  ../xpath/$(OBJDIR)/NumberFunctionCall.obj \
81
  ../xpath/$(OBJDIR)/NumberFunctionCall.obj \
82
  ../xpath/$(OBJDIR)/NumberResult.obj \
82
  ../xpath/$(OBJDIR)/NumberResult.obj \
83
  ../xpath/$(OBJDIR)/ParentExpr.obj \
84
  ../xpath/$(OBJDIR)/PathExpr.obj \
83
  ../xpath/$(OBJDIR)/PathExpr.obj \
85
  ../xpath/$(OBJDIR)/PredicateList.obj \
84
  ../xpath/$(OBJDIR)/PredicateList.obj \
86
  ../xpath/$(OBJDIR)/RelationalExpr.obj \
85
  ../xpath/$(OBJDIR)/RelationalExpr.obj \
 Lines 90-95    Link Here 
90
  ../xpath/$(OBJDIR)/StringResult.obj \
89
  ../xpath/$(OBJDIR)/StringResult.obj \
91
  ../xpath/$(OBJDIR)/TextExpr.obj \
90
  ../xpath/$(OBJDIR)/TextExpr.obj \
92
  ../xpath/$(OBJDIR)/UnionExpr.obj \
91
  ../xpath/$(OBJDIR)/UnionExpr.obj \
92
  ../xpath/$(OBJDIR)/UnaryExpr.obj \
93
  ../xpath/$(OBJDIR)/VariableRefExpr.obj \
93
  ../xpath/$(OBJDIR)/VariableRefExpr.obj \
94
  ../xpath/$(OBJDIR)/XPathNames.obj \
94
  ../xpath/$(OBJDIR)/XPathNames.obj \
95
  ../xml/$(OBJDIR)/XMLUtils.obj \
95
  ../xml/$(OBJDIR)/XMLUtils.obj \
(-)BasicNodeExpr.cpp (-9 / +25 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 74-90    Link Here 
74
    return nodeSet;
85
    return nodeSet;
75
} //-- evaluate
86
} //-- evaluate
76
87
77
  //-----------------------------/
78
 //- Methods from NodeExpr.cpp -/
79
//-----------------------------/
80
81
/**
88
/**
82
 * Returns the default priority of this Pattern based on the given Node,
89
 * Returns the default priority of this Expr based on the given Node,
83
 * context Node, and ContextState.
90
 * context Node, and ContextState.
84
 * If this pattern does not match the given Node under the current context Node and
85
 * ContextState then Negative Infinity is returned.
86
**/
91
**/
87
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
92
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
93
    if (nodeNameSet) return 0;
88
    return -0.5;
94
    return -0.5;
89
} //-- getDefaultPriority
95
} //-- getDefaultPriority
90
96
 Lines 106-113    Link Here 
106
        case NodeExpr::COMMENT_EXPR:
112
        case NodeExpr::COMMENT_EXPR:
107
            return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
113
            return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
108
        case NodeExpr::PI_EXPR :
114
        case NodeExpr::PI_EXPR :
109
            return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE);
115
            return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE &&
116
                            !nodeNameSet || nodeName.isEqual(node->getNodeName()));
110
        default: //-- node()
117
        default: //-- node()
118
            //XXX WhiteSpace: filter whitespace nodes properly
119
            return (MBool) !(node->getNodeType() == Node::TEXT_NODE &&
120
                             node->getParentNode() == node->getOwnerDocument());
111
            break;
121
            break;
112
    }
122
    }
113
    return MB_TRUE;
123
    return MB_TRUE;
 Lines 129-135    Link Here 
129
            dest.append("comment()");
139
            dest.append("comment()");
130
            break;
140
            break;
131
        case NodeExpr::PI_EXPR :
141
        case NodeExpr::PI_EXPR :
132
            dest.append("processing-instruction()");
142
            dest.append("processing-instruction(");
143
            if (nodeNameSet) {
144
                dest.append('\'');
145
                dest.append(nodeName);
146
                dest.append('\'');
147
            }
148
            dest.append(')');
133
            break;
149
            break;
134
        default: //-- node()
150
        default: //-- node()
135
            dest.append("node()");
151
            dest.append("node()");
(-)Expr.h (-278 / +178 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.10 2001/04/08 14:33:45 peterv%netscape.com Exp $
31
 * $Id: Expr.h,v 1.10 2001/04/08 14:33:45 peterv%netscape.com Exp $
29
 */
32
 */
 Lines 52-57    Link Here 
52
//necessary prototypes
55
//necessary prototypes
53
class FunctionCall;
56
class FunctionCall;
54
57
58
typedef class Expr Pattern;
59
typedef class Expr PatternExpr;
60
61
55
/**
62
/**
56
 * The expression context and state class used when evaluating XPath Expressions.
63
 * The expression context and state class used when evaluating XPath Expressions.
57
**/
64
**/
 Lines 115-121    Link Here 
115
    /**
122
    /**
116
     * Virtual destructor, important for subclasses
123
     * Virtual destructor, important for subclasses
117
    **/
124
    **/
118
    virtual ~Expr() {};
125
    virtual ~Expr();
119
126
120
    /**
127
    /**
121
     * Evaluates this Expr based on the given context node and processor state
128
     * Evaluates this Expr based on the given context node and processor state
 Lines 127-132    Link Here 
127
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
134
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
128
135
129
    /**
136
    /**
137
     * Determines whether this Expr matches the given node within
138
     * the given context
139
    **/
140
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
141
142
    /**
143
     * Returns the default priority of this Expr based on the given Node,
144
     * context Node, and ContextState.
145
    **/
146
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
147
148
    /**
130
     * Returns the String representation of this Expr.
149
     * Returns the String representation of this Expr.
131
     * @param dest the String to use when creating the String
150
     * @param dest the String to use when creating the String
132
     * representation. The String representation will be appended to
151
     * representation. The String representation will be appended to
 Lines 138-144    Link Here 
138
157
139
}; //-- Expr
158
}; //-- Expr
140
159
141
142
/**
160
/**
143
 * This class represents a FunctionCall as defined by the XPath 1.0
161
 * This class represents a FunctionCall as defined by the XPath 1.0
144
 * Recommendation.
162
 * Recommendation.
 Lines 168-173    Link Here 
168
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
186
    virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
169
187
170
    /**
188
    /**
189
     * Determines whether this FunctionCall matches the given node within
190
     * the given context
191
    **/
192
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
193
194
    /**
195
     * Returns the default priority of this FunctionCall based on the given Node,
196
     * context Node, and ContextState.
197
    **/
198
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
199
200
    /**
171
     * Returns the name of this FunctionCall
201
     * Returns the name of this FunctionCall
172
     * @return the name of this FunctionCall
202
     * @return the name of this FunctionCall
173
    **/
203
    **/
 Lines 185-196    Link Here 
185
    **/
215
    **/
186
    void setName(const String& name);
216
    void setName(const String& name);
187
    /**
217
    /**
188
     * Returns the String representation of this Pattern.
218
     * Returns the String representation of this Expr.
189
     * @param dest the String to use when creating the String
219
     * @param dest the String to use when creating the String
190
     * representation. The String representation will be appended to
220
     * representation. The String representation will be appended to
191
     * any data in the destination String, to allow cascading calls to
221
     * any data in the destination String, to allow cascading calls to
192
     * other #toString() methods for Expressions.
222
     * other #toString() methods for Expressions.
193
     * @return the String representation of this Pattern.
223
     * @return the String representation of this Expr.
194
    **/
224
    **/
195
    virtual void toString(String& dest);
225
    virtual void toString(String& dest);
196
226
 Lines 221-317    Link Here 
221
    String name;
251
    String name;
222
}; //-- FunctionCall
252
}; //-- FunctionCall
223
253
224
/**
225
 * A base Pattern class
226
**/
227
class Pattern {
228
229
public:
230
231
    /**
232
     * Virtual destructor, important for subclasses
233
    **/
234
    virtual ~Pattern() {};
235
236
    /**
237
     * Returns the default priority of this Pattern based on the given Node,
238
     * context Node, and ContextState.
239
     * If this pattern does not match the given Node under the current context Node and
240
     * ContextState then Negative Infinity is returned.
241
    **/
242
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
243
244
    /**
245
     * Determines whether this Pattern matches the given node within
246
     * the given context
247
    **/
248
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
249
250
251
    /**
252
     * Returns the String representation of this Pattern.
253
     * @param dest the String to use when creating the String
254
     * representation. The String representation will be appended to
255
     * any data in the destination String, to allow cascading calls to
256
     * other #toString() methods for Expressions.
257
     * @return the String representation of this Pattern.
258
    **/
259
    virtual void toString(String& dest) = 0;
260
261
}; //-- Pattern
262
254
263
264
/**
255
/**
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
256
 * Represents an AttributeValueTemplate
316
**/
257
**/
317
class AttributeValueTemplate: public Expr {
258
class AttributeValueTemplate: public Expr {
 Lines 355-361    Link Here 
355
 * This class represents a NodeTestExpr as defined by the XSL
296
 * This class represents a NodeTestExpr as defined by the XSL
356
 * Working Draft
297
 * Working Draft
357
**/
298
**/
358
class NodeExpr : public PatternExpr {
299
class NodeExpr : public Expr {
359
300
360
public:
301
public:
361
302
 Lines 379-392    Link Here 
379
    //------------------/
320
    //------------------/
380
321
381
    /**
322
    /**
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
323
     * Returns the type of this NodeExpr
391
     * @return the type of this NodeExpr
324
     * @return the type of this NodeExpr
392
    **/
325
    **/
 Lines 399-410    Link Here 
399
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
332
    virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
400
333
401
    /**
334
    /**
402
     * Returns the String representation of this Pattern.
335
     * Returns the default priority of this Expr based on the given Node,
336
     * context Node, and ContextState.
337
    **/
338
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
339
340
    /**
341
     * Returns the String representation of this Expr.
403
     * @param dest the String to use when creating the String
342
     * @param dest the String to use when creating the String
404
     * representation. The String representation will be appended to
343
     * representation. The String representation will be appended to
405
     * any data in the destination String, to allow cascading calls to
344
     * any data in the destination String, to allow cascading calls to
406
     * other #toString() methods for Expressions.
345
     * other #toString() methods for Expressions.
407
     * @return the String representation of this Pattern.
346
     * @return the String representation of this Expr.
408
    **/
347
    **/
409
    virtual void toString(String& dest) = 0;
348
    virtual void toString(String& dest) = 0;
410
349
 Lines 445-458    Link Here 
445
  //-----------------------------------/
384
  //-----------------------------------/
446
385
447
    /**
386
    /**
448
     * Returns the default priority of this Pattern based on the given Node,
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
387
     * Evaluates this Expr based on the given context node and processor state
457
     * @param context the context node for evaluation of this Expr
388
     * @param context the context node for evaluation of this Expr
458
     * @param ps the ContextState containing the stack information needed
389
     * @param ps the ContextState containing the stack information needed
 Lines 474-479    Link Here 
474
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
405
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
475
406
476
    /**
407
    /**
408
     * Returns the default priority of this Expr based on the given Node,
409
     * context Node, and ContextState.
410
    **/
411
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
412
413
    /**
477
     * Returns the String representation of this NodeExpr.
414
     * Returns the String representation of this NodeExpr.
478
     * @param dest the String to use when creating the String
415
     * @param dest the String to use when creating the String
479
     * representation. The String representation will be appended to
416
     * representation. The String representation will be appended to
 Lines 521-540    Link Here 
521
     * Destroys this BasicNodeExpr
458
     * Destroys this BasicNodeExpr
522
    **/
459
    **/
523
    virtual ~BasicNodeExpr();
460
    virtual ~BasicNodeExpr();
461
    
462
    /**
463
     * Sets the name of the node to match. Only availible for pi nodes
464
    **/
465
    void setNodeName(const String& name);
524
466
525
    //-----------------------------------/
467
    //-----------------------------------/
526
   //- Method signatures from NodeExpr -/
468
   //- Method signatures from NodeExpr -/
527
  //-----------------------------------/
469
  //-----------------------------------/
528
470
529
    /**
471
    /**
530
     * Returns the default priority of this Pattern based on the given Node,
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
    **/
535
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
536
537
    /**
538
     * Evaluates this Expr based on the given context node and processor state
472
     * Evaluates this Expr based on the given context node and processor state
539
     * @param context the context node for evaluation of this Expr
473
     * @param context the context node for evaluation of this Expr
540
     * @param ps the ContextState containing the stack information needed
474
     * @param ps the ContextState containing the stack information needed
 Lines 556-561    Link Here 
556
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
490
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
557
491
558
    /**
492
    /**
493
     * Returns the default priority of this Expr based on the given Node,
494
     * context Node, and ContextState.
495
    **/
496
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
497
498
    /**
559
     * Returns the String representation of this NodeExpr.
499
     * Returns the String representation of this NodeExpr.
560
     * @param dest the String to use when creating the String
500
     * @param dest the String to use when creating the String
561
     * representation. The String representation will be appended to
501
     * representation. The String representation will be appended to
 Lines 567-572    Link Here 
567
507
568
private:
508
private:
569
    NodeExprType type;
509
    NodeExprType type;
510
    String nodeName;
511
    MBool nodeNameSet;
570
}; //-- BasicNodeExpr
512
}; //-- BasicNodeExpr
571
513
572
/**
514
/**
 Lines 611-620    Link Here 
611
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
553
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
612
554
613
    /**
555
    /**
614
     * Returns the default priority of this Pattern based on the given Node,
556
     * Returns the default priority of this Expr based on the given Node,
615
     * context Node, and ContextState.
557
     * 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
    **/
558
    **/
619
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
559
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
620
560
 Lines 655-727    Link Here 
655
}; //-- ElementExpr
595
}; //-- ElementExpr
656
596
657
/**
597
/**
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
598
 * This class represents a TextExpr, which only matches any text node
726
**/
599
**/
727
class TextExpr : public NodeExpr {
600
class TextExpr : public NodeExpr {
 Lines 742-755    Link Here 
742
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
615
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
743
616
744
    /**
617
    /**
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
618
     * Returns the type of this NodeExpr
754
     * @return the type of this NodeExpr
619
     * @return the type of this NodeExpr
755
    **/
620
    **/
 Lines 761-766    Link Here 
761
    **/
626
    **/
762
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
627
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
763
628
629
    /**
630
     * Returns the default priority of this Expr based on the given Node,
631
     * context Node, and ContextState.
632
    **/
633
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
764
634
765
    /**
635
    /**
766
     * Returns the String representation of this NodeExpr.
636
     * Returns the String representation of this NodeExpr.
 Lines 827-833    Link Here 
827
    List predicates;
697
    List predicates;
828
}; //-- PredicateList
698
}; //-- PredicateList
829
699
830
class LocationStep : public PredicateList, public PatternExpr {
700
class LocationStep : public PredicateList, public Expr {
831
701
832
public:
702
public:
833
703
 Lines 887-895    Link Here 
887
    **/
757
    **/
888
    void setNodeExpr(NodeExpr* nodeExpr);
758
    void setNodeExpr(NodeExpr* nodeExpr);
889
759
890
      //------------------------------------/
760
      //-----------------------------/
891
     //- Virtual methods from PatternExpr -/
761
     //- Virtual methods from Expr -/
892
    //------------------------------------/
762
    //-----------------------------/
893
763
894
    /**
764
    /**
895
     * Evaluates this Expr based on the given context node and processor state
765
     * Evaluates this Expr based on the given context node and processor state
 Lines 901-940    Link Here 
901
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
771
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
902
772
903
    /**
773
    /**
904
     * Returns the default priority of this Pattern based on the given Node,
774
     * Determines whether this Expr matches the given node within
905
     * context Node, and ContextState.
775
     * the given context
906
     * If this pattern does not match the given Node under the current context Node and
907
     * ContextState then Negative Infinity is returned.
908
    **/
776
    **/
909
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
777
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
910
778
911
    /**
779
    /**
912
     * Determines whether this PatternExpr matches the given node within
780
     * Returns the default priority of this Expr based on the given Node,
913
     * the given context
781
     * context Node, and ContextState.
914
    **/
782
    **/
915
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
783
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
916
784
917
    /**
785
    /**
918
     * Returns the String representation of this PatternExpr.
786
     * Returns the String representation of this Expr.
919
     * @param dest the String to use when creating the String
787
     * @param dest the String to use when creating the String
920
     * representation. The String representation will be appended to
788
     * representation. The String representation will be appended to
921
     * any data in the destination String, to allow cascading calls to
789
     * any data in the destination String, to allow cascading calls to
922
     * other #toString() methods for Expressions.
790
     * other #toString() methods for Expressions.
923
     * @return the String representation of this PatternExpr.
791
     * @return the String representation of this Expr.
924
    **/
792
    **/
925
    virtual void toString(String& dest);
793
    virtual void toString(String& dest);
926
794
927
private:
795
private:
928
796
929
  NodeExpr* nodeExpr;
797
    NodeExpr* nodeExpr;
930
  short     axisIdentifier;
798
    short     axisIdentifier;
931
799
932
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
800
    void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
801
    void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
933
802
934
}; //-- LocationStep
803
}; //-- LocationStep
935
804
936
805
937
class FilterExpr : public PredicateList, public PatternExpr {
806
class FilterExpr : public PredicateList, public Expr {
938
807
939
public:
808
public:
940
809
 Lines 961-969    Link Here 
961
    **/
830
    **/
962
    void setExpr(Expr* expr);
831
    void setExpr(Expr* expr);
963
832
964
      //------------------------------------/
833
      //-----------------------------/
965
     //- Virtual methods from PatternExpr -/
834
     //- Virtual methods from Expr -/
966
    //------------------------------------/
835
    //-----------------------------/
967
836
968
    /**
837
    /**
969
     * Evaluates this Expr based on the given context node and processor state
838
     * Evaluates this Expr based on the given context node and processor state
 Lines 975-1006    Link Here 
975
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
844
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
976
845
977
    /**
846
    /**
978
     * Returns the default priority of this Pattern based on the given Node,
847
     * Determines whether this Expr matches the given node within
979
     * context Node, and ContextState.
848
     * the given context
980
     * If this pattern does not match the given Node under the current context Node and
981
     * ContextState then Negative Infinity is returned.
982
    **/
849
    **/
983
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
850
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
984
851
985
    /**
852
    /**
986
     * Determines whether this PatternExpr matches the given node within
853
     * Returns the default priority of this Expr based on the given Node,
987
     * the given context
854
     * context Node, and ContextState.
988
    **/
855
    **/
989
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
856
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
990
857
991
    /**
858
    /**
992
     * Returns the String representation of this PatternExpr.
859
     * Returns the String representation of this Expr.
993
     * @param dest the String to use when creating the String
860
     * @param dest the String to use when creating the String
994
     * representation. The String representation will be appended to
861
     * representation. The String representation will be appended to
995
     * any data in the destination String, to allow cascading calls to
862
     * any data in the destination String, to allow cascading calls to
996
     * other #toString() methods for Expressions.
863
     * other #toString() methods for Expressions.
997
     * @return the String representation of this PatternExpr.
864
     * @return the String representation of this Expr.
998
    **/
865
    **/
999
    virtual void toString(String& dest);
866
    virtual void toString(String& dest);
1000
867
1001
private:
868
private:
1002
869
1003
  Expr*     expr;
870
    Expr* expr;
1004
871
1005
}; //-- FilterExpr
872
}; //-- FilterExpr
1006
873
 Lines 1131-1136    Link Here 
1131
}; //-- AdditiveExpr
998
}; //-- AdditiveExpr
1132
999
1133
/**
1000
/**
1001
 * Represents an UnaryExpr.
1002
**/
1003
class UnaryExpr : public Expr {
1004
1005
public:
1006
1007
     UnaryExpr();
1008
     UnaryExpr(Expr* expr);
1009
     ~UnaryExpr();
1010
1011
    /**
1012
     * Sets the expression to negate
1013
    **/
1014
    void setExpr(Expr* expr);
1015
1016
    /**
1017
     * Evaluates this Expr based on the given context node and processor state
1018
     * @param context the context node for evaluation of this Expr
1019
     * @param ps the ContextState containing the stack information needed
1020
     * for evaluation
1021
     * @return the result of the evaluation
1022
    **/
1023
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1024
1025
    /**
1026
     * Returns the String representation of this Expr.
1027
     * @param dest the String to use when creating the String
1028
     * representation. The String representation will be appended to
1029
     * any data in the destination String, to allow cascading calls to
1030
     * other #toString() methods for Expressions.
1031
     * @return the String representation of this Expr.
1032
    **/
1033
    virtual void toString(String& str);
1034
1035
private:
1036
    Expr* expr;
1037
}; //-- AdditiveExpr
1038
1039
/**
1134
 * Represents a BooleanExpr, a binary expression that
1040
 * Represents a BooleanExpr, a binary expression that
1135
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
1041
 * performs a boolean operation between it's lvalue and rvalue:<BR/>
1136
**/
1042
**/
 Lines 1344-1350    Link Here 
1344
/**
1250
/**
1345
 *  Represents a PathExpr
1251
 *  Represents a PathExpr
1346
**/
1252
**/
1347
class PathExpr : public PatternExpr {
1253
class PathExpr : public Expr {
1348
1254
1349
public:
1255
public:
1350
1256
 Lines 1359-1386    Link Here 
1359
    PathExpr();
1265
    PathExpr();
1360
1266
1361
    /**
1267
    /**
1362
     * Destructor, will delete all Pattern Expressions
1268
     * Destructor, will delete all Expressions
1363
    **/
1269
    **/
1364
    virtual ~PathExpr();
1270
    virtual ~PathExpr();
1365
1271
1366
    /**
1272
    /**
1367
     * Adds the PatternExpr to this PathExpr
1273
     * Adds the Expr to this PathExpr
1368
     * @param expr the Expr to add to this PathExpr
1274
     * @param expr the Expr to add to this PathExpr
1369
     * @param index the index at which to add the given Expr
1275
     * @param index the index at which to add the given Expr
1370
    **/
1276
    **/
1371
    void addPatternExpr(int index, PatternExpr* expr, short ancestryOp);
1277
    void addExpr(int index, Expr* expr, short ancestryOp);
1372
1278
1373
    /**
1279
    /**
1374
     * Adds the PatternExpr to this PathExpr
1280
     * Adds the Expr to this PathExpr
1375
     * @param expr the Expr to add to this PathExpr
1281
     * @param expr the Expr to add to this PathExpr
1376
    **/
1282
    **/
1377
    void addPatternExpr(PatternExpr* expr, short ancestryOp);
1283
    void addExpr(Expr* expr, short ancestryOp);
1378
1284
1379
    virtual MBool isAbsolute();
1285
    virtual MBool isAbsolute();
1380
1286
1381
      //------------------------------------/
1287
      //-----------------------------/
1382
     //- Virtual methods from PatternExpr -/
1288
     //- Virtual methods from Expr -/
1383
    //------------------------------------/
1289
    //-----------------------------/
1384
1290
1385
    /**
1291
    /**
1386
     * Evaluates this Expr based on the given context node and processor state
1292
     * Evaluates this Expr based on the given context node and processor state
 Lines 1392-1424    Link Here 
1392
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1298
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1393
1299
1394
    /**
1300
    /**
1395
     * Returns the default priority of this Pattern based on the given Node,
1301
     * Determines whether this Expr matches the given node within
1396
     * context Node, and ContextState.
1302
     * the given context
1397
     * If this pattern does not match the given Node under the current context Node and
1398
     * ContextState then Negative Infinity is returned.
1399
    **/
1303
    **/
1400
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1304
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1401
1305
1402
    /**
1306
    /**
1403
     * Determines whether this PatternExpr matches the given node within
1307
     * Returns the default priority of this Expr based on the given Node,
1404
     * the given context
1308
     * context Node, and ContextState.
1405
    **/
1309
    **/
1406
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1310
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1407
1311
1408
    /**
1312
    /**
1409
     * Returns the String representation of this PatternExpr.
1313
     * Returns the String representation of this Expr.
1410
     * @param dest the String to use when creating the String
1314
     * @param dest the String to use when creating the String
1411
     * representation. The String representation will be appended to
1315
     * representation. The String representation will be appended to
1412
     * any data in the destination String, to allow cascading calls to
1316
     * any data in the destination String, to allow cascading calls to
1413
     * other #toString() methods for Expressions.
1317
     * other #toString() methods for Expressions.
1414
     * @return the String representation of this PatternExpr.
1318
     * @return the String representation of this Expr.
1415
    **/
1319
    **/
1416
    virtual void toString(String& dest);
1320
    virtual void toString(String& dest);
1417
1321
1418
private:
1322
private:
1419
1323
1420
    struct PathExprItem {
1324
    struct PathExprItem {
1421
        PatternExpr* pExpr;
1325
        Expr* expr;
1422
        short ancestryOp;
1326
        short ancestryOp;
1423
    };
1327
    };
1424
1328
 Lines 1426-1438    Link Here 
1426
1330
1427
   /**
1331
   /**
1428
    * Selects from the descendants of the context node
1332
    * Selects from the descendants of the context node
1429
    * all nodes that match the PatternExpr
1333
    * all nodes that match the Expr
1430
    * -- this will be moving to a Utility class
1334
    * -- this will be moving to a Utility class
1431
   **/
1335
   **/
1432
   void fromDescendants(PatternExpr* pExpr,
1336
   void evalDescendants(Expr* expr,
1433
                        Node* context,
1337
                        Node* context,
1434
                        ContextState* cs,
1338
                        ContextState* cs,
1435
                        NodeSet* nodes);
1339
                        NodeSet* resNodes);
1436
1340
1437
}; //-- PathExpr
1341
}; //-- PathExpr
1438
1342
 Lines 1459-1484    Link Here 
1459
    virtual MBool isAbsolute();
1363
    virtual MBool isAbsolute();
1460
1364
1461
    /**
1365
    /**
1462
     * Returns the default priority of this Pattern based on the given Node,
1463
     * context Node, and ContextState.
1464
     * If this pattern does not match the given Node under the current context Node and
1465
     * ContextState then Negative Infinity is returned.
1466
    **/
1467
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1468
1469
    /**
1470
     * Determines whether this NodeExpr matches the given node within
1366
     * Determines whether this NodeExpr matches the given node within
1471
     * the given context
1367
     * the given context
1472
    **/
1368
    **/
1473
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1369
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1474
1370
1371
    /**
1372
     * Returns the default priority of this Expr based on the given Node,
1373
     * context Node, and ContextState.
1374
    **/
1375
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1376
1475
    /**
1377
    /**
1476
     * Returns the String representation of this PatternExpr.
1378
     * Returns the String representation of this Expr.
1477
     * @param dest the String to use when creating the String
1379
     * @param dest the String to use when creating the String
1478
     * representation. The String representation will be appended to
1380
     * representation. The String representation will be appended to
1479
     * any data in the destination String, to allow cascading calls to
1381
     * any data in the destination String, to allow cascading calls to
1480
     * other #toString() methods for Expressions.
1382
     * other #toString() methods for Expressions.
1481
     * @return the String representation of this PatternExpr.
1383
     * @return the String representation of this Expr.
1482
    **/
1384
    **/
1483
    virtual void toString(String& dest);
1385
    virtual void toString(String& dest);
1484
1386
 Lines 1488-1494    Link Here 
1488
/**
1390
/**
1489
 *  Represents a UnionExpr
1391
 *  Represents a UnionExpr
1490
**/
1392
**/
1491
class UnionExpr : public PatternExpr {
1393
class UnionExpr : public Expr {
1492
1394
1493
public:
1395
public:
1494
1396
 Lines 1506-1522    Link Here 
1506
     * Adds the PathExpr to this UnionExpr
1408
     * Adds the PathExpr to this UnionExpr
1507
     * @param expr the Expr to add to this UnionExpr
1409
     * @param expr the Expr to add to this UnionExpr
1508
    **/
1410
    **/
1509
    void addPathExpr(PathExpr* expr);
1411
    void addExpr(Expr* expr);
1510
1412
1511
    /**
1413
    /**
1512
     * Adds the PathExpr to this UnionExpr at the specified index
1414
     * Adds the PathExpr to this UnionExpr at the specified index
1513
     * @param expr the Expr to add to this UnionExpr
1415
     * @param expr the Expr to add to this UnionExpr
1514
    **/
1416
    **/
1515
    void addPathExpr(int index, PathExpr* expr);
1417
    void addExpr(int index, Expr* expr);
1516
1418
1517
      //------------------------------------/
1419
      //-----------------------------/
1518
     //- Virtual methods from PatternExpr -/
1420
     //- Virtual methods from Expr -/
1519
    //------------------------------------/
1421
    //-----------------------------/
1520
1422
1521
    /**
1423
    /**
1522
     * Evaluates this Expr based on the given context node and processor state
1424
     * Evaluates this Expr based on the given context node and processor state
 Lines 1528-1553    Link Here 
1528
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1430
    virtual ExprResult* evaluate(Node* context, ContextState* cs);
1529
1431
1530
    /**
1432
    /**
1531
     * Returns the default priority of this Pattern based on the given Node,
1433
     * Determines whether this Expr matches the given node within
1532
     * context Node, and ContextState.
1434
     * the given context
1533
     * If this pattern does not match the given Node under the current context Node and
1534
     * ContextState then Negative Infinity is returned.
1535
    **/
1435
    **/
1536
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1436
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1537
1437
1538
    /**
1438
    /**
1539
     * Determines whether this PatternExpr matches the given node within
1439
     * Returns the default priority of this Expr based on the given Node,
1540
     * the given context
1440
     * context Node, and ContextState.
1541
    **/
1441
    **/
1542
    virtual MBool matches(Node* node, Node* context, ContextState* cs);
1442
    virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
1543
1443
1544
    /**
1444
    /**
1545
     * Returns the String representation of this PatternExpr.
1445
     * Returns the String representation of this Expr.
1546
     * @param dest the String to use when creating the String
1446
     * @param dest the String to use when creating the String
1547
     * representation. The String representation will be appended to
1447
     * representation. The String representation will be appended to
1548
     * any data in the destination String, to allow cascading calls to
1448
     * any data in the destination String, to allow cascading calls to
1549
     * other #toString() methods for Expressions.
1449
     * other #toString() methods for Expressions.
1550
     * @return the String representation of this PatternExpr.
1450
     * @return the String representation of this Expr.
1551
    **/
1451
    **/
1552
    virtual void toString(String& dest);
1452
    virtual void toString(String& dest);
1553
1453
(-)ExprLexer.cpp (-541 / +351 lines)
Line     Link Here 
 Lines 1-4    Link Here 
1
/*
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 
2
 * The contents of this file are subject to the Mozilla Public
2
 * The contents of this file are subject to the Mozilla Public
3
 * License Version 1.1 (the "License"); you may not use this file
3
 * License Version 1.1 (the "License"); you may not use this file
4
 * except in compliance with the License. You may obtain a copy of
4
 * except in compliance with the License. You may obtain a copy of
 Lines 29-34    Link Here 
29
 *   -- Fixed bug in parse method so that we make sure we check for
29
 *   -- Fixed bug in parse method so that we make sure we check for
30
 *      axis identifier wild cards, such as ancestor::*
30
 *      axis identifier wild cards, such as ancestor::*
31
 *
31
 *
32
 * Axel Hecht <axel@pike.org>
33
 *   -- big beating, general overhaul
34
 *
32
 * $Id: ExprLexer.cpp,v 1.12 2001/04/03 12:25:03 peterv%netscape.com Exp $
35
 * $Id: ExprLexer.cpp,v 1.12 2001/04/03 12:25:03 peterv%netscape.com Exp $
33
 */
36
 */
34
37
 Lines 40-55    Link Here 
40
43
41
#include "ExprLexer.h"
44
#include "ExprLexer.h"
42
45
43
  //---------------------------/
44
 //- Implementation of Token -/
45
//---------------------------/
46
//---------------------------/
47
//- Implementation of Token -/
48
//---------------------------/
46
49
47
50
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
  this->type =0;
53
} //-- Token;
56
} //-- Token;
54
57
55
/**
58
/**
 Lines 57-63    Link Here 
57
 * @param type, the type of Token being represented
60
 * @param type, the type of Token being represented
58
**/
61
**/
59
Token::Token(short type) {
62
Token::Token(short type) {
60
    this->type = type;
63
  this->type = type;
61
} //-- Token;
64
} //-- Token;
62
65
63
/**
66
/**
 Lines 66-99    Link Here 
66
 * @param type, the type of Token being represented
69
 * @param type, the type of Token being represented
67
**/
70
**/
68
Token::Token(const String& value, short type) {
71
Token::Token(const String& value, short type) {
69
    this->type = type;
72
  this->type = type;
70
    //-- make copy of value String
73
  //-- make copy of value String
71
    this->value = value;
74
  this->value = value;
72
} //-- Token
75
} //-- Token
73
76
74
Token::Token(UNICODE_CHAR uniChar, short type) {
77
Token::Token(UNICODE_CHAR uniChar, short type) {
75
    this->type = type;
78
  this->type = type;
76
    this->value.append(uniChar);
79
  this->value.append(uniChar);
77
} //-- Token
80
} //-- Token
78
81
79
/**
82
/**
80
 * Copy Constructor
83
 * Copy Constructor
81
**/
84
**/
82
Token::Token(const Token& token) {
85
Token::Token(const Token& token) {
83
    this->type = token.type;
86
  this->type = token.type;
84
    this->value = token.value;
87
  this->value = token.value;
85
} //-- Token
88
} //-- Token
86
89
87
/**
90
/**
88
 * Destructor for Token
91
 * Destructor for Token
89
**/
92
**/
90
Token::~Token() {
93
Token::~Token() {
91
    //-- currently nothing is needed
94
  //-- currently nothing is needed
92
} //-- ~Token
95
} //-- ~Token
93
96
94
97
95
  //--------------------------------/
98
//--------------------------------/
96
 //- Implementation of ExprLexer -/
99
//- Implementation of ExprLexer -/
97
//-------------------------------/
100
//-------------------------------/
98
101
99
/*
102
/*
 Lines 110-115    Link Here 
110
const String ExprLexer::OR      = "or";
113
const String ExprLexer::OR      = "or";
111
114
112
//-- multiplicative operators
115
//-- multiplicative operators
116
const String ExprLexer::MULTIPLY= "*";
113
const String ExprLexer::MODULUS = "mod";
117
const String ExprLexer::MODULUS = "mod";
114
const String ExprLexer::DIVIDE  = "div";
118
const String ExprLexer::DIVIDE  = "div";
115
119
 Lines 119-725    Link Here 
119
**/
123
**/
120
const Token ExprLexer::TOKENS[] = {
124
const Token ExprLexer::TOKENS[] = {
121
125
122
    //-- Nodetype tokens
126
  //-- Nodetype tokens
123
    Token(ExprLexer::COMMENT,       Token::COMMENT),
127
  Token(ExprLexer::COMMENT,       Token::COMMENT),
124
    Token(ExprLexer::NODE,          Token::NODE),
128
  Token(ExprLexer::NODE,          Token::NODE),
125
    Token(ExprLexer::PI,            Token::PI),
129
  Token(ExprLexer::PI,            Token::PI),
126
    Token(ExprLexer::TEXT,          Token::TEXT),
130
  Token(ExprLexer::TEXT,          Token::TEXT),
127
    //-- boolean operators
131
  //-- boolean operators
128
    Token(ExprLexer::AND,           Token::AND_OP),
132
  Token(ExprLexer::AND,           Token::AND_OP),
129
    Token(ExprLexer::OR,            Token::OR_OP),
133
  Token(ExprLexer::OR,            Token::OR_OP),
130
134
131
    //-- multiplicative operators
135
  //-- multiplicative operators
132
    Token(ExprLexer::MODULUS,       Token::MODULUS_OP),
136
  Token(ExprLexer::MULTIPLY,      Token::MULTIPLY_OP),
133
    Token(ExprLexer::DIVIDE,        Token::DIVIDE_OP)
137
  Token(ExprLexer::MODULUS,       Token::MODULUS_OP),
138
  Token(ExprLexer::DIVIDE,        Token::DIVIDE_OP)
134
};
139
};
140
141
const short ExprLexer::NUMBER_OF_TOKENS  = 9;
135
142
136
const short ExprLexer::NUMBER_OF_TOKENS  = 8;
143
/**
144
 * The set of Lexer error messages
145
 **/
146
const String ExprLexer::error_message[] = {
147
  "VariableReference expected",
148
  "Operator expected",
149
  "Literal is not closed",
150
  ": not expected",
151
  "! not expected, use != or not()"
152
};
137
153
138
  //---------------/
139
 //- Contructors -/
140
//---------------/
154
//---------------/
155
//- Contructors -/
156
//---------------/
141
157
142
/**
158
/**
143
 * Creates a new ExprLexer using the given String
159
 * Creates a new ExprLexer using the given String
144
**/
160
**/
145
ExprLexer::ExprLexer(const String& pattern) {
161
ExprLexer::ExprLexer(const String& pattern) {
146
162
147
    firstItem    = 0;
163
  firstItem    = 0;
148
    lastItem     = 0;
164
  lastItem     = 0;
149
    tokenCount   = 0;
165
  tokenCount   = 0;
150
    prevToken    = 0;
166
  prevToken    = 0;
151
    parse(pattern);
167
  endToken.type = Token::END;
152
    currentItem = firstItem;
168
  parse(pattern);
169
  currentItem = firstItem;
153
} //-- ExprLexer
170
} //-- ExprLexer
154
171
155
/**
172
/**
156
 * Destroys this instance of an ExprLexer
173
 * Destroys this instance of an ExprLexer
157
**/
174
**/
158
ExprLexer::~ExprLexer() {
175
ExprLexer::~ExprLexer() {
159
   //-- delete tokens
176
  //-- delete tokens
160
177
161
   //cout << "~ExprLexer() - start"<<endl;
178
  currentItem = firstItem;
162
   currentItem = firstItem;
179
  while ( currentItem ) {
163
   while ( currentItem ) {
180
    TokenListItem* temp = currentItem->next;
164
       TokenListItem* temp = currentItem->next;
181
    delete currentItem->token;
165
       //cout << "deleting token: " << currentItem->token->value << endl;
182
    delete currentItem;
166
       delete currentItem->token;
183
    currentItem = temp;
167
       delete currentItem;
184
  }
168
       currentItem = temp;
169
   }
170
   //cout << "~ExprLexer() - done"<<endl;
171
} //-- ~ExprLexer
185
} //-- ~ExprLexer
172
186
173
187
174
int ExprLexer::countAllTokens() {
188
int ExprLexer::countAllTokens() {
175
    return tokenCount;
189
  return tokenCount;
176
} //-- countAllTokens
190
} //-- countAllTokens
177
191
178
int ExprLexer::countRemainingTokens() {
192
int ExprLexer::countRemainingTokens() {
179
    TokenListItem* temp = currentItem;
193
  TokenListItem* temp = currentItem;
180
    int c = 0;
194
  int c = 0;
181
    while ( temp ) {
195
  while ( temp ) {
182
        ++c;
196
    ++c;
183
        temp = temp->next;
197
    temp = temp->next;
184
    }
198
  }
185
    return c;
199
  return c;
186
} //-- countRemainingTokens
200
} //-- countRemainingTokens
187
201
188
202
189
MBool ExprLexer::hasMoreTokens() {
203
MBool ExprLexer::hasMoreTokens() {
190
    return (MBool) ( currentItem );
204
  return (MBool) ( currentItem );
191
} //-- hasMoreTokens
205
} //-- hasMoreTokens
192
206
193
Token* ExprLexer::nextToken() {
207
Token* ExprLexer::nextToken() {
194
    if ( currentItem ) {
208
  if ( currentItem ) {
195
        Token* token = currentItem->token;
209
    Token* token = currentItem->token;
196
        currentItem = currentItem->next;
210
    currentItem = currentItem->next;
197
        return token;
211
    return token;
198
    }
212
  }
199
    return 0;
213
  return &endToken;
200
} //-- nextToken
214
} //-- nextToken
201
215
202
void ExprLexer::pushBack() {
216
void ExprLexer::pushBack() {
203
    if ( !currentItem ) {
217
  if ( !currentItem ) {
204
        currentItem = lastItem;
218
    currentItem = lastItem;
205
    }
219
  }
206
    else currentItem = currentItem->previous;
220
  else currentItem = currentItem->previous;
207
} //-- pushBack
221
} //-- pushBack
208
222
209
/*
210
Token* ExprLexer::lastToken() {
211
    if (lastItem) {
212
        return lastItem->token;
213
    }
214
    return 0;
215
} //-- lastToken
216
*/
217
218
Token* ExprLexer::peek() {
223
Token* ExprLexer::peek() {
219
    Token* token = 0;
224
  if ( currentItem )
220
    TokenListItem* tlItem = currentItem;
225
    return currentItem->token;
221
    if (tlItem) token = tlItem->token;
226
  return &endToken;
222
    return token;
223
} //-- peek
227
} //-- peek
224
228
225
Token* ExprLexer::lookAhead(int offset) {
229
Token* ExprLexer::lookAhead(int offset) {
226
    Token* token = 0;
230
  Token* token = &endToken;
227
    TokenListItem* tlItem = currentItem;
231
  TokenListItem* tlItem = currentItem;
228
    //-- advance to proper offset
232
  //-- advance to proper offset
229
    for ( int i = 0; i < offset; i++ )
233
  for ( int i = 0; i < offset; i++ )
230
        if ( tlItem ) tlItem = currentItem->next;
234
    if ( tlItem ) tlItem = currentItem->next;
231
235
232
    if (tlItem) token = tlItem->token;
236
  if (tlItem) token = tlItem->token;
233
    return token;
237
  return token;
234
} //-- lookAhead
238
} //-- lookAhead
235
239
236
void ExprLexer::addToken(Token* token) {
240
void ExprLexer::addToken(Token* token) {
237
    TokenListItem* tlItem = new TokenListItem;
241
  TokenListItem* tlItem = new TokenListItem;
238
    tlItem->token = token;
242
  tlItem->token = token;
239
    tlItem->next  = 0;
243
  tlItem->next  = 0;
240
    if (lastItem) {
244
  if (lastItem) {
241
        tlItem->previous = lastItem;
245
    tlItem->previous = lastItem;
242
        lastItem->next = tlItem;
246
    lastItem->next = tlItem;
243
    }
247
  }
244
    if (!firstItem) firstItem = tlItem;
248
  if (!firstItem) firstItem = tlItem;
245
    lastItem = tlItem;
249
  lastItem = tlItem;
246
    prevToken = token;
250
  prevToken = token;
247
    ++tokenCount;
251
  ++tokenCount;
248
} //-- addToken
252
} //-- addToken
249
253
254
// macros for inclusion of char range headers
255
#define TX_CHAR_RANGE(a,b) if (ch<a) return MB_FALSE; \
256
  if (ch<=b) return MB_TRUE
257
#define TX_MATCH_CHAR(a) if (ch<a) return MB_FALSE; \
258
  if (ch==a) return MB_TRUE
259
250
/**
260
/**
251
 * Returns true if the given character represents an Alpha letter
261
 * Returns true if the given character represents an Alpha letter
252
**/
262
**/
253
MBool ExprLexer::isAlphaChar(Int32 ch) {
263
MBool ExprLexer::isLetter(UNICODE_CHAR ch) {
254
    if ((ch >= 'a' ) && (ch <= 'z' )) return MB_TRUE;
264
#include "Letter.h"
255
    if ((ch >= 'A' ) && (ch <= 'Z' )) return MB_TRUE;
265
  return MB_FALSE;
256
    return MB_FALSE;
257
} //-- isAlphaChar
266
} //-- isAlphaChar
258
267
259
/**
268
/**
260
 * Returns true if the given character represents a numeric letter (digit)
269
 * Returns true if the given character represents a numeric letter (digit)
261
**/
270
**/
262
MBool ExprLexer::isDigit(Int32 ch) {
271
MBool ExprLexer::isDigit(UNICODE_CHAR ch) {
263
    if ((ch >= '0') && (ch <= '9'))   return MB_TRUE;
272
  if ((ch >= '0') && (ch <= '9'))   return MB_TRUE;
264
    return MB_FALSE;
273
  return MB_FALSE;
265
} //-- isDigit
274
} //-- isDigit
266
275
267
/**
276
/**
268
 * Returns true if the given character is an allowable NCName character
277
 * Returns true if the given character is an allowable NCName character
269
**/
278
**/
270
MBool ExprLexer::isNCNameChar(Int32 ch) {
279
MBool ExprLexer::isNCNameChar(UNICODE_CHAR ch) {
271
    if (isDigit(ch) || isAlphaChar(ch)) return MB_TRUE;
280
#include "NCNameChar.h"
272
    return (MBool) ((ch == '.') || (ch == '_') || (ch == '-'));
281
  return MB_FALSE;
273
} //-- isNCNameChar
282
} //-- isNCNameChar
274
283
275
/**
284
/**
276
 * Returns true if the given character is an allowable QName character
285
 * Returns true if the following Token should be an operator.
277
**/
286
 * This is a helper for the first bullet of [XPath 3.7]
278
MBool ExprLexer::isQNameChar(Int32 ch) {
287
 *  Lexical Structure
279
    return (MBool) (( ch == ':') || isNCNameChar(ch));
288
**/
280
} //-- isQNameChar
289
MBool ExprLexer::nextIsOperatorToken(Token* token) {
281
290
  if ( !token ) return MB_FALSE;
282
/**
291
  if (token->type >= Token::AXIS_IDENTIFIER && 
283
 * Returns true if the given String is a valid XML QName
292
      token->type <= Token::UNION_OP)
284
**/
285
MBool ExprLexer::isValidQName(String& name) {
286
287
    int size = name.length();
288
    if ( size == 0 ) return MB_FALSE;
289
    else if ( !isAlphaChar(name.charAt(0))) return MB_FALSE;
290
    else {
291
        for ( int i = 1; i < size; i++) {
292
            if ( ! isQNameChar(name.charAt(i))) return MB_FALSE;
293
        }
294
    }
295
    return MB_TRUE;
296
} //-- isValidQName
297
298
MBool ExprLexer::isOperatorToken(Token* token) {
299
    if ( !token ) return MB_FALSE;
300
    switch ( token->type ) {
301
        //-- boolean operators
302
        case Token::AND_OP:
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;
293
    return MB_FALSE;
294
  if (token->type == Token::NULL_TOKEN) return MB_FALSE;
295
  if (token->type == Token::L_PAREN) return MB_FALSE;
296
  if (token->type == Token::L_BRACKET) return MB_FALSE;
297
  if (token->type == Token::AT_SIGN) return MB_FALSE;
298
  return MB_TRUE;
324
} //-- isOperatorToken
299
} //-- isOperatorToken
325
300
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
    }
380
    Token* token = 0;
381
    if ( addChar ) token = new Token(ch, tokenType);
382
    else token = new Token(tokenType);
383
384
    addToken(token);
385
    return MB_TRUE;
386
} //-- matchDelimiter
387
388
/**
301
/**
389
 * Returns true if the value of the given String matches
390
 * an OperatorName
391
**/
392
MBool ExprLexer::matchesOperator(String& buffer) {
393
394
    int index = 0;
395
    while (index < NUMBER_OF_TOKENS) {
396
        Token tok = TOKENS[index++];
397
        if ( tok.value.isEqual(buffer) ) {
398
            if (isOperatorToken( &tok )) return MB_TRUE;
399
        }
400
    }
401
    return MB_FALSE;
402
403
} //-- matchesOperator
404
405
/**
406
 * Matches the given String to the appropriate Token
407
 * @param buffer the current StringBuffer representing the value of the Token
408
 * @param ch, the current delimiter token
409
**/
410
void ExprLexer::matchToken(String& buffer, UNICODE_CHAR ch) {
411
412
    if ( buffer.length() == 0) return;
413
414
    Token* match = new Token();
415
    MBool foundMatch = MB_FALSE;
416
    int index = 0;
417
418
    //-- check previous token
419
    switch(prevToken->type) {
420
        case Token::VAR_REFERENCE :
421
            if ( prevToken->value.length() == 0) {
422
                prevToken->value.append(buffer);
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::PI :
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
302
 *  Parses the given String into the set of Tokens
498
**/
303
**/
499
void ExprLexer::parse(const String& pattern) {
304
void ExprLexer::parse(const String& pattern) {
500
305
306
  String tokenBuffer;
501
307
502
    String tokenBuffer;
308
  Int32 iter = 0, start;
503
    UNICODE_CHAR inLiteral = '\0';
309
  Int32 size = pattern.length();
504
    MBool inNumber  = MB_FALSE;
310
  short defType = Token::CNAME;
505
311
  UNICODE_CHAR ch;
506
    Int32 currentPos = 0;
312
  if ( size==0 ) return;
507
313
508
    UNICODE_CHAR ch = '\0';
314
  //-- initialize previous token, this will automatically get
509
    UNICODE_CHAR prevCh = ch;
315
  //-- deleted when it goes out of scope
510
316
  Token nullToken('\0', Token::NULL_TOKEN);
511
    //-- initialize previous token, this will automatically get
317
512
    //-- deleted when it goes out of scope
318
  prevToken = &nullToken;
513
    Token nullToken('\0', Token::NULL_TOKEN);
319
514
320
  while (iter < size) {
515
    prevToken = &nullToken;
321
516
322
    ch = pattern.charAt(iter);
517
    while (currentPos < pattern.length()) {
323
    defType = Token::CNAME;
518
324
519
        prevCh = ch;
325
    if (ch==DOLLAR_SIGN){
520
        ch = pattern.charAt(currentPos);
326
      if (iter++ == size || !isLetter(ch=pattern.charAt(iter))) {
521
327
        // Error, VariableReference expected
522
        if ( inLiteral ) {
328
        errorPos = iter;
523
            //-- look for end of literal
329
        errorCode = ERROR_UNRESOLVED_VAR_REFERENCE;
524
            if ( ch == inLiteral ) {
330
        firstItem->token->type=Token::ERROR;
525
                inLiteral = '\0';
331
        iter=size; // bail
526
                addToken(new Token(tokenBuffer, Token::LITERAL));
332
      } else
527
                tokenBuffer.clear();
333
        defType = Token::VAR_REFERENCE;
528
            }
334
    } 
529
            else {
335
    // just reuse the QName parsing, which will use defType 
530
                tokenBuffer.append(ch);
336
    // the token to construct
531
            }
337
338
    if ( isLetter(ch) ) {
339
      // NCName, can get QName or OperatorName;
340
      //  FunctionName, NodeName, and AxisSpecifier may want whitespace,
341
      //  and are dealt with below
342
      start = iter;
343
      while (iter++ < size && 
344
             isNCNameChar(pattern.charAt(iter))) /* just go */ ;
345
      Int32 end = iter;
346
      if (pattern.charAt(iter)==COLON) {
347
        // try QName, might need to step back for axis
348
        while(iter++ < size && 
349
              isNCNameChar(pattern.charAt(iter))) /* just go */ ;
350
        if (iter==end+1) iter--; // step back
351
      }
352
      if (nextIsOperatorToken(prevToken)){
353
        if (pattern.subString(start,end,subStr).isEqual(AND))
354
          defType = Token::AND_OP;
355
        else if (pattern.subString(start,end,subStr).isEqual(OR))
356
          defType = Token::OR_OP;
357
        else if (pattern.subString(start,end,subStr).isEqual(MODULUS))
358
          defType = Token::MODULUS_OP;
359
        else if (pattern.subString(start,end,subStr).isEqual(DIVIDE))
360
          defType = Token::DIVIDE_OP;
361
        else {
362
          // Error "operator expected"
363
          // XXX QUESTION: spec is not too precise
364
          // badops is sure an error, but is bad:ops, too? We say yes!
365
          errorPos = iter;
366
          errorCode = ERROR_OP_EXPECTED;
367
          firstItem->token->type=Token::ERROR;
368
          iter=size; // bail
532
        }
369
        }
533
        else if ( inNumber ) {
370
      }
534
            if (isDigit(ch) || (ch == '.')) {
371
      addToken(new Token(pattern.subString(start,iter,subStr),defType));
535
                tokenBuffer.append(ch);
372
    } else if ( isDigit(ch) ) {
536
            }
373
      start = iter;
537
            else {
374
      while (iter++ < size && 
538
                inNumber = MB_FALSE;
375
             isDigit(pattern.charAt(iter))) /* just go */;
539
                addToken(new Token(tokenBuffer, Token::NUMBER));
376
      if (pattern.charAt(iter)=='.')
540
                tokenBuffer.clear();
377
        while (iter++ < size && 
541
                //-- push back last char
378
               isDigit(pattern.charAt(iter))) /* just go */;
542
                --currentPos;
379
      addToken(new Token(pattern.subString(start,iter,subStr),Token::NUMBER));
543
            }
380
    } else {
381
      switch (ch) {
382
        //-- ignore whitespace
383
      case SPACE:
384
      case TX_TAB:
385
      case TX_CR:
386
      case TX_LF:
387
        iter++;
388
        break;
389
      case S_QUOTE :
390
      case D_QUOTE :
391
        start=iter;
392
        iter = pattern.indexOf(ch,start+1);
393
        if (iter==NOT_FOUND){
394
          // XXX Error reporting "unclosed literal"
395
          errorPos = start;
396
          errorCode = ERROR_UNCLOSED_LITERAL;
397
          firstItem->token->type=Token::ERROR;
398
          iter=size; // bail
399
        } else {
400
          addToken(new Token(pattern.subString(start+1,iter,subStr),
401
                             Token::LITERAL));
402
          iter++;
544
        }
403
        }
545
        else if (isDigit(ch)) {
404
        break;
546
            if  ((tokenBuffer.length() == 0 ) || matchesOperator(tokenBuffer) ) {
405
      case PERIOD:
547
                //-- match operator and free up token buffer
406
        // period can be .., .(DIGITS)+ or ., check next
548
                matchToken(tokenBuffer, ch);
407
        if (iter++ < size){
549
                inNumber = MB_TRUE;
408
          if (isDigit(ch=pattern.charAt(iter))){
550
            }
409
            start=iter-1;
551
            else if (( tokenBuffer.length() == 1 ) && (prevCh = '-')) {
410
            while (iter++ < size && 
552
                inNumber = MB_TRUE;
411
                   isDigit(pattern.charAt(iter))) /* just go */;
553
            }
412
            addToken(new Token(pattern.subString(start,iter,subStr),
554
            tokenBuffer.append(ch);
413
                               Token::NUMBER));
414
          } else if (ch==PERIOD) {
415
            addToken(new Token(pattern.subString(iter-1,iter++,subStr),
416
                               Token::PARENT_NODE));
417
          } else
418
            addToken(new Token(ch, Token::SELF_NODE));
419
          // iter++ is already in the number test
555
        }
420
        }
556
        else {
421
        break;
557
            switch (ch) {
422
      case COLON: // QNames are dealt above, must be axis ident
558
                //-- ignore whitespace
423
        if (iter++ < size && pattern.charAt(iter)==COLON &&
559
                case SPACE:
424
            prevToken->type == Token::CNAME) {
560
                case TX_TAB:
425
          prevToken->type = Token::AXIS_IDENTIFIER;
561
                case TX_CR:
426
          iter++;
562
                case TX_LF:
427
        } else {
563
                    break;
428
          // XXX Error report "colon is neither QName nor axis"
564
                case S_QUOTE :
429
          errorPos = iter;
565
                case D_QUOTE :
430
          errorCode = ERROR_COLON;
566
                    matchToken(tokenBuffer, ch);
431
          firstItem->token->type=Token::ERROR;
567
                    inLiteral = ch;
432
          iter=size; // bail
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
                        Int32 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
        }
433
        }
714
        ++currentPos;
434
        break;
715
    }
435
      case FORWARD_SLASH :
716
    //-- end lexical parsing of current token
436
        if (iter++ < size && pattern.charAt(iter)==ch){
717
    //-- freeBuffer if needed
437
          addToken(new Token(pattern.subString(iter-1,iter++,subStr),
718
438
                             Token::ANCESTOR_OP));
719
    if ( inNumber ) {
439
        } else {
720
        addToken(new Token(tokenBuffer, Token::NUMBER));
440
          addToken(new Token(ch, Token::PARENT_OP));
441
        }
442
        break;
443
      case BANG : // can only be !=
444
        if (iter++ < size && pattern.charAt(iter)==EQUAL) {
445
          addToken(new Token(pattern.subString(iter-1,iter+1,subStr),
446
                             Token::NOT_EQUAL_OP));
447
          iter++;
448
        } else {
449
          // Error ! is not not()
450
          errorPos = iter;
451
          errorCode = ERROR_BANG;
452
          firstItem->token->type=Token::ERROR;
453
          iter=size; // bail
454
        }
455
        break;
456
      case EQUAL:
457
        addToken(new Token(ch,Token::EQUAL_OP));
458
        iter++;
459
        break;
460
      case L_ANGLE:
461
        if (iter++ < size && pattern.charAt(iter)==EQUAL){
462
          addToken(new Token(pattern.subString(iter-1,iter+1,subStr),
463
                             Token::LESS_OR_EQUAL_OP));
464
          iter++;
465
        } else
466
          addToken(new Token(ch,Token::LESS_THAN_OP));
467
        break;
468
      case R_ANGLE:
469
        if (iter++ < size && pattern.charAt(iter)==EQUAL){
470
          addToken(new Token(pattern.subString(iter-1,iter+1,subStr),
471
                             Token::GREATER_OR_EQUAL_OP));
472
          iter++;
473
        } else
474
          addToken(new Token(ch,Token::GREATER_THAN_OP));
475
        break;
476
      case HYPHEN :
477
        addToken(new Token(ch,Token::SUBTRACTION_OP));
478
        iter++;
479
        break;
480
      case ASTERIX:
481
        if (nextIsOperatorToken(prevToken))
482
          addToken(new Token(ch,Token::MULTIPLY_OP));
483
        else
484
          addToken(new Token(ch,Token::CNAME));
485
        iter++;
486
        break;
487
      case L_PAREN:
488
        if (prevToken->type == Token::CNAME){
489
          if (prevToken->value.isEqual(COMMENT))
490
            prevToken->type = Token::COMMENT;
491
          else if (prevToken->value.isEqual(NODE))
492
            prevToken->type = Token::NODE;
493
          else if (prevToken->value.isEqual(PI))
494
            prevToken->type = Token::PI;
495
          else if (prevToken->value.isEqual(TEXT))
496
            prevToken->type = Token::TEXT;
497
          else
498
            prevToken->type = Token::FUNCTION_NAME;
499
        }
500
        iter++;
501
        addToken(new Token(ch,Token::L_PAREN));
502
        break;
503
      case R_PAREN:
504
        iter++;
505
        addToken(new Token(ch,Token::R_PAREN));
506
        break;
507
      case L_BRACKET:
508
        iter++;
509
        addToken(new Token(ch,Token::L_BRACKET));
510
        break;
511
      case R_BRACKET:
512
        iter++;
513
        addToken(new Token(ch,Token::R_BRACKET));
514
        break;
515
      case COMMA:
516
        iter++;
517
        addToken(new Token(ch,Token::COMMA));
518
        break;
519
      case AT_SIGN :
520
        iter++;
521
        addToken(new Token(ch,Token::AT_SIGN));
522
        break;
523
      case PLUS:
524
        iter++;
525
        addToken(new Token(ch,Token::ADDITION_OP));
526
        break;
527
      case VERT_BAR:
528
        iter++;
529
        addToken(new Token(ch,Token::UNION_OP));
530
        break;
531
      }
721
    }
532
    }
722
    else matchToken(tokenBuffer, ch);
533
  }    
723
    prevToken = 0;
724
} //-- parse
534
} //-- parse
725
535
(-)ExprLexer.h (-42 / +37 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 25-31    Link Here 
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.6 2001/04/08 14:36:50 peterv%netscape.com Exp $
28
 * $Id: ExprLexer.h,v 1.5 2001/01/22 09:36:16 kvisco%ziplink.net Exp $
29
 */
29
 */
30
30
31
31
 Lines 41-47    Link Here 
41
 * This class was ported from XSL:P, an open source Java based 
41
 * This class was ported from XSL:P, an open source Java based 
42
 * XSLT processor, written by yours truly.
42
 * XSLT processor, written by yours truly.
43
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
43
 * @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
44
 * @version $Revision: 1.6 $ $Date: 2001/04/08 14:36:50 $
44
 * @version $Revision: 1.5 $ $Date: 2001/01/22 09:36:16 $
45
**/
45
**/
46
class Token {
46
class Token {
47
47
 Lines 65-71    Link Here 
65
        L_BRACKET,
65
        L_BRACKET,
66
        R_BRACKET,
66
        R_BRACKET,
67
        COMMA,
67
        COMMA,
68
        FUNCTION_NAME,
68
        FUNCTION_NAME, // 10
69
        AT_SIGN,
69
        AT_SIGN,
70
        VAR_REFERENCE,
70
        VAR_REFERENCE,
71
        PARENT_NODE,
71
        PARENT_NODE,
 Lines 76-107    Link Here 
76
        //-------------/
76
        //-------------/
77
77
78
        //-- boolean ops
78
        //-- boolean ops
79
        AND_OP,
79
        AND_OP, // 16
80
        OR_OP,
80
        OR_OP,
81
81
82
        //-- relational
82
        //-- relational
83
        EQUAL_OP,
83
        EQUAL_OP, // 18
84
        NOT_EQUAL_OP,
84
        NOT_EQUAL_OP,
85
        LESS_THAN_OP,
85
        LESS_THAN_OP,
86
        GREATER_THAN_OP,
86
        GREATER_THAN_OP,
87
        LESS_OR_EQUAL_OP,
87
        LESS_OR_EQUAL_OP,
88
        GREATER_OR_EQUAL_OP,
88
        GREATER_OR_EQUAL_OP,
89
        //-- additive operators
89
        //-- additive operators
90
        ADDITION_OP,
90
        ADDITION_OP, // 24
91
        SUBTRACTION_OP,
91
        SUBTRACTION_OP,
92
        //-- multiplicative
92
        //-- multiplicative
93
        DIVIDE_OP ,
93
        DIVIDE_OP , // 26
94
        MULTIPLY_OP,
94
        MULTIPLY_OP,
95
        MODULUS_OP,
95
        MODULUS_OP,
96
        //-- path operators
96
        //-- path operators
97
        PARENT_OP,
97
        PARENT_OP, // 29
98
        ANCESTOR_OP,
98
        ANCESTOR_OP,
99
        UNION_OP,
99
        UNION_OP,
100
        //-- node type tokens
100
        //-- node type tokens
101
        COMMENT,
101
        COMMENT, // 32
102
        NODE,
102
        NODE,
103
        PI,
103
        PI,
104
        TEXT
104
        TEXT,
105
        
106
        //-- Special endtoken
107
        END // 36
105
    };
108
    };
106
109
107
110
 Lines 166-171    Link Here 
166
        TX_LF             = '\r'
169
        TX_LF             = '\r'
167
    };
170
    };
168
171
172
    enum _error_consts {
173
        ERROR_UNRESOLVED_VAR_REFERENCE = 0,
174
        ERROR_OP_EXPECTED,
175
        ERROR_UNCLOSED_LITERAL,
176
        ERROR_COLON,
177
        ERROR_BANG
178
    };
179
    static const String error_message[];
180
    Int32 errorPos;
181
    short errorCode;
169
182
170
    /*
183
    /*
171
     * Complex Tokens
184
     * Complex Tokens
 Lines 181-186    Link Here 
181
    static const String OR;
194
    static const String OR;
182
195
183
    //-- Multiplicative
196
    //-- Multiplicative
197
    static const String MULTIPLY;
184
    static const String MODULUS;
198
    static const String MODULUS;
185
    static const String DIVIDE;
199
    static const String DIVIDE;
186
200
 Lines 220-227    Link Here 
220
    void   pushBack();
234
    void   pushBack();
221
    MBool  hasMoreTokens();
235
    MBool  hasMoreTokens();
222
236
223
    MBool isOperatorToken(Token* token);
224
225
private:
237
private:
226
238
227
    struct TokenListItem {
239
    struct TokenListItem {
 Lines 237-286    Link Here 
237
    int tokenCount;
249
    int tokenCount;
238
250
239
    Token* prevToken;
251
    Token* prevToken;
252
    Token endToken;
240
253
241
    void addToken(Token* token);
254
    void addToken(Token* token);
242
255
243
    /**
256
    /**
244
     * Returns true if the given character represents an Alpha letter
257
     * Returns true if the following Token should be an operator.
245
    **/
258
     * This is a helper for the first bullet of [XPath 3.7]
246
    static MBool isAlphaChar(Int32 ch);
259
     *  Lexical Structure
260
     **/
261
    MBool nextIsOperatorToken(Token* token);
247
262
248
    /**
263
    /**
249
     * Returns true if the given character represents a numeric letter (digit)
264
     * Returns true if the given character represents an Alpha letter
250
    **/
265
    **/
251
    static MBool isDigit(Int32 ch);
266
    static MBool isLetter(UNICODE_CHAR ch);
252
267
253
    /**
268
    /**
254
     * Returns true if the given character is an allowable QName character
269
     * Returns true if the given character represents a numeric letter (digit)
255
    **/
270
    **/
256
    static MBool isQNameChar(Int32 ch);
271
    static MBool isDigit(UNICODE_CHAR ch);
257
272
258
    /**
273
    /**
259
     * Returns true if the given character is an allowable NCName character
274
     * Returns true if the given character is an allowable NCName character
260
    **/
261
    static MBool isNCNameChar(Int32 ch);
262
263
    /**
264
     * Returns true if the given String is a valid XML QName
265
    **/
266
    static MBool isValidQName(String& name);
267
268
    MBool matchDelimiter(UNICODE_CHAR ch);
269
270
    /**
271
     * Returns true if the value of the given String matches
272
     * an OperatorName
273
    **/
275
    **/
274
    MBool matchesOperator(String& buffer);
276
    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
277
278
    String subStr;
284
    void parse(const String& pattern);
279
    void parse(const String& pattern);
285
280
286
}; //-- ExprLexer
281
}; //-- ExprLexer
(-)ExprParser.cpp (-359 / +312 lines)
Line     Link Here 
 Lines 45-53    Link Here 
45
#include "FunctionLib.h"
45
#include "FunctionLib.h"
46
#include "Names.h"
46
#include "Names.h"
47
47
48
const String ExprParser::L_CURLY_BRACE = "{";
49
const String ExprParser::R_CURLY_BRACE = "}";
50
51
/**
48
/**
52
 * Creates a new ExprParser
49
 * Creates a new ExprParser
53
**/
50
**/
 Lines 60-145    Link Here 
60
57
61
/**
58
/**
62
 * Creates an Attribute Value Template using the given value
59
 * Creates an Attribute Value Template using the given value
60
 * This should move to XSLProcessor class
63
**/
61
**/
64
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
62
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
65
    (const String& attValue)
63
    (const String& attValue)
66
{
64
{
67
65
68
    AttributeValueTemplate* avt = new AttributeValueTemplate();
66
    AttributeValueTemplate* avt = new AttributeValueTemplate();
67
69
    Int32 size = attValue.length();
68
    Int32 size = attValue.length();
69
    if ( size == 0) return avt; //XXX should return 0, but that causes crash in lre12
70
70
    int cc = 0;
71
    int cc = 0;
72
    UNICODE_CHAR nextCh;
73
    UNICODE_CHAR ch;
71
    String buffer;
74
    String buffer;
72
    MBool inExpr    = MB_FALSE;
75
    MBool inExpr    = MB_FALSE;
73
    MBool inLiteral = MB_FALSE;
76
    MBool inLiteral = MB_FALSE;
74
    UNICODE_CHAR endLiteral = '"';
77
    UNICODE_CHAR endLiteral;
75
    UNICODE_CHAR prevCh = '\0';
76
78
77
    while ( cc < size) {
79
    nextCh = attValue.charAt(cc);
78
        UNICODE_CHAR ch = attValue.charAt(cc++);
80
    while ( cc++ < size) {
81
        ch = nextCh;
82
        nextCh = cc != size ? attValue.charAt(cc) : 0;
83
        
79
        // if in literal just add ch to buffer
84
        // if in literal just add ch to buffer
80
        if ( inLiteral && (ch != endLiteral) ) {
85
        if ( inLiteral && (ch != endLiteral) ) {
81
                buffer.append(ch);
86
                buffer.append(ch);
82
                prevCh = ch;
83
                continue;
87
                continue;
84
        }
88
        }
85
        switch ( ch ) {
89
        switch ( ch ) {
86
            case '\'' :
90
            case '\'' :
87
            case '"' :
91
            case '"' :
88
                buffer.append(ch);
92
                buffer.append(ch);
89
                if (inLiteral) inLiteral = MB_FALSE;
93
                if (inLiteral)
90
                else {
94
                    inLiteral = MB_FALSE;
95
                else if (inExpr) {
91
                    inLiteral = MB_TRUE;
96
                    inLiteral = MB_TRUE;
92
                    endLiteral = ch;
97
                    endLiteral = ch;
93
                }
98
                }
94
                break;
99
                break;
95
            case  '{' :
100
            case  '{' :
96
                // Ignore case where we find two { without a }
97
                if (!inExpr) {
101
                if (!inExpr) {
98
                    //-- clear buffer
102
                    // Ignore case where we find two {
99
                    if ( buffer.length() > 0) {
103
                    if ( nextCh == ch ) {
100
                        avt->addExpr(new StringExpr(buffer));
104
                        buffer.append(ch); //-- append '{'
105
                        cc++;
106
                        nextCh = cc != size ? attValue.charAt(cc) : 0;
107
                    }
108
                    else {
109
                        if ( buffer.length() > 0)
110
                            avt->addExpr(new StringExpr(buffer));
101
                        buffer.clear();
111
                        buffer.clear();
112
                        inExpr = MB_TRUE;
102
                    }
113
                    }
103
                    inExpr = MB_TRUE;
104
                }
114
                }
105
                else if (prevCh == ch) {
115
                else
106
                    inExpr = MB_FALSE;
107
                    buffer.append(ch);
108
                }
109
                else {
110
                    buffer.append(ch); //-- simply append '{'
116
                    buffer.append(ch); //-- simply append '{'
111
                    ch = '\0';
112
                }
113
                break;
117
                break;
114
            case '}':
118
            case '}':
115
                if (inExpr) {
119
                if (inExpr) {
116
                    inExpr = MB_FALSE;
120
                    inExpr = MB_FALSE;
117
                    avt->addExpr(createExpr(buffer));
121
                    Expr* expr = createExpr(buffer);
122
                    if (!expr) {
123
                        delete avt;
124
                        return 0;
125
                    }
126
                    avt->addExpr(expr);
118
                    buffer.clear();
127
                    buffer.clear();
119
                    //-- change in case another '}' follows
120
                    ch = '\0';
121
                }
128
                }
122
                else if (prevCh != ch) {
129
                else if (nextCh == ch) {
123
                    if ( buffer.length() > 0) buffer.append('}');
130
                    buffer.append(ch);
124
                    else avt->addExpr(new StringExpr(R_CURLY_BRACE));
131
                    cc++;
132
                    nextCh = cc != size ? attValue.charAt(cc) : 0;
125
                }
133
                }
134
                else {
135
                    //XXX ErrorReport: unmatched '}' found
136
                    delete avt;
137
                    return 0;
138
                }
126
                break;
139
                break;
127
            default:
140
            default:
128
                buffer.append(ch);
141
                buffer.append(ch);
129
                break;
142
                break;
130
        }
143
        }
131
        prevCh = ch;
132
    }
144
    }
133
    if ( buffer.length() > 0) {
145
134
        if ( inExpr ) {
146
    if ( inExpr ) {
135
            //-- error
147
        //XXX ErrorReport: ending '}' missing
136
            String errMsg("#error evaluating AttributeValueTemplate. ");
148
        delete avt;
137
            errMsg.append("Missing '}' after: ");
149
        return 0;
138
            errMsg.append(buffer);
139
            avt->addExpr(new StringExpr(errMsg));
140
        }
141
        else avt->addExpr(new StringExpr(buffer));
142
    }
150
    }
151
152
    if ( buffer.length() > 0)
153
        avt->addExpr(new StringExpr(buffer));
154
143
    return avt;
155
    return avt;
144
156
145
} //-- createAttributeValueTemplate
157
} //-- createAttributeValueTemplate
 Lines 149-157    Link Here 
149
    return createExpr(lexer);
161
    return createExpr(lexer);
150
} //-- createExpr
162
} //-- createExpr
151
163
152
PatternExpr* ExprParser::createPatternExpr(const String& pattern) {
164
Expr* ExprParser::createPatternExpr(const String& pattern) {
153
    ExprLexer lexer(pattern);
165
    ExprLexer lexer(pattern);
154
    return createUnionExpr(lexer);
166
    Expr* expr = createUnionExpr(lexer);
167
    return expr;
155
} //-- createPatternExpr
168
} //-- createPatternExpr
156
169
157
LocationStep* ExprParser::createLocationStep(const String& path) {
170
LocationStep* ExprParser::createLocationStep(const String& path) {
 Lines 216-222    Link Here 
216
} //-- createBinaryExpr
229
} //-- createBinaryExpr
217
230
218
231
219
Expr*  ExprParser::createExpr(ExprLexer& lexer) {
232
Expr* ExprParser::createExpr(ExprLexer& lexer) {
220
233
221
    MBool done = MB_FALSE;
234
    MBool done = MB_FALSE;
222
235
 Lines 224-291    Link Here 
224
237
225
    Stack exprs;
238
    Stack exprs;
226
    Stack ops;
239
    Stack ops;
240
    
241
    if (lexer.peek()->type == Token::ERROR) {
242
      done = MB_TRUE;
243
      // XXX Error notification of caller
244
    }
245
    while ( !done ) {
246
247
        MBool unary = MB_FALSE;
248
        while( lexer.peek()->type == Token::SUBTRACTION_OP ) {
249
            unary = !unary;
250
            lexer.nextToken();
251
        }
252
253
        expr = createUnionExpr(lexer);
254
        if ( !expr )
255
            break;
227
256
228
    while ( lexer.hasMoreTokens() && (!done)) {
257
        if ( unary )
258
            expr = new UnaryExpr(expr);
229
259
230
        Token* tok = lexer.nextToken();
260
        Token* tok = lexer.nextToken();
231
        switch ( tok->type ) {
261
        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:
262
            case Token::ADDITION_OP:
290
            case Token::DIVIDE_OP:
263
            case Token::DIVIDE_OP:
291
            //-- boolean ops
264
            //-- boolean ops
 Lines 304-331    Link Here 
304
            case Token::MULTIPLY_OP:
277
            case Token::MULTIPLY_OP:
305
            case Token::SUBTRACTION_OP:
278
            case Token::SUBTRACTION_OP:
306
            {
279
            {
307
                if ( !exprs.empty() ) {
280
                while ( !exprs.empty() &&
308
                    short ttype = ((Token*)ops.peek())->type;
281
                        precedenceLevel(tok->type) <= precedenceLevel(((Token*)ops.peek())->type)) {
309
                    if (precedenceLevel(tok->type) < precedenceLevel(ttype)) {
282
                    expr = createBinaryExpr((Expr*)exprs.pop(),
310
                        expr = createBinaryExpr((Expr*)exprs.pop(), expr,
283
                                             expr,
311
                            (Token*)ops.pop());
284
                                             (Token*)ops.pop());
312
                    }
313
                }
285
                }
314
                exprs.push(expr);
286
                exprs.push(expr);
315
                ops.push(tok);
287
                ops.push(tok);
316
                expr = 0; // OG, prevent reuse of expr
317
                break;
288
                break;
318
            }
289
            }
319
            default:
290
            default:
320
                lexer.pushBack();
291
                lexer.pushBack();
321
                expr = createPatternExpr(lexer);
292
                done = MB_TRUE;
322
                break;
293
                break;
323
        }
294
        }
324
    }
295
    }
325
296
326
    // make sure expr != 0, will this happen?
297
    // make sure expr != 0
327
    if (( expr == 0 ) && (!exprs.empty()))
298
    if ( expr == 0 ) {
328
        expr = (Expr*) exprs.pop();
299
        while (!exprs.empty() ) {
300
            delete (Expr*)exprs.pop();
301
        }
302
        return 0;
303
    }
329
304
330
    while (!exprs.empty() ) {
305
    while (!exprs.empty() ) {
331
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
306
        expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
 Lines 335-401    Link Here 
335
310
336
} //-- createExpr
311
} //-- createExpr
337
312
338
FilterExpr*  ExprParser::createFilterExpr(ExprLexer& lexer) {
313
Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
339
314
340
    FilterExpr* filterExpr = new FilterExpr();
341
    Token* tok = lexer.nextToken();
315
    Token* tok = lexer.nextToken();
342
    if ( !tok ) return filterExpr;
343
316
344
    Expr* expr = 0;
317
    Expr* expr = 0;
345
    switch ( tok->type ) {
318
    switch ( tok->type ) {
346
        case Token::FUNCTION_NAME :
319
        case Token::FUNCTION_NAME :
320
            lexer.pushBack();
347
            expr = createFunctionCall(lexer);
321
            expr = createFunctionCall(lexer);
348
            filterExpr->setExpr(expr);
349
            break;
322
            break;
350
        case Token::VAR_REFERENCE :
323
        case Token::VAR_REFERENCE :
351
            expr = new VariableRefExpr(tok->value);
324
            expr = new VariableRefExpr(tok->value);
352
            filterExpr->setExpr(expr);
353
            break;
325
            break;
354
        case Token::L_PAREN:
326
        case Token::L_PAREN:
355
            //-- primary group expr:
356
            expr = createExpr(lexer);
327
            expr = createExpr(lexer);
357
            tok = lexer.nextToken();
328
            if(!expr) return 0;
358
            if ( (!tok) || (tok->type != Token::R_PAREN ) ) {
329
359
                String errMsg("error: ");
330
            if ( lexer.nextToken()->type != Token::R_PAREN ) {
360
                expr->toString(errMsg);
331
                lexer.pushBack();
361
                errMsg.append(" - missing ')'");
332
                //XXX ErrorReport: right parenthesis expected
362
                delete expr; //-- free up current expr
333
                delete expr;
363
                expr = new ErrorFunctionCall(errMsg);
334
                return 0;
364
            }
335
            }
365
            filterExpr->setExpr(expr);
366
            break;
336
            break;
367
        case Token::PARENT_NODE :
337
        case Token::LITERAL :
368
            expr = new ParentExpr();
338
            expr = new StringExpr(tok->value);
369
            filterExpr->setExpr(expr);
370
            break;
339
            break;
371
        case Token::SELF_NODE :
340
        case Token::NUMBER:
372
            expr = new IdentityExpr();
341
        {
373
            filterExpr->setExpr(expr);
342
            StringResult str(tok->value);
343
            expr = new NumberExpr(str.numberValue());
374
            break;
344
            break;
345
        }
375
        default:
346
        default:
347
            // this should never ever happen.
348
            lexer.pushBack();
349
            //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
350
            return 0;
376
            break;
351
            break;
377
    }
352
    }
353
    if(!expr) return 0;
378
354
379
    //-- handle predicates
355
    if ( lexer.peek()->type == Token::L_BRACKET ) {
380
    parsePredicates(filterExpr, lexer);
381
356
382
    return filterExpr;
357
        FilterExpr* filterExpr = new FilterExpr();
358
        filterExpr->setExpr(expr);
359
360
        //-- handle predicates
361
        if(!parsePredicates(filterExpr, lexer)) {
362
            delete filterExpr;
363
            return 0;
364
        }
365
        expr = filterExpr;
366
    }
383
367
368
    return expr;
369
384
} //-- createFilterExpr
370
} //-- createFilterExpr
385
371
386
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
372
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
387
373
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;
374
    FunctionCall* fnCall = 0;
394
375
395
    Token* tok = lexer.nextToken();
376
    Token* tok = lexer.nextToken();
396
397
    if ( tok->type != Token::FUNCTION_NAME ) {
377
    if ( tok->type != Token::FUNCTION_NAME ) {
398
        return new ErrorFunctionCall("invalid function call");
378
        //XXX ErrorReport: error in parser, please report on bugzilla.mozilla.org
379
        return 0;
399
    }
380
    }
400
381
401
    String fnName = tok->value;
382
    String fnName = tok->value;
 Lines 491-512    Link Here 
491
        //-- not our job to report an invalid function call here
472
        //-- not our job to report an invalid function call here
492
        fnCall = new ExtensionFunctionCall(fnName);
473
        fnCall = new ExtensionFunctionCall(fnName);
493
    }
474
    }
475
    
494
    //-- handle parametes
476
    //-- handle parametes
495
    List params;
477
    if(!parseParameters(fnCall, lexer)) {
496
    String* errMsg = parseParameters(&params, lexer);
478
        delete fnCall;
497
    if (errMsg) {
479
        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
    }
480
    }
511
    return fnCall;
481
    return fnCall;
512
} //-- createFunctionCall
482
} //-- createFunctionCall
 Lines 514-522    Link Here 
514
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
484
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
515
485
516
    LocationStep* lstep = new LocationStep();
486
    LocationStep* lstep = new LocationStep();
487
488
    //-- child axis is default
517
    short axisIdentifier = LocationStep::CHILD_AXIS;
489
    short axisIdentifier = LocationStep::CHILD_AXIS;
490
    NodeExpr* nodeExpr = 0;
518
491
519
    //-- get Axis Identifier, if present
492
    //-- get Axis Identifier or AbbreviatedStep, if present
520
    Token* tok = lexer.peek();
493
    Token* tok = lexer.peek();
521
    switch (tok->type) {
494
    switch (tok->type) {
522
        case Token::AXIS_IDENTIFIER:
495
        case Token::AXIS_IDENTIFIER:
 Lines 550-560    Link Here 
550
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
523
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
551
            else if ( SELF_AXIS.isEqual(tok->value) )
524
            else if ( SELF_AXIS.isEqual(tok->value) )
552
                axisIdentifier = LocationStep::SELF_AXIS;
525
                axisIdentifier = LocationStep::SELF_AXIS;
553
            //-- child axis is default
526
            else {
554
            else if (!CHILD_AXIS.isEqual(tok->value)) {
527
                delete lstep;
555
                //-- handle error gracefully, simply ignore invalid axis and
528
                //XXX ErrorReport: unknow axis
556
                //-- use default. Add error message when message observer
529
                return 0;
557
                //-- is implemented
558
            }
530
            }
559
            break;
531
            break;
560
        }
532
        }
 Lines 563-611    Link Here 
563
            lexer.nextToken();
535
            lexer.nextToken();
564
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
536
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
565
            break;
537
            break;
538
        case Token::PARENT_NODE :
539
            //-- eat token
540
            lexer.nextToken();
541
            axisIdentifier = LocationStep::PARENT_AXIS;
542
            nodeExpr = new BasicNodeExpr();
543
            break;
544
        case Token::SELF_NODE :
545
            //-- eat token
546
            lexer.nextToken();
547
            axisIdentifier = LocationStep::SELF_AXIS;
548
            nodeExpr = new BasicNodeExpr();
549
            break;
566
        default:
550
        default:
567
            break;
551
            break;
568
    }
552
    }
569
570
    lstep->setAxisIdentifier(axisIdentifier);
571
572
573
    NodeExpr* nodeExpr = 0;
574
575
    tok = lexer.peek();
576
    if (!tok) {
577
        ///XXXXX We need to create an ErrorExpr or something to
578
        ///XXXXX handle errors
579
    }
580
    // NameTest
581
    else if (tok->type == Token::CNAME) {
582
        //-- handle NameTest
583
        //-- eat token
584
        lexer.nextToken();
585
        if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
586
            nodeExpr = new AttributeExpr(tok->value);
587
        else
588
            nodeExpr = new ElementExpr(tok->value);
589
553
590
    }
554
    //-- get NodeTest unless AbbreviatedStep was found
591
    // NodeType
555
    if ( !nodeExpr ) {
592
    else {
556
        tok = lexer.nextToken();
593
       nodeExpr = createNodeExpr(lexer);
557
558
        switch(tok->type) {
559
            case Token::CNAME :
560
                // NameTest
561
                // XXX Namespace: handle namespaces here
562
                if (axisIdentifier ==  LocationStep::ATTRIBUTE_AXIS)
563
                    nodeExpr = new AttributeExpr(tok->value);
564
                else
565
                    nodeExpr = new ElementExpr(tok->value);
566
                break;
567
            default:
568
                lexer.pushBack();
569
                nodeExpr = createNodeExpr(lexer);
570
                if(!nodeExpr) {
571
                    delete lstep;
572
                    return 0;
573
                }
574
        }
594
    }
575
    }
595
576
    
577
    lstep->setAxisIdentifier(axisIdentifier);
596
    lstep->setNodeExpr(nodeExpr);
578
    lstep->setNodeExpr(nodeExpr);
597
579
598
599
600
    //-- handle predicates
580
    //-- handle predicates
601
581
    if(!parsePredicates(lstep, lexer)) {
602
    parsePredicates(lstep, lexer);
582
        delete lstep;
603
583
        return 0;
604
    //<debug>
584
    }
605
    //String tmp;
606
    //lstep->toString(tmp);
607
    //cout << "returning LocationStep: "<< tmp <<endl;
608
    //</debug>
609
585
610
    return lstep;
586
    return lstep;
611
} //-- createLocationPath
587
} //-- createLocationPath
 Lines 616-663    Link Here 
616
**/
592
**/
617
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
593
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
618
594
619
    //cout << "creating NodeExpr: "<<endl;
620
    if (!lexer.hasMoreTokens() )  cout << "Lexer has no Tokens"<<endl;
621
622
    if (!lexer.hasMoreTokens() )  return 0;
623
624
    NodeExpr* nodeExpr = 0;
595
    NodeExpr* nodeExpr = 0;
625
626
    Token* tok = lexer.nextToken();
627
    //cout << "Token #" << tok->type <<endl;
628
    List params;
629
596
630
    String* errMsg = 0;
597
    Token* nodeTok = lexer.nextToken();
631
598
632
    switch ( tok->type ) {
599
    switch ( nodeTok->type ) {
633
        case Token::COMMENT:
600
        case Token::COMMENT:
634
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
601
            nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
635
            errMsg = parseParameters(&params, lexer);
636
            //-- ignore errMsg for now
637
            delete errMsg;
638
            break;
602
            break;
639
        case Token::NODE :
603
        case Token::NODE :
640
            nodeExpr = new BasicNodeExpr();
604
            nodeExpr = new BasicNodeExpr();
641
            errMsg = parseParameters(&params, lexer);
642
            //-- ignore errMsg for now
643
            delete errMsg;
644
            break;
605
            break;
645
        case Token::PI :
606
        case Token::PI :
646
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
607
            nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
647
            errMsg = parseParameters(&params, lexer);
648
            //-- ignore errMsg for now
649
            delete errMsg;
650
            break;
608
            break;
651
        case Token::TEXT :
609
        case Token::TEXT :
652
            nodeExpr = new TextExpr();
610
            nodeExpr = new TextExpr();
653
            errMsg = parseParameters(&params, lexer);
654
            //-- ignore errMsg for now
655
            delete errMsg;
656
            break;
611
            break;
657
        default:
612
        default:
658
            //XXXX ignore error for now
613
            lexer.pushBack();
614
            // XXX ErrorReport: unexpected token
615
            return 0;
659
            break;
616
            break;
660
    }
617
    }
618
619
    if ( lexer.nextToken()->type != Token::L_PAREN ) {
620
        lexer.pushBack();
621
        //XXX ErrorReport: left parenthesis expected
622
        delete nodeExpr;
623
        return 0;
624
    }
625
    if ( nodeTok->type == Token::PI && lexer.peek()->type == Token::LITERAL ) {
626
        Token* tok = lexer.nextToken();
627
        ((BasicNodeExpr*)nodeExpr)->setNodeName(tok->value);
628
    }
629
    if ( lexer.nextToken()->type != Token::R_PAREN ) {
630
        lexer.pushBack();
631
        //XXX ErrorReport: right parenthesis expected (or literal for pi)
632
        delete nodeExpr;
633
        return 0;
634
    }
635
    
636
        
661
    return nodeExpr;
637
    return nodeExpr;
662
} //-- createNodeExpr
638
} //-- createNodeExpr
663
639
 Lines 665-701    Link Here 
665
 * Creates a PathExpr using the given ExprLexer
641
 * Creates a PathExpr using the given ExprLexer
666
 * @param lexer the ExprLexer for retrieving Tokens
642
 * @param lexer the ExprLexer for retrieving Tokens
667
**/
643
**/
668
PathExpr* ExprParser::createPathExpr(ExprLexer& lexer) {
644
Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
669
645
646
    Expr* expr = 0;
670
647
671
    //-- check for RootExpr
648
    Token* tok = lexer.peek();
672
    if ( lexer.countRemainingTokens() == 1 ) {
649
673
        if ( lexer.peek()->type == Token::PARENT_OP ) {
650
    // is this a root expression?
674
            lexer.nextToken(); //-- eat token
651
    if ( tok->type == Token::PARENT_OP ) {
675
            return new RootExpr();
652
        lexer.nextToken();
676
        }
653
        if ( !isLocationStepToken(lexer.peek()) )
654
            return new RootExpr;
655
656
        lexer.pushBack();
677
    }
657
    }
678
658
679
    PathExpr* pathExpr = new PathExpr();
659
    // parse first step (possibly a FilterExpr)
680
    short ancestryOp = PathExpr::RELATIVE_OP;
660
    if ( tok->type != Token::PARENT_OP &&
661
         tok->type != Token::ANCESTOR_OP ) {
662
        if ( isFilterExprToken(tok) ) {
663
            expr = createFilterExpr(lexer);
664
        }
665
        else
666
            expr = createLocationStep(lexer);
681
667
682
    while ( lexer.hasMoreTokens() ) {
668
        if ( !expr ) {
683
        Token* tok = lexer.nextToken();
669
            return 0;
684
        if ( lexer.isOperatorToken(tok) ) {
685
            lexer.pushBack();
686
            return pathExpr;
687
        }
670
        }
671
        
672
        // is this a singlestep path expression?
673
        tok = lexer.peek();
674
        if ( tok->type != Token::PARENT_OP &&
675
             tok->type != Token::ANCESTOR_OP)
676
            return expr;
677
    }
678
    
679
    //we have a pathexpression containing several steps
680
    PathExpr* pathExpr = new PathExpr();
681
    if(expr)
682
        pathExpr->addExpr(expr, PathExpr::RELATIVE_OP);
683
684
    // this is ugly
685
    while (1) {
686
        short ancestryOp;
687
        tok = lexer.nextToken();
688
        switch ( tok->type ) {
688
        switch ( tok->type ) {
689
            case Token::R_PAREN:
690
            case Token::R_BRACKET:
691
            case Token::UNION_OP:
692
                //Marina, addition start
693
                // When parsing a list of parameters for a function comma should signal a spot
694
                // without it further processing pathExpr was causing "invalid token" error
695
            case Token::COMMA:
696
                // Marina, addition ends
697
                lexer.pushBack();
698
                return pathExpr;
699
            case Token::ANCESTOR_OP :
689
            case Token::ANCESTOR_OP :
700
                ancestryOp = PathExpr::ANCESTOR_OP;
690
                ancestryOp = PathExpr::ANCESTOR_OP;
701
                break;
691
                break;
 Lines 704-786    Link Here 
704
                break;
694
                break;
705
            default:
695
            default:
706
                lexer.pushBack();
696
                lexer.pushBack();
707
                pathExpr->addPatternExpr(createPatternExpr(lexer), ancestryOp);
697
                return pathExpr;
708
                ancestryOp = PathExpr::RELATIVE_OP;
698
        }
709
                break;
699
        
700
        expr = createLocationStep(lexer);
701
        if ( !expr ) {
702
            delete pathExpr;
703
            return 0;
710
        }
704
        }
705
        
706
        pathExpr->addExpr(expr, ancestryOp);
711
    }
707
    }
712
708
713
    /* <debug> *
714
    String tmp;
715
    pathExpr->toString(tmp);
716
    cout << "creating pathExpr: " << tmp << endl;
717
    /* </debug> */
718
719
    return pathExpr;
709
    return pathExpr;
720
} //-- createPathExpr
710
} //-- createPathExpr
721
711
722
/**
712
/**
723
 * Creates a PatternExpr using the given ExprLexer
713
 * Creates a PathExpr using the given ExprLexer
714
 * XXX temporary use as top of XSLT Pattern
724
 * @param lexer the ExprLexer for retrieving Tokens
715
 * @param lexer the ExprLexer for retrieving Tokens
725
**/
716
**/
726
PatternExpr* ExprParser::createPatternExpr(ExprLexer& lexer) {
717
Expr* ExprParser::createUnionExpr(ExprLexer& lexer) {
727
718
728
    PatternExpr* pExpr = 0;
719
    if (lexer.peek()->type == Token::ERROR) {
729
    Token* tok = lexer.peek();
720
      // XXX Error notification of caller
730
    if ( isLocationStepToken(tok) ) {
721
      return 0;
731
        pExpr = createLocationStep(lexer);
732
    }
722
    }
733
    else if ( isFilterExprToken(tok) ) {
734
        pExpr = createFilterExpr(lexer);
735
    }
736
    else {
737
        cout << "invalid token: " << tok->value << endl;
738
        //-- eat token for now
739
        lexer.nextToken();
740
    }
741
    return pExpr;
742
} //-- createPatternExpr
743
723
744
/**
724
    Expr* expr = createPathExpr(lexer);
745
 * Creates a PathExpr using the given ExprLexer
725
    if(!expr)
746
 * @param lexer the ExprLexer for retrieving Tokens
726
        return 0;
747
**/
727
    
748
UnionExpr* ExprParser::createUnionExpr(ExprLexer& lexer) {
728
    if ( lexer.peek()->type != Token::UNION_OP )
729
        return expr;
730
749
    UnionExpr* unionExpr = new UnionExpr();
731
    UnionExpr* unionExpr = new UnionExpr();
732
    unionExpr->addExpr(expr);
750
733
751
    while ( lexer.hasMoreTokens() ) {
734
    while ( lexer.peek()->type == Token::UNION_OP ) {
752
        Token* tok = lexer.nextToken();
735
        lexer.nextToken(); //-- eat token
753
        switch ( tok->type ) {
754
736
755
            case Token::R_PAREN:
737
        expr = createPathExpr(lexer);
756
            case Token::R_BRACKET:
738
        if ( !expr ) {
757
                lexer.pushBack();
739
            delete unionExpr;
758
                return unionExpr;
740
            return 0;
759
            case Token::UNION_OP :
760
                //-- eat token
761
                break;
762
            default:
763
                lexer.pushBack();
764
                unionExpr->addPathExpr(createPathExpr(lexer));
765
                break;
766
        }
741
        }
742
        unionExpr->addExpr(expr);
767
    }
743
    }
768
    //String tmp;
744
769
    //unionExpr->toString(tmp);
770
    //cout << "creating UnionExpr: " << tmp << endl;
771
    return unionExpr;
745
    return unionExpr;
772
} //-- createUnionExpr
746
} //-- createUnionExpr
773
747
774
MBool ExprParser::isFilterExprToken(Token* token) {
748
MBool ExprParser::isFilterExprToken(Token* token) {
775
    if ( !token ) return MB_FALSE;
776
    switch (token->type) {
749
    switch (token->type) {
777
        case Token::LITERAL:
750
        case Token::LITERAL:
778
        case Token::NUMBER:
751
        case Token::NUMBER:
779
        case Token::FUNCTION_NAME:
752
        case Token::FUNCTION_NAME:
780
        case Token::VAR_REFERENCE:
753
        case Token::VAR_REFERENCE:
781
        case Token::L_PAREN:            // grouping expr
754
        case Token::L_PAREN:            // grouping expr
782
        case Token::PARENT_NODE:
783
        case Token::SELF_NODE :
784
            return MB_TRUE;
755
            return MB_TRUE;
785
        default:
756
        default:
786
            return MB_FALSE;
757
            return MB_FALSE;
 Lines 788-802    Link Here 
788
} //-- isFilterExprToken
759
} //-- isFilterExprToken
789
760
790
MBool ExprParser::isLocationStepToken(Token* token) {
761
MBool ExprParser::isLocationStepToken(Token* token) {
791
    if (!token) return MB_FALSE;
762
    switch (token->type) {
792
    return ((token->type == Token::AXIS_IDENTIFIER) || isNodeTypeToken(token));
763
        case Token::AXIS_IDENTIFIER :
764
        case Token::AT_SIGN :
765
        case Token::PARENT_NODE :
766
        case Token::SELF_NODE :
767
            return MB_TRUE;
768
        default:
769
            return isNodeTypeToken(token);
770
    }
793
} //-- isLocationStepToken
771
} //-- isLocationStepToken
794
772
795
MBool ExprParser::isNodeTypeToken(Token* token) {
773
MBool ExprParser::isNodeTypeToken(Token* token) {
796
    if (!token) return MB_FALSE;
797
798
    switch ( token->type ) {
774
    switch ( token->type ) {
799
        case Token::AT_SIGN:
800
        case Token::CNAME:
775
        case Token::CNAME:
801
        case Token::COMMENT:
776
        case Token::COMMENT:
802
        case Token::NODE :
777
        case Token::NODE :
 Lines 806-812    Link Here 
806
        default:
781
        default:
807
            return MB_FALSE;
782
            return MB_FALSE;
808
    }
783
    }
809
} //-- isLocationStepToken
784
} //-- isNodeTypeToken
810
785
811
/**
786
/**
812
 * Using the given lexer, parses the tokens if they represent a predicate list
787
 * Using the given lexer, parses the tokens if they represent a predicate list
 Lines 816-858    Link Here 
816
 * @param lexer the ExprLexer to use for parsing tokens
791
 * @param lexer the ExprLexer to use for parsing tokens
817
 * @return 0 if successful, or a String pointer to the error message
792
 * @return 0 if successful, or a String pointer to the error message
818
**/
793
**/
819
String* ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
794
MBool ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
820
795
821
    String* errorMsg = 0;
796
    String* errorMsg = 0;
822
823
    Token* tok = lexer.peek();
824
825
    if ( !tok ) return 0; //-- no predicates
826
    if ( tok->type != Token::L_BRACKET ) return 0; //-- not start of predicate list
827
797
828
    lexer.nextToken();
798
    while ( lexer.peek()->type == Token::L_BRACKET ) {
799
        //-- eat Token
800
        lexer.nextToken();
829
801
830
    while ( lexer.hasMoreTokens() ) {
802
        Expr* expr = createExpr(lexer);
831
        tok = lexer.peek();
803
        if(!expr)
832
        if(!tok) {
804
            return MB_FALSE;
833
            //-- error missing ']'
834
            errorMsg = new String("missing close of predicate expression ']'");
835
            break;
836
        }
837
        if ( tok->type == Token::R_BRACKET) {
838
            lexer.nextToken(); //-- eat ']'
839
805
806
        predicateList->add(expr);
840
807
841
            //-- Fix: look ahead at next token for mulitple predicates - Marina M.
808
        if(lexer.nextToken()->type != Token::R_BRACKET) {
842
            tok = lexer.peek();
809
            lexer.pushBack();
843
            if ((!tok) || ( tok->type != Token::L_BRACKET )) break;
810
            //XXX ErrorReport: right bracket expected
844
            //-- /Fix
811
            return MB_FALSE;
845
        }
812
        }
846
813
847
        //-- Fix: handle multiple predicates - Marina M.
848
        if (tok->type == Token::L_BRACKET)
849
            lexer.nextToken(); //-- swallow '['
850
        //-- /Fix
851
852
        Expr* expr = createExpr(lexer);
853
        predicateList->add(expr);
854
    }
814
    }
855
    return errorMsg;
815
    return MB_TRUE;
856
816
857
} //-- parsePredicates
817
} //-- parsePredicates
858
818
 Lines 863-910    Link Here 
863
 * error message.
823
 * error message.
864
 * @param list, the List to add parameter expressions to
824
 * @param list, the List to add parameter expressions to
865
 * @param lexer the ExprLexer to use for parsing tokens
825
 * @param lexer the ExprLexer to use for parsing tokens
866
 * @return 0 if successful, or a String pointer to the error message
826
 * @return MB_TRUE if successful, or a MB_FALSE otherwise
867
**/
827
**/
868
String* ExprParser::parseParameters(List* list, ExprLexer& lexer) {
828
MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer) {
869
870
    String* errorMsg = 0;
871
829
872
    Token* tok = lexer.peek();
830
    if ( lexer.nextToken()->type != Token::L_PAREN ) {
873
831
        lexer.pushBack();
874
    if ( !tok ) return 0; //-- no params
832
        //XXX ErrorReport: left parenthesis expected
875
    if ( tok->type != Token::L_PAREN ) return 0; //-- not start of param list
833
        return MB_FALSE;
834
    }
876
835
877
    lexer.nextToken(); //-- eat L_PAREN
836
    if( lexer.peek()->type == Token::R_PAREN ) {
837
        lexer.nextToken();
838
        return MB_TRUE;
839
    }
878
840
879
    MBool done     = MB_FALSE;
841
    while ( 1 ) {
880
    MBool foundSep = MB_FALSE;
842
        Expr* expr = createExpr(lexer);
843
        if(!expr)
844
            return MB_FALSE;
881
845
882
    while ( lexer.hasMoreTokens() && !done) {
846
        fnCall->addParam(expr);
883
        tok = lexer.peek();
847
            
884
        switch ( tok->type ) {
848
        switch ( lexer.nextToken()->type ) {
885
            case Token::R_PAREN :
849
            case Token::R_PAREN :
886
                if (foundSep) errorMsg = new String("missing expression after ','");
850
                return MB_TRUE;
887
                lexer.nextToken(); //-- eat R_PAREN
888
                done = MB_TRUE;
889
                break;
890
            case Token::COMMA: //-- param separator
851
            case Token::COMMA: //-- param separator
891
                //-- eat COMMA
892
                lexer.nextToken();
893
                foundSep = MB_TRUE;
894
                break;
852
                break;
895
            default:
853
            default:
896
                if ((list->getLength() > 0) && (!foundSep)) {
854
                lexer.pushBack();
897
                    errorMsg = new String("missing ',' or ')'");
855
                //XXX ErrorReport: right parenthesis or comma expected
898
                    done = MB_TRUE;
856
                return MB_FALSE;
899
                    break;
900
                }
901
                foundSep = MB_FALSE;
902
                Expr* expr = createExpr(lexer);
903
                list->add(expr);
904
                break;
905
        }
857
        }
906
    }
858
    }
907
    return errorMsg;
859
860
    return MB_FALSE;
908
861
909
} //-- parseParameters
862
} //-- parseParameters
910
863
(-)ExprParser.h (-10 / +6 lines)
Line     Link Here 
 Lines 44-52    Link Here 
44
44
45
public:
45
public:
46
46
47
    static const String R_CURLY_BRACE;
48
    static const String L_CURLY_BRACE;
49
50
    /**
47
    /**
51
     * Creates a new ExprParser
48
     * Creates a new ExprParser
52
    **/
49
    **/
 Lines 58-64    Link Here 
58
    ~ExprParser();
55
    ~ExprParser();
59
56
60
    Expr*          createExpr        (const String& pattern);
57
    Expr*          createExpr        (const String& pattern);
61
    PatternExpr*   createPatternExpr (const String& pattern);
58
    Expr*          createPatternExpr (const String& pattern);
62
    LocationStep*  createLocationStep(const String& path);
59
    LocationStep*  createLocationStep(const String& path);
63
60
64
    /**
61
    /**
 Lines 72-84    Link Here 
72
69
73
    Expr*          createBinaryExpr   (Expr* left, Expr* right, Token* op);
70
    Expr*          createBinaryExpr   (Expr* left, Expr* right, Token* op);
74
    Expr*          createExpr         (ExprLexer& lexer);
71
    Expr*          createExpr         (ExprLexer& lexer);
75
    FilterExpr*    createFilterExpr   (ExprLexer& lexer);
72
    Expr*          createFilterExpr   (ExprLexer& lexer);
76
    FunctionCall*  createFunctionCall (ExprLexer& lexer);
73
    FunctionCall*  createFunctionCall (ExprLexer& lexer);
77
    LocationStep*  createLocationStep (ExprLexer& lexer);
74
    LocationStep*  createLocationStep (ExprLexer& lexer);
78
    NodeExpr*      createNodeExpr     (ExprLexer& lexer);
75
    NodeExpr*      createNodeExpr     (ExprLexer& lexer);
79
    PathExpr*      createPathExpr     (ExprLexer& lexer);
76
    Expr*          createPathExpr     (ExprLexer& lexer);
80
    PatternExpr*   createPatternExpr  (ExprLexer& lexer);
77
    Expr*          createUnionExpr    (ExprLexer& lexer);
81
    UnionExpr*     createUnionExpr    (ExprLexer& lexer);
82
78
83
    MBool          isFilterExprToken   (Token* tok);
79
    MBool          isFilterExprToken   (Token* tok);
84
    MBool          isLocationStepToken (Token* tok);
80
    MBool          isLocationStepToken (Token* tok);
 Lines 94-101    Link Here 
94
     * @param lexer the ExprLexer to use for parsing tokens
90
     * @param lexer the ExprLexer to use for parsing tokens
95
     * @return 0 if successful, or a String pointer to the error message
91
     * @return 0 if successful, or a String pointer to the error message
96
    **/
92
    **/
97
    String* parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
93
    MBool parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
98
    String* parseParameters(List* list, ExprLexer& lexer);
94
    MBool parseParameters(FunctionCall* fnCall, ExprLexer& lexer);
99
95
100
96
101
}; //-- ExprParser
97
}; //-- ExprParser
(-)FunctionCall.cpp (+25 lines)
Line     Link Here 
 Lines 101-106    Link Here 
101
} //-- addParam
101
} //-- addParam
102
102
103
/**
103
/**
104
 * Returns the default priority of this Expr based on the given Node,
105
 * context Node, and ContextState.
106
**/
107
double FunctionCall::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
108
    return 0.5;
109
} //-- getDefaultPriority
110
111
/**
112
 * Determines whether this Expr matches the given node within
113
 * the given context
114
**/
115
MBool FunctionCall::matches(Node* node, Node* context, ContextState* cs) {
116
117
    MBool result = MB_FALSE;
118
    ExprResult* exprResult = evaluate(node, cs);
119
    if ( exprResult->getResultType() == ExprResult::NODESET ) {
120
        NodeSet* nodes = (NodeSet*)exprResult;
121
        result = (nodes->contains(node));
122
    }
123
    delete exprResult;
124
    return result;
125
126
} //-- matches
127
128
/**
104
 * Evaluates the given Expression and converts it's result to a String.
129
 * Evaluates the given Expression and converts it's result to a String.
105
 * The value is appended to the given destination String
130
 * The value is appended to the given destination String
106
**/
131
**/
(-)Makefile (-2 / +8 lines)
Line     Link Here 
 Lines 23-39    Link Here 
23
             BooleanExpr.o \
23
             BooleanExpr.o \
24
             BooleanResult.o \
24
             BooleanResult.o \
25
             ElementExpr.o \
25
             ElementExpr.o \
26
             Expr.o \
26
             ExprLexer.o \
27
             ExprLexer.o \
27
             ExprParser.o \
28
             ExprParser.o \
28
             FilterExpr.o \
29
             FilterExpr.o \
29
             IdentityExpr.o \
30
             LocationStep.o \
30
             LocationStep.o \
31
             MultiplicativeExpr.o \
31
             MultiplicativeExpr.o \
32
             NodeSet.o \
32
             NodeSet.o \
33
             NumberExpr.o \
33
             NumberExpr.o \
34
             NumberResult.o \
34
             NumberResult.o \
35
             PredicateList.o \
35
             PredicateList.o \
36
             ParentExpr.o \
37
             PathExpr.o \
36
             PathExpr.o \
38
             RelationalExpr.o \
37
             RelationalExpr.o \
39
             RootExpr.o \
38
             RootExpr.o \
 Lines 41-46    Link Here 
41
             StringResult.o \
40
             StringResult.o \
42
	         TextExpr.o \
41
	         TextExpr.o \
43
             UnionExpr.o \
42
             UnionExpr.o \
43
             UnaryExpr.o \
44
             VariableRefExpr.o \
44
             VariableRefExpr.o \
45
             XPathNames.o
45
             XPathNames.o
46
46
 Lines 80-85    Link Here 
80
ElementExpr.o: Expr.h ElementExpr.cpp
80
ElementExpr.o: Expr.h ElementExpr.cpp
81
	$(CC) $(INCLUDE_PATHS) -c ElementExpr.cpp
81
	$(CC) $(INCLUDE_PATHS) -c ElementExpr.cpp
82
82
83
Expr.o: Expr.cpp Expr.h
84
	$(CC) $(INCLUDE_PATHS) -c Expr.cpp
85
83
ExprLexer.o: ExprLexer.cpp ExprLexer.h
86
ExprLexer.o: ExprLexer.cpp ExprLexer.h
84
	$(CC) $(INCLUDE_PATHS) -c ExprLexer.cpp
87
	$(CC) $(INCLUDE_PATHS) -c ExprLexer.cpp
85
88
 Lines 133-138    Link Here 
133
136
134
UnionExpr.o: Expr.h UnionExpr.cpp
137
UnionExpr.o: Expr.h UnionExpr.cpp
135
	$(CC) $(INCLUDE_PATHS) -c UnionExpr.cpp
138
	$(CC) $(INCLUDE_PATHS) -c UnionExpr.cpp
139
140
UnaryExpr.o: Expr.h UnaryExpr.cpp
141
	$(CC) $(INCLUDE_PATHS) -c UnaryExpr.cpp
136
142
137
VariableRefExpr.o: Expr.h VariableRefExpr.cpp
143
VariableRefExpr.o: Expr.h VariableRefExpr.cpp
138
	$(CC) $(INCLUDE_PATHS) -c VariableRefExpr.cpp
144
	$(CC) $(INCLUDE_PATHS) -c VariableRefExpr.cpp
(-)Makefile.in (-2 / +2 lines)
Line     Link Here 
 Lines 35-46    Link Here 
35
        BooleanResult.cpp \
35
        BooleanResult.cpp \
36
        ElementExpr.cpp \
36
        ElementExpr.cpp \
37
        ErrorFunctionCall.cpp \
37
        ErrorFunctionCall.cpp \
38
        Expr.cpp \
38
        ExprLexer.cpp \
39
        ExprLexer.cpp \
39
        ExprParser.cpp \
40
        ExprParser.cpp \
40
        ExtensionFunctionCall.cpp \
41
        ExtensionFunctionCall.cpp \
41
        FilterExpr.cpp \
42
        FilterExpr.cpp \
42
        FunctionCall.cpp \
43
        FunctionCall.cpp \
43
        IdentityExpr.cpp \
44
        LocationStep.cpp \
44
        LocationStep.cpp \
45
        MultiplicativeExpr.cpp \
45
        MultiplicativeExpr.cpp \
46
        NodeSet.cpp \
46
        NodeSet.cpp \
 Lines 48-54    Link Here 
48
        NumberExpr.cpp \
48
        NumberExpr.cpp \
49
        NumberFunctionCall.cpp \
49
        NumberFunctionCall.cpp \
50
        NumberResult.cpp \
50
        NumberResult.cpp \
51
        ParentExpr.cpp \
52
        PathExpr.cpp \
51
        PathExpr.cpp \
53
        PredicateList.cpp \
52
        PredicateList.cpp \
54
        RelationalExpr.cpp \
53
        RelationalExpr.cpp \
 Lines 58-63    Link Here 
58
        StringResult.cpp \
57
        StringResult.cpp \
59
        TextExpr.cpp \
58
        TextExpr.cpp \
60
        UnionExpr.cpp \
59
        UnionExpr.cpp \
60
        UnaryExpr.cpp \
61
        VariableRefExpr.cpp \
61
        VariableRefExpr.cpp \
62
        XPathNames.cpp
62
        XPathNames.cpp
63
ifdef MOZ_XSL
63
ifdef MOZ_XSL
(-)PathExpr.cpp (-68 / +71 lines)
Line     Link Here 
 Lines 47-87    Link Here 
47
}
47
}
48
48
49
/**
49
/**
50
 * Destructor, will delete all Pattern Expressions
50
 * Destructor, will delete all Expressions
51
**/
51
**/
52
PathExpr::~PathExpr() {
52
PathExpr::~PathExpr() {
53
    ListIterator* iter = expressions.iterator();
53
    ListIterator* iter = expressions.iterator();
54
    while ( iter->hasNext() ) {
54
    while ( iter->hasNext() ) {
55
         iter->next();
55
         iter->next();
56
         PathExprItem* pxi = (PathExprItem*)iter->remove();
56
         PathExprItem* pxi = (PathExprItem*)iter->remove();
57
         delete pxi->pExpr;
57
         delete pxi->expr;
58
         delete pxi;
58
         delete pxi;
59
    }
59
    }
60
    delete iter;
60
    delete iter;
61
} //-- ~PathExpr
61
} //-- ~PathExpr
62
62
63
/**
63
/**
64
 * Adds the PatternExpr to this PathExpr
64
 * Adds the Expr to this PathExpr
65
 * @param expr the Expr to add to this PathExpr
65
 * @param expr the Expr to add to this PathExpr
66
 * @param index the index at which to add the given Expr
66
 * @param index the index at which to add the given Expr
67
**/
67
**/
68
void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp) {
68
void PathExpr::addExpr(int index, Expr* expr, short ancestryOp) {
69
    if (expr) {
69
    if (expr) {
70
        PathExprItem* pxi = new PathExprItem;
70
        PathExprItem* pxi = new PathExprItem;
71
        pxi->pExpr = expr;
71
        pxi->expr = expr;
72
        pxi->ancestryOp = ancestryOp;
72
        pxi->ancestryOp = ancestryOp;
73
        expressions.insert(index, pxi);
73
        expressions.insert(index, pxi);
74
    }
74
    }
75
} //-- addPattenExpr
75
} //-- addPattenExpr
76
76
77
/**
77
/**
78
 * Adds the PatternExpr to this PathExpr
78
 * Adds the Expr to this PathExpr
79
 * @param expr the Expr to add to this PathExpr
79
 * @param expr the Expr to add to this PathExpr
80
**/
80
**/
81
void PathExpr::addPatternExpr(PatternExpr* expr, short ancestryOp) {
81
void PathExpr::addExpr(Expr* expr, short ancestryOp) {
82
    if (expr) {
82
    if (expr) {
83
        PathExprItem* pxi = new PathExprItem;
83
        PathExprItem* pxi = new PathExprItem;
84
        pxi->pExpr = expr;
84
        pxi->expr = expr;
85
        pxi->ancestryOp = ancestryOp;
85
        pxi->ancestryOp = ancestryOp;
86
        expressions.add(pxi);
86
        expressions.add(pxi);
87
    }
87
    }
 Lines 97-105    Link Here 
97
    return MB_FALSE;
97
    return MB_FALSE;
98
} //-- isAbsolute
98
} //-- isAbsolute
99
99
100
    //------------------------------------/
100
    //-----------------------------/
101
  //- Virtual methods from PatternExpr -/
101
  //- Virtual methods from Expr -/
102
//------------------------------------/
102
//-----------------------------/
103
103
104
/**
104
/**
105
 * Evaluates this Expr based on the given context node and processor state
105
 * Evaluates this Expr based on the given context node and processor state
 Lines 124-156    Link Here 
124
124
125
    ListIterator* iter = expressions.iterator();
125
    ListIterator* iter = expressions.iterator();
126
126
127
    MBool ancestorMode = MB_FALSE;
128
    while ( iter->hasNext() ) {
127
    while ( iter->hasNext() ) {
129
128
130
        PathExprItem* pxi = (PathExprItem*)iter->next();
129
        PathExprItem* pxi = (PathExprItem*)iter->next();
131
        ancestorMode = (ancestorMode || (pxi->ancestryOp == ANCESTOR_OP));
132
        NodeSet* tmpNodes = 0;
130
        NodeSet* tmpNodes = 0;
133
        cs->getNodeSetStack()->push(nodes);
131
        cs->getNodeSetStack()->push(nodes);
134
        for (int i = 0; i < nodes->size(); i++) {
132
        for (int i = 0; i < nodes->size(); i++) {
135
            Node* node = nodes->get(i);
133
            Node* node = nodes->get(i);
136
#if 0
134
            
137
            NodeSet* xNodes = (NodeSet*) pxi->pExpr->evaluate(node, cs);
135
            NodeSet* resNodes;
138
#else
136
            if ( pxi->ancestryOp == ANCESTOR_OP) {
139
           ExprResult *res = pxi->pExpr->evaluate(node, cs);
137
                resNodes = new NodeSet;
140
           if (!res || res->getResultType() != ExprResult::NODESET)
138
                evalDescendants(pxi->expr, node, cs, resNodes);
141
               continue;
142
            NodeSet* xNodes = (NodeSet *) res;
143
#endif
144
            if ( tmpNodes ) {
145
                xNodes->copyInto(*tmpNodes);
146
            }
139
            }
147
            else {
140
            else {
148
                tmpNodes = xNodes;
141
                ExprResult *res = pxi->expr->evaluate(node, cs);
149
                xNodes = 0;
142
                if (!res || res->getResultType() != ExprResult::NODESET) {
143
                    //XXX ErrorReport: report nonnodeset error
144
                    delete res;
145
                    res = new NodeSet;
146
                }
147
148
                resNodes = (NodeSet*)res;
150
            }
149
            }
151
            delete xNodes;
150
152
            //-- handle ancestorMode
151
            if ( tmpNodes ) {
153
            if ( ancestorMode ) fromDescendants(pxi->pExpr, node, cs, tmpNodes);
152
                resNodes->copyInto(*tmpNodes);
153
                delete resNodes;
154
            }
155
            else
156
                tmpNodes = resNodes;
157
154
        }
158
        }
155
        delete (NodeSet*) cs->getNodeSetStack()->pop();
159
        delete (NodeSet*) cs->getNodeSetStack()->pop();
156
        nodes = tmpNodes;
160
        nodes = tmpNodes;
 Lines 163-213    Link Here 
163
167
164
/**
168
/**
165
 * Selects from the descendants of the context node
169
 * Selects from the descendants of the context node
166
 * all nodes that match the PatternExpr
170
 * all nodes that match the Expr
167
 * -- this will be moving to a Utility class
171
 * -- this will be moving to a Utility class
168
**/
172
**/
169
void PathExpr::fromDescendants
173
void PathExpr::evalDescendants
170
    (PatternExpr* pExpr, Node* context, ContextState* cs, NodeSet* nodes)
174
    (Expr* expr, Node* context, ContextState* cs, NodeSet* resNodes)
171
{
175
{
172
176
173
    if (( !context ) || (! pExpr )) return;
177
    ExprResult *res = expr->evaluate(context, cs);
174
178
    if (!res || res->getResultType() != ExprResult::NODESET) {
175
    NodeList* nl = context->getChildNodes();
179
        //XXX ErrorReport: report nonnodeset error
176
    for (UInt32 i = 0; i < nl->getLength(); i++) {
180
    }
177
        Node* child = nl->item(i);
181
    ((NodeSet*)res)->copyInto(*resNodes);
178
        if (pExpr->matches(child, context, cs))
182
    delete res;
179
            nodes->add(child);
183
    
180
        //-- check childs descendants
184
    Node* child = context->getFirstChild();
181
        if (child->hasChildNodes())
185
    while(child) {
182
            fromDescendants(pExpr, child, cs, nodes);
186
        //XXX WhiteSpace: filter whitespace nodes
187
        evalDescendants(expr, child, cs, resNodes);
188
        child = child->getNextSibling();
183
    }
189
    }
190
    
191
184
} //-- fromDescendants
192
} //-- fromDescendants
185
193
186
/**
194
/**
187
 * Returns the default priority of this Pattern based on the given Node,
195
 * Returns the default priority of this Expr based on the given Node,
188
 * context Node, and ContextState.
196
 * context Node, and ContextState.
189
 * If this pattern does not match the given Node under the current context Node and
190
 * ContextState then Negative Infinity is returned.
191
**/
197
**/
192
double PathExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
198
double PathExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
193
199
194
    if ( matches(node, context, cs) ) {
200
    int size = expressions.getLength();
195
        int size = expressions.getLength();
201
    if ( size > 1 || isAbsolute() ) {
196
        if ( size == 1) {
202
        return 0.5;
197
            ListIterator* iter = expressions.iterator();
198
            PathExprItem* pxi = (PathExprItem*)iter->next();
199
            delete iter;
200
            return pxi->pExpr->getDefaultPriority(node, context, cs);
201
        }
202
        else if ( size > 1 ) {
203
            return 0.5;
204
        }
205
    }
203
    }
206
    return Double::NEGATIVE_INFINITY;
204
205
    ListIterator* iter = expressions.iterator();
206
    PathExprItem* pxi = (PathExprItem*)iter->next();
207
    delete iter;
208
    return pxi->expr->getDefaultPriority(node, context, cs);
209
207
} //-- getDefaultPriority
210
} //-- getDefaultPriority
208
211
209
/**
212
/**
210
 * Determines whether this PatternExpr matches the given node within
213
 * Determines whether this Expr matches the given node within
211
 * the given context
214
 * the given context
212
**/
215
**/
213
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
216
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
 Lines 231-237    Link Here 
231
            {
234
            {
232
                Node* ancestor = node;
235
                Node* ancestor = node;
233
                while (ancestor = cs->getParentNode(ancestor))  {
236
                while (ancestor = cs->getParentNode(ancestor))  {
234
                    if (pxi->pExpr->matches(node, ancestor, cs))
237
                    if (pxi->expr->matches(node, ancestor, cs))
235
                        return MB_TRUE;
238
                        return MB_TRUE;
236
                }
239
                }
237
                break;
240
                break;
 Lines 242-253    Link Here 
242
                if (parent) {
245
                if (parent) {
243
                    //-- make sure node is Document node
246
                    //-- make sure node is Document node
244
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
247
                    if (parent->getNodeType() == Node::DOCUMENT_NODE)
245
                        return pxi->pExpr->matches(node, parent, cs);
248
                        return pxi->expr->matches(node, parent, cs);
246
                }
249
                }
247
                break;
250
                break;
248
            }
251
            }
249
            default:
252
            default:
250
                return pxi->pExpr->matches(node, context, cs);
253
                return pxi->expr->matches(node, context, cs);
251
254
252
        }
255
        }
253
256
 Lines 280-286    Link Here 
280
                {
283
                {
281
                    Node* parent = tnode;
284
                    Node* parent = tnode;
282
                    while (parent = cs->getParentNode(parent))  {
285
                    while (parent = cs->getParentNode(parent))  {
283
                        if (pxi->pExpr->matches(tnode, parent, cs))
286
                        if (pxi->expr->matches(tnode, parent, cs))
284
                            tmpNodes.add(parent);
287
                            tmpNodes.add(parent);
285
                    }
288
                    }
286
                    break;
289
                    break;
 Lines 294-300    Link Here 
294
                        if ( !iter->hasNext() )
297
                        if ( !iter->hasNext() )
295
                            if (parent->getNodeType() != Node::DOCUMENT_NODE) break;
298
                            if (parent->getNodeType() != Node::DOCUMENT_NODE) break;
296
299
297
                        if (pxi->pExpr->matches(tnode, parent, cs))
300
                        if (pxi->expr->matches(tnode, parent, cs))
298
                            tmpNodes.add(parent);
301
                            tmpNodes.add(parent);
299
                    }
302
                    }
300
                    break;
303
                    break;
 Lines 303-317    Link Here 
303
                    if ( !iter->hasNext() ) {
306
                    if ( !iter->hasNext() ) {
304
307
305
                        /*
308
                        /*
306
                          // PREVIOUS // result = pxi->pExpr->matches(tnode, context, cs);
309
                          // PREVIOUS // result = pxi->expr->matches(tnode, context, cs);
307
                          // result was being overwritten if there was more than one
310
                          // result was being overwritten if there was more than one
308
                          // node in nodes during the final iteration  (Marina)
311
                          // node in nodes during the final iteration  (Marina)
309
312
310
                          result = result || pxi->pExpr->matches(tnode, context, cs)
313
                          result = result || pxi->expr->matches(tnode, context, cs)
311
                        */
314
                        */
312
315
313
                        //-- Just return true if we match here
316
                        //-- Just return true if we match here
314
                        if (pxi->pExpr->matches(tnode, context, cs)) {
317
                        if (pxi->expr->matches(tnode, context, cs)) {
315
                            delete iter;
318
                            delete iter;
316
                            return MB_TRUE;
319
                            return MB_TRUE;
317
                        }
320
                        }
 Lines 352-363    Link Here 
352
355
353
356
354
/**
357
/**
355
 * Returns the String representation of this PatternExpr.
358
 * Returns the String representation of this Expr.
356
 * @param dest the String to use when creating the String
359
 * @param dest the String to use when creating the String
357
 * representation. The String representation will be appended to
360
 * representation. The String representation will be appended to
358
 *  any data in the destination String, to allow cascading calls to
361
 *  any data in the destination String, to allow cascading calls to
359
 * other #toString() methods for Expressions.
362
 * other #toString() methods for Expressions.
360
 * @return the String representation of this PatternExpr.
363
 * @return the String representation of this Expr.
361
**/
364
**/
362
void PathExpr::toString(String& dest) {
365
void PathExpr::toString(String& dest) {
363
    ListIterator* iter = expressions.iterator();
366
    ListIterator* iter = expressions.iterator();
 Lines 374-380    Link Here 
374
            default:
377
            default:
375
                break;
378
                break;
376
        }
379
        }
377
        pxi->pExpr->toString(dest);
380
        pxi->expr->toString(dest);
378
    }
381
    }
379
    delete iter;
382
    delete iter;
380
} //-- toString
383
} //-- toString
(-)StringExpr.cpp (-2 / +5 lines)
Line     Link Here 
 Lines 72-79    Link Here 
72
 * @return the String representation of this Expr.
72
 * @return the String representation of this Expr.
73
**/
73
**/
74
void StringExpr::toString(String& str) {
74
void StringExpr::toString(String& str) {
75
    str.append('\'');
75
    UNICODE_CHAR ch = '\'';
76
    if ( value.indexOf(ch) != NOT_FOUND )
77
        ch = '\"';
78
    str.append(ch);
76
    str.append(value);
79
    str.append(value);
77
    str.append('\'');
80
    str.append(ch);
78
} //-- toString
81
} //-- toString
79
82
(-)UnionExpr.cpp (-25 / +24 lines)
Line     Link Here 
 Lines 45-73    Link Here 
45
    ListIterator* iter = expressions.iterator();
45
    ListIterator* iter = expressions.iterator();
46
    while ( iter->hasNext() ) {
46
    while ( iter->hasNext() ) {
47
         iter->next();
47
         iter->next();
48
         delete  (PathExpr*)iter->remove();
48
         delete  (Expr*)iter->remove();
49
    }
49
    }
50
    delete iter;
50
    delete iter;
51
} //-- ~UnionExpr
51
} //-- ~UnionExpr
52
52
53
/**
53
/**
54
 * Adds the PathExpr to this UnionExpr
54
 * Adds the Expr to this UnionExpr
55
 * @param pathExpr the PathExpr to add to this UnionExpr
55
 * @param expr the Expr to add to this UnionExpr
56
**/
56
**/
57
void UnionExpr::addPathExpr(PathExpr* pathExpr) {
57
void UnionExpr::addExpr(Expr* expr) {
58
    if (pathExpr) expressions.add(pathExpr);
58
    if (expr) expressions.add(expr);
59
} //-- addPathExpr
59
} //-- addExpr
60
60
61
/**
61
/**
62
 * Adds the PathExpr to this UnionExpr
62
 * Adds the Expr to this UnionExpr
63
 * @param pathExpr the PathExpr to add to this UnionExpr
63
 * @param expr the Expr to add to this UnionExpr
64
**/
64
**/
65
void UnionExpr::addPathExpr(int index, PathExpr* pathExpr) {
65
void UnionExpr::addExpr(int index, Expr* expr) {
66
    if (pathExpr) expressions.insert(index, pathExpr);
66
    if (expr) expressions.insert(index, expr);
67
} //-- addPathExpr
67
} //-- addExpr
68
68
69
    //------------------------------------/
69
    //------------------------------------/
70
  //- Virtual methods from PatternExpr -/
70
  //- Virtual methods from Expr -/
71
//------------------------------------/
71
//------------------------------------/
72
72
73
/**
73
/**
 Lines 88-99    Link Here 
88
88
89
    while ( iter->hasNext() ) {
89
    while ( iter->hasNext() ) {
90
90
91
        PathExpr* pExpr = (PathExpr*)iter->next();
91
        Expr* expr = (Expr*)iter->next();
92
        NodeSet* tmpNodes = (NodeSet*)pExpr->evaluate(context, cs);
92
        ExprResult* exprResult = expr->evaluate(context, cs);
93
        for (int j = 0; j < tmpNodes->size(); j++) {
93
        if ( exprResult->getResultType() == ExprResult::NODESET ) {
94
            nodes->add(tmpNodes->get(j));
94
            ((NodeSet*)exprResult)->copyInto(*nodes);
95
        }
95
        }
96
        delete tmpNodes;
97
    }
96
    }
98
97
99
    delete iter;
98
    delete iter;
 Lines 112-120    Link Here 
112
    double priority = Double::NEGATIVE_INFINITY;
111
    double priority = Double::NEGATIVE_INFINITY;
113
    ListIterator* iter = expressions.iterator();
112
    ListIterator* iter = expressions.iterator();
114
    while ( iter->hasNext() ) {
113
    while ( iter->hasNext() ) {
115
        PathExpr* pExpr = (PathExpr*)iter->next();
114
        Expr* expr = (Expr*)iter->next();
116
        if ( pExpr->matches(node, context, cs) ) {
115
        if ( expr->matches(node, context, cs) ) {
117
            double tmpPriority = pExpr->getDefaultPriority(node, context, cs);
116
            double tmpPriority = expr->getDefaultPriority(node, context, cs);
118
            priority = (tmpPriority > priority) ? tmpPriority : priority;
117
            priority = (tmpPriority > priority) ? tmpPriority : priority;
119
        }
118
        }
120
    }
119
    }
 Lines 132-139    Link Here 
132
    ListIterator* iter = expressions.iterator();
131
    ListIterator* iter = expressions.iterator();
133
132
134
    while ( iter->hasNext() ) {
133
    while ( iter->hasNext() ) {
135
        PathExpr* pExpr = (PathExpr*)iter->next();
134
        Expr* expr = (Expr*)iter->next();
136
        if ( pExpr->matches(node, context, cs) ) {
135
        if ( expr->matches(node, context, cs) ) {
137
             delete iter;
136
             delete iter;
138
             return MB_TRUE;
137
             return MB_TRUE;
139
        }
138
        }
 Lines 144-155    Link Here 
144
143
145
144
146
/**
145
/**
147
 * Returns the String representation of this PatternExpr.
146
 * Returns the String representation of this Expr.
148
 * @param dest the String to use when creating the String
147
 * @param dest the String to use when creating the String
149
 * representation. The String representation will be appended to
148
 * representation. The String representation will be appended to
150
 *  any data in the destination String, to allow cascading calls to
149
 *  any data in the destination String, to allow cascading calls to
151
 * other #toString() methods for Expressions.
150
 * other #toString() methods for Expressions.
152
 * @return the String representation of this PatternExpr.
151
 * @return the String representation of this Expr.
153
**/
152
**/
154
void UnionExpr::toString(String& dest) {
153
void UnionExpr::toString(String& dest) {
155
    ListIterator* iter = expressions.iterator();
154
    ListIterator* iter = expressions.iterator();
 Lines 158-164    Link Here 
158
    while ( iter->hasNext() ) {
157
    while ( iter->hasNext() ) {
159
        //-- set operator
158
        //-- set operator
160
        if (count > 0) dest.append(" | ");
159
        if (count > 0) dest.append(" | ");
161
        ((PathExpr*)iter->next())->toString(dest);
160
        ((Expr*)iter->next())->toString(dest);
162
        ++count;
161
        ++count;
163
    }
162
    }
164
    delete iter;
163
    delete iter;
(-)makefile.win (-4 / +4 lines)
Line     Link Here 
 Lines 35-46    Link Here 
35
	BooleanResult.cpp		\
35
	BooleanResult.cpp		\
36
	ElementExpr.cpp			\
36
	ElementExpr.cpp			\
37
	ErrorFunctionCall.cpp		\
37
	ErrorFunctionCall.cpp		\
38
	Expr.cpp			\
38
	ExprLexer.cpp			\
39
	ExprLexer.cpp			\
39
	ExprParser.cpp			\
40
	ExprParser.cpp			\
40
	ExtensionFunctionCall.cpp	\
41
	ExtensionFunctionCall.cpp	\
41
	FilterExpr.cpp			\
42
	FilterExpr.cpp			\
42
	FunctionCall.cpp		\
43
	FunctionCall.cpp		\
43
	IdentityExpr.cpp		\
44
	LocationStep.cpp		\
44
	LocationStep.cpp		\
45
	MultiplicativeExpr.cpp		\
45
	MultiplicativeExpr.cpp		\
46
	NodeSet.cpp			\
46
	NodeSet.cpp			\
 Lines 48-54    Link Here 
48
	NumberExpr.cpp			\
48
	NumberExpr.cpp			\
49
	NumberFunctionCall.cpp		\
49
	NumberFunctionCall.cpp		\
50
	NumberResult.cpp		\
50
	NumberResult.cpp		\
51
	ParentExpr.cpp			\
52
	PathExpr.cpp			\
51
	PathExpr.cpp			\
53
	PredicateList.cpp		\
52
	PredicateList.cpp		\
54
	RelationalExpr.cpp		\
53
	RelationalExpr.cpp		\
 Lines 58-63    Link Here 
58
	StringResult.cpp		\
57
	StringResult.cpp		\
59
	TextExpr.cpp			\
58
	TextExpr.cpp			\
60
	UnionExpr.cpp			\
59
	UnionExpr.cpp			\
60
	UnaryExpr.cpp			\
61
	VariableRefExpr.cpp		\
61
	VariableRefExpr.cpp		\
62
	XPathNames.cpp			\
62
	XPathNames.cpp			\
63
!if defined(MOZ_XSL)
63
!if defined(MOZ_XSL)
 Lines 76-87    Link Here 
76
	.\$(OBJDIR)\BooleanResult.obj			\
76
	.\$(OBJDIR)\BooleanResult.obj			\
77
	.\$(OBJDIR)\ElementExpr.obj			\
77
	.\$(OBJDIR)\ElementExpr.obj			\
78
	.\$(OBJDIR)\ErrorFunctionCall.obj		\
78
	.\$(OBJDIR)\ErrorFunctionCall.obj		\
79
	.\$(OBJDIR)\Expr.obj				\
79
	.\$(OBJDIR)\ExprLexer.obj			\
80
	.\$(OBJDIR)\ExprLexer.obj			\
80
	.\$(OBJDIR)\ExprParser.obj			\
81
	.\$(OBJDIR)\ExprParser.obj			\
81
	.\$(OBJDIR)\ExtensionFunctionCall.obj		\
82
	.\$(OBJDIR)\ExtensionFunctionCall.obj		\
82
	.\$(OBJDIR)\FilterExpr.obj			\
83
	.\$(OBJDIR)\FilterExpr.obj			\
83
	.\$(OBJDIR)\FunctionCall.obj			\
84
	.\$(OBJDIR)\FunctionCall.obj			\
84
	.\$(OBJDIR)\IdentityExpr.obj			\
85
	.\$(OBJDIR)\LocationStep.obj			\
85
	.\$(OBJDIR)\LocationStep.obj			\
86
	.\$(OBJDIR)\MultiplicativeExpr.obj		\
86
	.\$(OBJDIR)\MultiplicativeExpr.obj		\
87
	.\$(OBJDIR)\NodeSet.obj				\
87
	.\$(OBJDIR)\NodeSet.obj				\
 Lines 89-95    Link Here 
89
	.\$(OBJDIR)\NumberExpr.obj			\
89
	.\$(OBJDIR)\NumberExpr.obj			\
90
	.\$(OBJDIR)\NumberFunctionCall.obj		\
90
	.\$(OBJDIR)\NumberFunctionCall.obj		\
91
	.\$(OBJDIR)\NumberResult.obj			\
91
	.\$(OBJDIR)\NumberResult.obj			\
92
	.\$(OBJDIR)\ParentExpr.obj			\
93
	.\$(OBJDIR)\PathExpr.obj			\
92
	.\$(OBJDIR)\PathExpr.obj			\
94
	.\$(OBJDIR)\PredicateList.obj			\
93
	.\$(OBJDIR)\PredicateList.obj			\
95
	.\$(OBJDIR)\RelationalExpr.obj			\
94
	.\$(OBJDIR)\RelationalExpr.obj			\
 Lines 99-104    Link Here 
99
	.\$(OBJDIR)\StringResult.obj			\
98
	.\$(OBJDIR)\StringResult.obj			\
100
	.\$(OBJDIR)\TextExpr.obj			\
99
	.\$(OBJDIR)\TextExpr.obj			\
101
	.\$(OBJDIR)\UnionExpr.obj			\
100
	.\$(OBJDIR)\UnionExpr.obj			\
101
	.\$(OBJDIR)\UnaryExpr.obj			\
102
	.\$(OBJDIR)\VariableRefExpr.obj			\
102
	.\$(OBJDIR)\VariableRefExpr.obj			\
103
	.\$(OBJDIR)\XPathNames.obj			\
103
	.\$(OBJDIR)\XPathNames.obj			\
104
!if defined(MOZ_XSL)
104
!if defined(MOZ_XSL)
(-)ProcessorState.cpp (-2 / +4 lines)
Line     Link Here 
 Lines 197-204    Link Here 
197
        namedTemplates.put(name,mObj);
197
        namedTemplates.put(name,mObj);
198
        if ( oldObj ) delete oldObj;
198
        if ( oldObj ) delete oldObj;
199
    }
199
    }
200
    patternExprHash.put(match, exprParser.createPatternExpr(match));
200
    if ( match.length() > 0 ) {
201
    templates.add(xslTemplate);
201
        patternExprHash.put(match, exprParser.createPatternExpr(match));
202
        templates.add(xslTemplate);
203
    }
202
} //-- addTempalte
204
} //-- addTempalte
203
205
204
/**
206
/**

Return to bug 75102