Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /**
7 : * ExprParser
8 : * This class is used to parse XSL Expressions
9 : * @see ExprLexer
10 : **/
11 :
12 : #include "mozilla/Move.h"
13 : #include "txExprParser.h"
14 : #include "txExprLexer.h"
15 : #include "txExpr.h"
16 : #include "txStack.h"
17 : #include "nsGkAtoms.h"
18 : #include "nsError.h"
19 : #include "txIXPathContext.h"
20 : #include "txStringUtils.h"
21 : #include "txXPathNode.h"
22 : #include "txXPathOptimizer.h"
23 :
24 : using mozilla::Move;
25 :
26 : /**
27 : * Creates an Attribute Value Template using the given value
28 : * This should move to XSLProcessor class
29 : */
30 : nsresult
31 0 : txExprParser::createAVT(const nsAString& aAttrValue,
32 : txIParseContext* aContext,
33 : Expr** aResult)
34 : {
35 0 : *aResult = nullptr;
36 0 : nsresult rv = NS_OK;
37 0 : nsAutoPtr<Expr> expr;
38 0 : FunctionCall* concat = nullptr;
39 :
40 0 : nsAutoString literalString;
41 0 : bool inExpr = false;
42 : nsAString::const_char_iterator iter, start, end, avtStart;
43 0 : aAttrValue.BeginReading(iter);
44 0 : aAttrValue.EndReading(end);
45 0 : avtStart = iter;
46 :
47 0 : while (iter != end) {
48 : // Every iteration through this loop parses either a literal section
49 : // or an expression
50 0 : start = iter;
51 0 : nsAutoPtr<Expr> newExpr;
52 0 : if (!inExpr) {
53 : // Parse literal section
54 0 : literalString.Truncate();
55 0 : while (iter != end) {
56 0 : char16_t q = *iter;
57 0 : if (q == '{' || q == '}') {
58 : // Store what we've found so far and set a new |start| to
59 : // skip the (first) brace
60 0 : literalString.Append(Substring(start, iter));
61 0 : start = ++iter;
62 : // Unless another brace follows we've found the start of
63 : // an expression (in case of '{') or an unbalanced brace
64 : // (in case of '}')
65 0 : if (iter == end || *iter != q) {
66 0 : if (q == '}') {
67 0 : aContext->SetErrorOffset(iter - avtStart);
68 0 : return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
69 : }
70 :
71 0 : inExpr = true;
72 0 : break;
73 : }
74 : // We found a second brace, let that be part of the next
75 : // literal section being parsed and continue looping
76 : }
77 0 : ++iter;
78 : }
79 :
80 0 : if (start == iter && literalString.IsEmpty()) {
81 : // Restart the loop since we didn't create an expression
82 0 : continue;
83 : }
84 0 : newExpr = new txLiteralExpr(literalString +
85 0 : Substring(start, iter));
86 : }
87 : else {
88 : // Parse expressions, iter is already past the initial '{' when
89 : // we get here.
90 0 : while (iter != end) {
91 0 : if (*iter == '}') {
92 0 : rv = createExprInternal(Substring(start, iter),
93 0 : start - avtStart, aContext,
94 0 : getter_Transfers(newExpr));
95 0 : NS_ENSURE_SUCCESS(rv, rv);
96 :
97 0 : inExpr = false;
98 0 : ++iter; // skip closing '}'
99 0 : break;
100 : }
101 0 : else if (*iter == '\'' || *iter == '"') {
102 0 : char16_t q = *iter;
103 0 : while (++iter != end && *iter != q) {} /* do nothing */
104 0 : if (iter == end) {
105 0 : break;
106 : }
107 : }
108 0 : ++iter;
109 : }
110 :
111 0 : if (inExpr) {
112 0 : aContext->SetErrorOffset(start - avtStart);
113 0 : return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
114 : }
115 : }
116 :
117 : // Add expression, create a concat() call if necessary
118 0 : if (!expr) {
119 0 : expr = Move(newExpr);
120 : }
121 : else {
122 0 : if (!concat) {
123 0 : concat = new txCoreFunctionCall(txCoreFunctionCall::CONCAT);
124 0 : rv = concat->addParam(expr.forget());
125 0 : expr = concat;
126 0 : NS_ENSURE_SUCCESS(rv, rv);
127 : }
128 :
129 0 : rv = concat->addParam(newExpr.forget());
130 0 : NS_ENSURE_SUCCESS(rv, rv);
131 : }
132 : }
133 :
134 0 : if (inExpr) {
135 0 : aContext->SetErrorOffset(iter - avtStart);
136 0 : return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
137 : }
138 :
139 0 : if (!expr) {
140 0 : expr = new txLiteralExpr(EmptyString());
141 : }
142 :
143 0 : *aResult = expr.forget();
144 :
145 0 : return NS_OK;
146 : }
147 :
148 : nsresult
149 0 : txExprParser::createExprInternal(const nsAString& aExpression,
150 : uint32_t aSubStringPos,
151 : txIParseContext* aContext, Expr** aExpr)
152 : {
153 0 : NS_ENSURE_ARG_POINTER(aExpr);
154 0 : *aExpr = nullptr;
155 0 : txExprLexer lexer;
156 0 : nsresult rv = lexer.parse(aExpression);
157 0 : if (NS_FAILED(rv)) {
158 : nsAString::const_char_iterator start;
159 0 : aExpression.BeginReading(start);
160 0 : aContext->SetErrorOffset(lexer.mPosition - start + aSubStringPos);
161 0 : return rv;
162 : }
163 0 : nsAutoPtr<Expr> expr;
164 0 : rv = createExpr(lexer, aContext, getter_Transfers(expr));
165 0 : if (NS_SUCCEEDED(rv) && lexer.peek()->mType != Token::END) {
166 0 : rv = NS_ERROR_XPATH_BINARY_EXPECTED;
167 : }
168 0 : if (NS_FAILED(rv)) {
169 : nsAString::const_char_iterator start;
170 0 : aExpression.BeginReading(start);
171 0 : aContext->SetErrorOffset(lexer.peek()->mStart - start + aSubStringPos);
172 :
173 0 : return rv;
174 : }
175 :
176 : txXPathOptimizer optimizer;
177 0 : Expr* newExpr = nullptr;
178 0 : rv = optimizer.optimize(expr, &newExpr);
179 0 : NS_ENSURE_SUCCESS(rv, rv);
180 :
181 0 : *aExpr = newExpr ? newExpr : expr.forget();
182 :
183 0 : return NS_OK;
184 : }
185 :
186 : /**
187 : * Private Methods
188 : */
189 :
190 : /**
191 : * Creates a binary Expr for the given operator
192 : */
193 : nsresult
194 0 : txExprParser::createBinaryExpr(nsAutoPtr<Expr>& left, nsAutoPtr<Expr>& right,
195 : Token* op, Expr** aResult)
196 : {
197 0 : NS_ASSERTION(op, "internal error");
198 0 : *aResult = nullptr;
199 :
200 0 : Expr* expr = nullptr;
201 0 : switch (op->mType) {
202 : //-- math ops
203 : case Token::ADDITION_OP :
204 0 : expr = new txNumberExpr(left, right, txNumberExpr::ADD);
205 0 : break;
206 : case Token::SUBTRACTION_OP:
207 0 : expr = new txNumberExpr(left, right, txNumberExpr::SUBTRACT);
208 0 : break;
209 : case Token::DIVIDE_OP :
210 0 : expr = new txNumberExpr(left, right, txNumberExpr::DIVIDE);
211 0 : break;
212 : case Token::MODULUS_OP :
213 0 : expr = new txNumberExpr(left, right, txNumberExpr::MODULUS);
214 0 : break;
215 : case Token::MULTIPLY_OP :
216 0 : expr = new txNumberExpr(left, right, txNumberExpr::MULTIPLY);
217 0 : break;
218 :
219 : //-- case boolean ops
220 : case Token::AND_OP:
221 0 : expr = new BooleanExpr(left, right, BooleanExpr::AND);
222 0 : break;
223 : case Token::OR_OP:
224 0 : expr = new BooleanExpr(left, right, BooleanExpr::OR);
225 0 : break;
226 :
227 : //-- equality ops
228 : case Token::EQUAL_OP :
229 0 : expr = new RelationalExpr(left, right, RelationalExpr::EQUAL);
230 0 : break;
231 : case Token::NOT_EQUAL_OP :
232 0 : expr = new RelationalExpr(left, right, RelationalExpr::NOT_EQUAL);
233 0 : break;
234 :
235 : //-- relational ops
236 : case Token::LESS_THAN_OP:
237 0 : expr = new RelationalExpr(left, right, RelationalExpr::LESS_THAN);
238 0 : break;
239 : case Token::GREATER_THAN_OP:
240 0 : expr = new RelationalExpr(left, right,
241 0 : RelationalExpr::GREATER_THAN);
242 0 : break;
243 : case Token::LESS_OR_EQUAL_OP:
244 0 : expr = new RelationalExpr(left, right,
245 0 : RelationalExpr::LESS_OR_EQUAL);
246 0 : break;
247 : case Token::GREATER_OR_EQUAL_OP:
248 0 : expr = new RelationalExpr(left, right,
249 0 : RelationalExpr::GREATER_OR_EQUAL);
250 0 : break;
251 :
252 : default:
253 0 : NS_NOTREACHED("operator tokens should be already checked");
254 0 : return NS_ERROR_UNEXPECTED;
255 : }
256 0 : NS_ENSURE_TRUE(expr, NS_ERROR_OUT_OF_MEMORY);
257 :
258 0 : left.forget();
259 0 : right.forget();
260 :
261 0 : *aResult = expr;
262 0 : return NS_OK;
263 : }
264 :
265 :
266 : nsresult
267 0 : txExprParser::createExpr(txExprLexer& lexer, txIParseContext* aContext,
268 : Expr** aResult)
269 : {
270 0 : *aResult = nullptr;
271 :
272 0 : nsresult rv = NS_OK;
273 0 : bool done = false;
274 :
275 0 : nsAutoPtr<Expr> expr;
276 :
277 0 : txStack exprs;
278 0 : txStack ops;
279 :
280 0 : while (!done) {
281 :
282 0 : uint16_t negations = 0;
283 0 : while (lexer.peek()->mType == Token::SUBTRACTION_OP) {
284 0 : negations++;
285 0 : lexer.nextToken();
286 : }
287 :
288 0 : rv = createUnionExpr(lexer, aContext, getter_Transfers(expr));
289 0 : if (NS_FAILED(rv)) {
290 0 : break;
291 : }
292 :
293 0 : if (negations > 0) {
294 0 : if (negations % 2 == 0) {
295 0 : FunctionCall* fcExpr = new txCoreFunctionCall(txCoreFunctionCall::NUMBER);
296 :
297 0 : rv = fcExpr->addParam(expr);
298 0 : if (NS_FAILED(rv))
299 0 : return rv;
300 0 : expr.forget();
301 0 : expr = fcExpr;
302 : }
303 : else {
304 0 : expr = new UnaryExpr(expr.forget());
305 : }
306 : }
307 :
308 0 : short tokPrecedence = precedence(lexer.peek());
309 0 : if (tokPrecedence != 0) {
310 0 : Token* tok = lexer.nextToken();
311 0 : while (!exprs.isEmpty() && tokPrecedence
312 0 : <= precedence(static_cast<Token*>(ops.peek()))) {
313 : // can't use expr as argument due to order of evaluation
314 0 : nsAutoPtr<Expr> left(static_cast<Expr*>(exprs.pop()));
315 0 : nsAutoPtr<Expr> right(Move(expr));
316 0 : rv = createBinaryExpr(left, right,
317 0 : static_cast<Token*>(ops.pop()),
318 0 : getter_Transfers(expr));
319 0 : if (NS_FAILED(rv)) {
320 0 : done = true;
321 0 : break;
322 : }
323 : }
324 0 : exprs.push(expr.forget());
325 0 : ops.push(tok);
326 : }
327 : else {
328 0 : done = true;
329 : }
330 : }
331 :
332 0 : while (NS_SUCCEEDED(rv) && !exprs.isEmpty()) {
333 0 : nsAutoPtr<Expr> left(static_cast<Expr*>(exprs.pop()));
334 0 : nsAutoPtr<Expr> right(Move(expr));
335 0 : rv = createBinaryExpr(left, right, static_cast<Token*>(ops.pop()),
336 0 : getter_Transfers(expr));
337 : }
338 : // clean up on error
339 0 : while (!exprs.isEmpty()) {
340 0 : delete static_cast<Expr*>(exprs.pop());
341 : }
342 0 : NS_ENSURE_SUCCESS(rv, rv);
343 :
344 0 : *aResult = expr.forget();
345 0 : return NS_OK;
346 : }
347 :
348 : nsresult
349 0 : txExprParser::createFilterOrStep(txExprLexer& lexer, txIParseContext* aContext,
350 : Expr** aResult)
351 : {
352 0 : *aResult = nullptr;
353 :
354 0 : nsresult rv = NS_OK;
355 0 : Token* tok = lexer.peek();
356 :
357 0 : nsAutoPtr<Expr> expr;
358 0 : switch (tok->mType) {
359 : case Token::FUNCTION_NAME_AND_PAREN:
360 0 : rv = createFunctionCall(lexer, aContext, getter_Transfers(expr));
361 0 : NS_ENSURE_SUCCESS(rv, rv);
362 0 : break;
363 : case Token::VAR_REFERENCE :
364 0 : lexer.nextToken();
365 : {
366 0 : nsCOMPtr<nsIAtom> prefix, lName;
367 : int32_t nspace;
368 0 : nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
369 0 : aContext, getter_AddRefs(lName),
370 0 : nspace);
371 0 : NS_ENSURE_SUCCESS(rv, rv);
372 0 : expr = new VariableRefExpr(prefix, lName, nspace);
373 : }
374 0 : break;
375 : case Token::L_PAREN:
376 0 : lexer.nextToken();
377 0 : rv = createExpr(lexer, aContext, getter_Transfers(expr));
378 0 : NS_ENSURE_SUCCESS(rv, rv);
379 :
380 0 : if (lexer.peek()->mType != Token::R_PAREN) {
381 0 : return NS_ERROR_XPATH_PAREN_EXPECTED;
382 : }
383 0 : lexer.nextToken();
384 0 : break;
385 : case Token::LITERAL :
386 0 : lexer.nextToken();
387 0 : expr = new txLiteralExpr(tok->Value());
388 0 : break;
389 : case Token::NUMBER:
390 : {
391 0 : lexer.nextToken();
392 0 : expr = new txLiteralExpr(txDouble::toDouble(tok->Value()));
393 0 : break;
394 : }
395 : default:
396 0 : return createLocationStep(lexer, aContext, aResult);
397 : }
398 :
399 0 : if (lexer.peek()->mType == Token::L_BRACKET) {
400 0 : nsAutoPtr<FilterExpr> filterExpr(new FilterExpr(expr));
401 :
402 0 : expr.forget();
403 :
404 : //-- handle predicates
405 0 : rv = parsePredicates(filterExpr, lexer, aContext);
406 0 : NS_ENSURE_SUCCESS(rv, rv);
407 0 : expr = filterExpr.forget();
408 : }
409 :
410 0 : *aResult = expr.forget();
411 0 : return NS_OK;
412 : }
413 :
414 : nsresult
415 0 : txExprParser::createFunctionCall(txExprLexer& lexer, txIParseContext* aContext,
416 : Expr** aResult)
417 : {
418 0 : *aResult = nullptr;
419 :
420 0 : nsAutoPtr<FunctionCall> fnCall;
421 :
422 0 : Token* tok = lexer.nextToken();
423 0 : NS_ASSERTION(tok->mType == Token::FUNCTION_NAME_AND_PAREN,
424 : "FunctionCall expected");
425 :
426 : //-- compare function names
427 0 : nsCOMPtr<nsIAtom> prefix, lName;
428 : int32_t namespaceID;
429 0 : nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
430 0 : getter_AddRefs(lName), namespaceID);
431 0 : NS_ENSURE_SUCCESS(rv, rv);
432 :
433 : txCoreFunctionCall::eType type;
434 0 : if (namespaceID == kNameSpaceID_None &&
435 0 : txCoreFunctionCall::getTypeFromAtom(lName, type)) {
436 : // It is a known built-in function.
437 0 : fnCall = new txCoreFunctionCall(type);
438 : }
439 :
440 : // check extension functions and xslt
441 0 : if (!fnCall) {
442 0 : rv = aContext->resolveFunctionCall(lName, namespaceID,
443 0 : getter_Transfers(fnCall));
444 :
445 0 : if (rv == NS_ERROR_NOT_IMPLEMENTED) {
446 : // this should just happen for unparsed-entity-uri()
447 0 : NS_ASSERTION(!fnCall, "Now is it implemented or not?");
448 0 : rv = parseParameters(0, lexer, aContext);
449 0 : NS_ENSURE_SUCCESS(rv, rv);
450 :
451 0 : *aResult = new txLiteralExpr(tok->Value() +
452 0 : NS_LITERAL_STRING(" not implemented."));
453 :
454 0 : return NS_OK;
455 : }
456 :
457 0 : NS_ENSURE_SUCCESS(rv, rv);
458 : }
459 :
460 : //-- handle parametes
461 0 : rv = parseParameters(fnCall, lexer, aContext);
462 0 : NS_ENSURE_SUCCESS(rv, rv);
463 :
464 0 : *aResult = fnCall.forget();
465 0 : return NS_OK;
466 : }
467 :
468 : nsresult
469 0 : txExprParser::createLocationStep(txExprLexer& lexer, txIParseContext* aContext,
470 : Expr** aExpr)
471 : {
472 0 : *aExpr = nullptr;
473 :
474 : //-- child axis is default
475 0 : LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS;
476 0 : nsAutoPtr<txNodeTest> nodeTest;
477 :
478 : //-- get Axis Identifier or AbbreviatedStep, if present
479 0 : Token* tok = lexer.peek();
480 0 : switch (tok->mType) {
481 : case Token::AXIS_IDENTIFIER:
482 : {
483 : //-- eat token
484 0 : lexer.nextToken();
485 0 : nsCOMPtr<nsIAtom> axis = NS_Atomize(tok->Value());
486 0 : if (axis == nsGkAtoms::ancestor) {
487 0 : axisIdentifier = LocationStep::ANCESTOR_AXIS;
488 : }
489 0 : else if (axis == nsGkAtoms::ancestorOrSelf) {
490 0 : axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
491 : }
492 0 : else if (axis == nsGkAtoms::attribute) {
493 0 : axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
494 : }
495 0 : else if (axis == nsGkAtoms::child) {
496 0 : axisIdentifier = LocationStep::CHILD_AXIS;
497 : }
498 0 : else if (axis == nsGkAtoms::descendant) {
499 0 : axisIdentifier = LocationStep::DESCENDANT_AXIS;
500 : }
501 0 : else if (axis == nsGkAtoms::descendantOrSelf) {
502 0 : axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
503 : }
504 0 : else if (axis == nsGkAtoms::following) {
505 0 : axisIdentifier = LocationStep::FOLLOWING_AXIS;
506 : }
507 0 : else if (axis == nsGkAtoms::followingSibling) {
508 0 : axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
509 : }
510 0 : else if (axis == nsGkAtoms::_namespace) {
511 0 : axisIdentifier = LocationStep::NAMESPACE_AXIS;
512 : }
513 0 : else if (axis == nsGkAtoms::parent) {
514 0 : axisIdentifier = LocationStep::PARENT_AXIS;
515 : }
516 0 : else if (axis == nsGkAtoms::preceding) {
517 0 : axisIdentifier = LocationStep::PRECEDING_AXIS;
518 : }
519 0 : else if (axis == nsGkAtoms::precedingSibling) {
520 0 : axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
521 : }
522 0 : else if (axis == nsGkAtoms::self) {
523 0 : axisIdentifier = LocationStep::SELF_AXIS;
524 : }
525 : else {
526 0 : return NS_ERROR_XPATH_INVALID_AXIS;
527 : }
528 0 : break;
529 : }
530 : case Token::AT_SIGN:
531 : //-- eat token
532 0 : lexer.nextToken();
533 0 : axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
534 0 : break;
535 : case Token::PARENT_NODE :
536 : //-- eat token
537 0 : lexer.nextToken();
538 0 : axisIdentifier = LocationStep::PARENT_AXIS;
539 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
540 0 : break;
541 : case Token::SELF_NODE :
542 : //-- eat token
543 0 : lexer.nextToken();
544 0 : axisIdentifier = LocationStep::SELF_AXIS;
545 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
546 0 : break;
547 : default:
548 0 : break;
549 : }
550 :
551 : //-- get NodeTest unless an AbbreviatedStep was found
552 0 : nsresult rv = NS_OK;
553 0 : if (!nodeTest) {
554 0 : tok = lexer.peek();
555 :
556 0 : if (tok->mType == Token::CNAME) {
557 0 : lexer.nextToken();
558 : // resolve QName
559 0 : nsCOMPtr<nsIAtom> prefix, lName;
560 : int32_t nspace;
561 0 : rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
562 0 : aContext, getter_AddRefs(lName),
563 0 : nspace, true);
564 0 : NS_ENSURE_SUCCESS(rv, rv);
565 :
566 : nodeTest =
567 : new txNameTest(prefix, lName, nspace,
568 : axisIdentifier == LocationStep::ATTRIBUTE_AXIS ?
569 : static_cast<uint16_t>(txXPathNodeType::ATTRIBUTE_NODE) :
570 0 : static_cast<uint16_t>(txXPathNodeType::ELEMENT_NODE));
571 : }
572 : else {
573 0 : rv = createNodeTypeTest(lexer, getter_Transfers(nodeTest));
574 0 : NS_ENSURE_SUCCESS(rv, rv);
575 : }
576 : }
577 :
578 0 : nsAutoPtr<LocationStep> lstep(new LocationStep(nodeTest, axisIdentifier));
579 :
580 0 : nodeTest.forget();
581 :
582 : //-- handle predicates
583 0 : rv = parsePredicates(lstep, lexer, aContext);
584 0 : NS_ENSURE_SUCCESS(rv, rv);
585 :
586 0 : *aExpr = lstep.forget();
587 0 : return NS_OK;
588 : }
589 :
590 : /**
591 : * This method only handles comment(), text(), processing-instructing()
592 : * and node()
593 : */
594 : nsresult
595 0 : txExprParser::createNodeTypeTest(txExprLexer& lexer, txNodeTest** aTest)
596 : {
597 0 : *aTest = 0;
598 0 : nsAutoPtr<txNodeTypeTest> nodeTest;
599 :
600 0 : Token* nodeTok = lexer.peek();
601 :
602 0 : switch (nodeTok->mType) {
603 : case Token::COMMENT_AND_PAREN:
604 0 : lexer.nextToken();
605 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE);
606 0 : break;
607 : case Token::NODE_AND_PAREN:
608 0 : lexer.nextToken();
609 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
610 0 : break;
611 : case Token::PROC_INST_AND_PAREN:
612 0 : lexer.nextToken();
613 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE);
614 0 : break;
615 : case Token::TEXT_AND_PAREN:
616 0 : lexer.nextToken();
617 0 : nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE);
618 0 : break;
619 : default:
620 0 : return NS_ERROR_XPATH_NO_NODE_TYPE_TEST;
621 : }
622 :
623 0 : NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY);
624 :
625 0 : if (nodeTok->mType == Token::PROC_INST_AND_PAREN &&
626 0 : lexer.peek()->mType == Token::LITERAL) {
627 0 : Token* tok = lexer.nextToken();
628 0 : nodeTest->setNodeName(tok->Value());
629 : }
630 0 : if (lexer.peek()->mType != Token::R_PAREN) {
631 0 : return NS_ERROR_XPATH_PAREN_EXPECTED;
632 : }
633 0 : lexer.nextToken();
634 :
635 0 : *aTest = nodeTest.forget();
636 0 : return NS_OK;
637 : }
638 :
639 : /**
640 : * Creates a PathExpr using the given txExprLexer
641 : * @param lexer the txExprLexer for retrieving Tokens
642 : */
643 : nsresult
644 0 : txExprParser::createPathExpr(txExprLexer& lexer, txIParseContext* aContext,
645 : Expr** aResult)
646 : {
647 0 : *aResult = nullptr;
648 :
649 0 : nsAutoPtr<Expr> expr;
650 :
651 0 : Token* tok = lexer.peek();
652 :
653 : // is this a root expression?
654 0 : if (tok->mType == Token::PARENT_OP) {
655 0 : if (!isLocationStepToken(lexer.peekAhead())) {
656 0 : lexer.nextToken();
657 0 : *aResult = new RootExpr();
658 0 : return NS_OK;
659 : }
660 : }
661 :
662 : // parse first step (possibly a FilterExpr)
663 0 : nsresult rv = NS_OK;
664 0 : if (tok->mType != Token::PARENT_OP &&
665 0 : tok->mType != Token::ANCESTOR_OP) {
666 0 : rv = createFilterOrStep(lexer, aContext, getter_Transfers(expr));
667 0 : NS_ENSURE_SUCCESS(rv, rv);
668 :
669 : // is this a singlestep path expression?
670 0 : tok = lexer.peek();
671 0 : if (tok->mType != Token::PARENT_OP &&
672 0 : tok->mType != Token::ANCESTOR_OP) {
673 0 : *aResult = expr.forget();
674 0 : return NS_OK;
675 0 : }
676 : }
677 : else {
678 0 : expr = new RootExpr();
679 :
680 : #ifdef TX_TO_STRING
681 0 : static_cast<RootExpr*>(expr.get())->setSerialize(false);
682 : #endif
683 : }
684 :
685 : // We have a PathExpr containing several steps
686 0 : nsAutoPtr<PathExpr> pathExpr(new PathExpr());
687 :
688 0 : rv = pathExpr->addExpr(expr, PathExpr::RELATIVE_OP);
689 0 : NS_ENSURE_SUCCESS(rv, rv);
690 :
691 0 : expr.forget();
692 :
693 : // this is ugly
694 : while (1) {
695 : PathExpr::PathOperator pathOp;
696 0 : switch (lexer.peek()->mType) {
697 : case Token::ANCESTOR_OP :
698 0 : pathOp = PathExpr::DESCENDANT_OP;
699 0 : break;
700 : case Token::PARENT_OP :
701 0 : pathOp = PathExpr::RELATIVE_OP;
702 0 : break;
703 : default:
704 0 : *aResult = pathExpr.forget();
705 0 : return NS_OK;
706 : }
707 0 : lexer.nextToken();
708 :
709 0 : rv = createLocationStep(lexer, aContext, getter_Transfers(expr));
710 0 : NS_ENSURE_SUCCESS(rv, rv);
711 :
712 0 : rv = pathExpr->addExpr(expr, pathOp);
713 0 : NS_ENSURE_SUCCESS(rv, rv);
714 :
715 0 : expr.forget();
716 0 : }
717 : NS_NOTREACHED("internal xpath parser error");
718 : return NS_ERROR_UNEXPECTED;
719 : }
720 :
721 : /**
722 : * Creates a PathExpr using the given txExprLexer
723 : * @param lexer the txExprLexer for retrieving Tokens
724 : */
725 : nsresult
726 0 : txExprParser::createUnionExpr(txExprLexer& lexer, txIParseContext* aContext,
727 : Expr** aResult)
728 : {
729 0 : *aResult = nullptr;
730 :
731 0 : nsAutoPtr<Expr> expr;
732 0 : nsresult rv = createPathExpr(lexer, aContext, getter_Transfers(expr));
733 0 : NS_ENSURE_SUCCESS(rv, rv);
734 :
735 0 : if (lexer.peek()->mType != Token::UNION_OP) {
736 0 : *aResult = expr.forget();
737 0 : return NS_OK;
738 : }
739 :
740 0 : nsAutoPtr<UnionExpr> unionExpr(new UnionExpr());
741 :
742 0 : rv = unionExpr->addExpr(expr);
743 0 : NS_ENSURE_SUCCESS(rv, rv);
744 :
745 0 : expr.forget();
746 :
747 0 : while (lexer.peek()->mType == Token::UNION_OP) {
748 0 : lexer.nextToken(); //-- eat token
749 :
750 0 : rv = createPathExpr(lexer, aContext, getter_Transfers(expr));
751 0 : NS_ENSURE_SUCCESS(rv, rv);
752 :
753 0 : rv = unionExpr->addExpr(expr.forget());
754 0 : NS_ENSURE_SUCCESS(rv, rv);
755 : }
756 :
757 0 : *aResult = unionExpr.forget();
758 0 : return NS_OK;
759 : }
760 :
761 : bool
762 0 : txExprParser::isLocationStepToken(Token* aToken)
763 : {
764 : // We could put these in consecutive order in ExprLexer.h for speed
765 0 : return aToken->mType == Token::AXIS_IDENTIFIER ||
766 0 : aToken->mType == Token::AT_SIGN ||
767 0 : aToken->mType == Token::PARENT_NODE ||
768 0 : aToken->mType == Token::SELF_NODE ||
769 0 : aToken->mType == Token::CNAME ||
770 0 : aToken->mType == Token::COMMENT_AND_PAREN ||
771 0 : aToken->mType == Token::NODE_AND_PAREN ||
772 0 : aToken->mType == Token::PROC_INST_AND_PAREN ||
773 0 : aToken->mType == Token::TEXT_AND_PAREN;
774 : }
775 :
776 : /**
777 : * Using the given lexer, parses the tokens if they represent a predicate list
778 : * If an error occurs a non-zero String pointer will be returned containing the
779 : * error message.
780 : * @param predicateList, the PredicateList to add predicate expressions to
781 : * @param lexer the txExprLexer to use for parsing tokens
782 : * @return 0 if successful, or a String pointer to the error message
783 : */
784 : nsresult
785 0 : txExprParser::parsePredicates(PredicateList* aPredicateList,
786 : txExprLexer& lexer, txIParseContext* aContext)
787 : {
788 0 : nsAutoPtr<Expr> expr;
789 0 : nsresult rv = NS_OK;
790 0 : while (lexer.peek()->mType == Token::L_BRACKET) {
791 : //-- eat Token
792 0 : lexer.nextToken();
793 :
794 0 : rv = createExpr(lexer, aContext, getter_Transfers(expr));
795 0 : NS_ENSURE_SUCCESS(rv, rv);
796 :
797 0 : rv = aPredicateList->add(expr);
798 0 : NS_ENSURE_SUCCESS(rv, rv);
799 :
800 0 : expr.forget();
801 :
802 0 : if (lexer.peek()->mType != Token::R_BRACKET) {
803 0 : return NS_ERROR_XPATH_BRACKET_EXPECTED;
804 : }
805 0 : lexer.nextToken();
806 : }
807 0 : return NS_OK;
808 : }
809 :
810 :
811 : /**
812 : * Using the given lexer, parses the tokens if they represent a parameter list
813 : * If an error occurs a non-zero String pointer will be returned containing the
814 : * error message.
815 : * @param list, the List to add parameter expressions to
816 : * @param lexer the txExprLexer to use for parsing tokens
817 : * @return NS_OK if successful, or another rv otherwise
818 : */
819 : nsresult
820 0 : txExprParser::parseParameters(FunctionCall* aFnCall, txExprLexer& lexer,
821 : txIParseContext* aContext)
822 : {
823 0 : if (lexer.peek()->mType == Token::R_PAREN) {
824 0 : lexer.nextToken();
825 0 : return NS_OK;
826 : }
827 :
828 0 : nsAutoPtr<Expr> expr;
829 0 : nsresult rv = NS_OK;
830 : while (1) {
831 0 : rv = createExpr(lexer, aContext, getter_Transfers(expr));
832 0 : NS_ENSURE_SUCCESS(rv, rv);
833 :
834 0 : if (aFnCall) {
835 0 : rv = aFnCall->addParam(expr.forget());
836 0 : NS_ENSURE_SUCCESS(rv, rv);
837 : }
838 :
839 0 : switch (lexer.peek()->mType) {
840 : case Token::R_PAREN :
841 0 : lexer.nextToken();
842 0 : return NS_OK;
843 : case Token::COMMA: //-- param separator
844 0 : lexer.nextToken();
845 0 : break;
846 : default:
847 0 : return NS_ERROR_XPATH_PAREN_EXPECTED;
848 : }
849 0 : }
850 :
851 : NS_NOTREACHED("internal xpath parser error");
852 : return NS_ERROR_UNEXPECTED;
853 : }
854 :
855 : short
856 0 : txExprParser::precedence(Token* aToken)
857 : {
858 0 : switch (aToken->mType) {
859 : case Token::OR_OP:
860 0 : return 1;
861 : case Token::AND_OP:
862 0 : return 2;
863 : //-- equality
864 : case Token::EQUAL_OP:
865 : case Token::NOT_EQUAL_OP:
866 0 : return 3;
867 : //-- relational
868 : case Token::LESS_THAN_OP:
869 : case Token::GREATER_THAN_OP:
870 : case Token::LESS_OR_EQUAL_OP:
871 : case Token::GREATER_OR_EQUAL_OP:
872 0 : return 4;
873 : //-- additive operators
874 : case Token::ADDITION_OP:
875 : case Token::SUBTRACTION_OP:
876 0 : return 5;
877 : //-- multiplicative
878 : case Token::DIVIDE_OP:
879 : case Token::MULTIPLY_OP:
880 : case Token::MODULUS_OP:
881 0 : return 6;
882 : default:
883 0 : break;
884 : }
885 0 : return 0;
886 : }
887 :
888 : nsresult
889 0 : txExprParser::resolveQName(const nsAString& aQName,
890 : nsIAtom** aPrefix, txIParseContext* aContext,
891 : nsIAtom** aLocalName, int32_t& aNamespace,
892 : bool aIsNameTest)
893 : {
894 0 : aNamespace = kNameSpaceID_None;
895 0 : int32_t idx = aQName.FindChar(':');
896 0 : if (idx > 0) {
897 0 : *aPrefix = NS_Atomize(StringHead(aQName, (uint32_t)idx)).take();
898 0 : if (!*aPrefix) {
899 0 : return NS_ERROR_OUT_OF_MEMORY;
900 : }
901 0 : *aLocalName = NS_Atomize(Substring(aQName, (uint32_t)idx + 1,
902 0 : aQName.Length() - (idx + 1))).take();
903 0 : if (!*aLocalName) {
904 0 : NS_RELEASE(*aPrefix);
905 0 : return NS_ERROR_OUT_OF_MEMORY;
906 : }
907 0 : return aContext->resolveNamespacePrefix(*aPrefix, aNamespace);
908 : }
909 : // the lexer dealt with idx == 0
910 0 : *aPrefix = 0;
911 0 : if (aIsNameTest && aContext->caseInsensitiveNameTests()) {
912 0 : nsAutoString lcname;
913 0 : nsContentUtils::ASCIIToLower(aQName, lcname);
914 0 : *aLocalName = NS_Atomize(lcname).take();
915 : }
916 : else {
917 0 : *aLocalName = NS_Atomize(aQName).take();
918 : }
919 0 : if (!*aLocalName) {
920 0 : return NS_ERROR_OUT_OF_MEMORY;
921 : }
922 0 : return NS_OK;
923 : }
|