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