Bug 1928997: Update tabs icon in Unified Search popup r=desktop-theme-reviewers,daleh...
[gecko.git] / dom / xslt / xpath / txExprParser.cpp
blob93d22bdafd5df9c8b1934adbe102c8cd9d1a7795
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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"
14 #include <utility>
16 #include "mozilla/UniquePtrExtensions.h"
17 #include "nsError.h"
18 #include "nsGkAtoms.h"
19 #include "txExpr.h"
20 #include "txExprLexer.h"
21 #include "txIXPathContext.h"
22 #include "txStack.h"
23 #include "txStringUtils.h"
24 #include "txXPathNode.h"
25 #include "txXPathOptimizer.h"
27 using mozilla::MakeUnique;
28 using mozilla::UniquePtr;
29 using mozilla::Unused;
30 using mozilla::WrapUnique;
32 /**
33 * Creates an Attribute Value Template using the given value
34 * This should move to XSLProcessor class
36 nsresult txExprParser::createAVT(const nsAString& aAttrValue,
37 txIParseContext* aContext, Expr** aResult) {
38 *aResult = nullptr;
39 nsresult rv = NS_OK;
40 UniquePtr<Expr> expr;
41 FunctionCall* concat = nullptr;
43 nsAutoString literalString;
44 bool inExpr = false;
45 nsAString::const_char_iterator iter, start, end, avtStart;
46 aAttrValue.BeginReading(iter);
47 aAttrValue.EndReading(end);
48 avtStart = iter;
50 while (iter != end) {
51 // Every iteration through this loop parses either a literal section
52 // or an expression
53 start = iter;
54 UniquePtr<Expr> newExpr;
55 if (!inExpr) {
56 // Parse literal section
57 literalString.Truncate();
58 while (iter != end) {
59 char16_t q = *iter;
60 if (q == '{' || q == '}') {
61 // Store what we've found so far and set a new |start| to
62 // skip the (first) brace
63 literalString.Append(Substring(start, iter));
64 start = ++iter;
65 // Unless another brace follows we've found the start of
66 // an expression (in case of '{') or an unbalanced brace
67 // (in case of '}')
68 if (iter == end || *iter != q) {
69 if (q == '}') {
70 aContext->SetErrorOffset(iter - avtStart);
71 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
74 inExpr = true;
75 break;
77 // We found a second brace, let that be part of the next
78 // literal section being parsed and continue looping
80 ++iter;
83 if (start == iter && literalString.IsEmpty()) {
84 // Restart the loop since we didn't create an expression
85 continue;
87 newExpr =
88 MakeUnique<txLiteralExpr>(literalString + Substring(start, iter));
89 } else {
90 // Parse expressions, iter is already past the initial '{' when
91 // we get here.
92 while (iter != end) {
93 if (*iter == '}') {
94 rv = createExprInternal(Substring(start, iter), start - avtStart,
95 aContext, getter_Transfers(newExpr));
96 NS_ENSURE_SUCCESS(rv, rv);
98 inExpr = false;
99 ++iter; // skip closing '}'
100 break;
101 } else if (*iter == '\'' || *iter == '"') {
102 char16_t q = *iter;
103 while (++iter != end && *iter != q) {
104 } /* do nothing */
105 if (iter == end) {
106 break;
109 ++iter;
112 if (inExpr) {
113 aContext->SetErrorOffset(start - avtStart);
114 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
118 // Add expression, create a concat() call if necessary
119 if (!expr) {
120 expr = std::move(newExpr);
121 } else {
122 if (!concat) {
123 concat = new txCoreFunctionCall(txCoreFunctionCall::CONCAT);
124 concat->addParam(expr.release());
125 expr = WrapUnique(concat);
128 concat->addParam(newExpr.release());
132 if (inExpr) {
133 aContext->SetErrorOffset(iter - avtStart);
134 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE;
137 if (!expr) {
138 expr = MakeUnique<txLiteralExpr>(u""_ns);
141 *aResult = expr.release();
143 return NS_OK;
146 nsresult txExprParser::createExprInternal(const nsAString& aExpression,
147 uint32_t aSubStringPos,
148 txIParseContext* aContext,
149 Expr** aExpr) {
150 NS_ENSURE_ARG_POINTER(aExpr);
151 *aExpr = nullptr;
152 txExprLexer lexer;
153 nsresult rv = lexer.parse(aExpression);
154 if (NS_FAILED(rv)) {
155 nsAString::const_char_iterator start;
156 aExpression.BeginReading(start);
157 aContext->SetErrorOffset(lexer.mPosition - start + aSubStringPos);
158 return rv;
160 UniquePtr<Expr> expr;
161 rv = createExpr(lexer, aContext, getter_Transfers(expr));
162 if (NS_SUCCEEDED(rv) && lexer.peek()->mType != Token::END) {
163 rv = NS_ERROR_XPATH_BINARY_EXPECTED;
165 if (NS_FAILED(rv)) {
166 nsAString::const_char_iterator start;
167 aExpression.BeginReading(start);
168 aContext->SetErrorOffset(lexer.peek()->mStart - start + aSubStringPos);
170 return rv;
173 txXPathOptimizer optimizer;
174 Expr* newExpr = nullptr;
175 optimizer.optimize(expr.get(), &newExpr);
177 *aExpr = newExpr ? newExpr : expr.release();
179 return NS_OK;
183 * Private Methods
187 * Creates a binary Expr for the given operator
189 nsresult txExprParser::createBinaryExpr(UniquePtr<Expr>& left,
190 UniquePtr<Expr>& right, Token* op,
191 Expr** aResult) {
192 NS_ASSERTION(op, "internal error");
193 *aResult = nullptr;
195 Expr* expr = nullptr;
196 switch (op->mType) {
197 //-- math ops
198 case Token::ADDITION_OP:
199 expr = new txNumberExpr(left.get(), right.get(), txNumberExpr::ADD);
200 break;
201 case Token::SUBTRACTION_OP:
202 expr = new txNumberExpr(left.get(), right.get(), txNumberExpr::SUBTRACT);
203 break;
204 case Token::DIVIDE_OP:
205 expr = new txNumberExpr(left.get(), right.get(), txNumberExpr::DIVIDE);
206 break;
207 case Token::MODULUS_OP:
208 expr = new txNumberExpr(left.get(), right.get(), txNumberExpr::MODULUS);
209 break;
210 case Token::MULTIPLY_OP:
211 expr = new txNumberExpr(left.get(), right.get(), txNumberExpr::MULTIPLY);
212 break;
214 //-- case boolean ops
215 case Token::AND_OP:
216 expr = new BooleanExpr(left.get(), right.get(), BooleanExpr::AND);
217 break;
218 case Token::OR_OP:
219 expr = new BooleanExpr(left.get(), right.get(), BooleanExpr::OR);
220 break;
222 //-- equality ops
223 case Token::EQUAL_OP:
224 expr = new RelationalExpr(left.get(), right.get(), RelationalExpr::EQUAL);
225 break;
226 case Token::NOT_EQUAL_OP:
227 expr = new RelationalExpr(left.get(), right.get(),
228 RelationalExpr::NOT_EQUAL);
229 break;
231 //-- relational ops
232 case Token::LESS_THAN_OP:
233 expr = new RelationalExpr(left.get(), right.get(),
234 RelationalExpr::LESS_THAN);
235 break;
236 case Token::GREATER_THAN_OP:
237 expr = new RelationalExpr(left.get(), right.get(),
238 RelationalExpr::GREATER_THAN);
239 break;
240 case Token::LESS_OR_EQUAL_OP:
241 expr = new RelationalExpr(left.get(), right.get(),
242 RelationalExpr::LESS_OR_EQUAL);
243 break;
244 case Token::GREATER_OR_EQUAL_OP:
245 expr = new RelationalExpr(left.get(), right.get(),
246 RelationalExpr::GREATER_OR_EQUAL);
247 break;
249 default:
250 MOZ_ASSERT_UNREACHABLE("operator tokens should be already checked");
251 return NS_ERROR_UNEXPECTED;
254 Unused << left.release();
255 Unused << right.release();
257 *aResult = expr;
258 return NS_OK;
261 nsresult txExprParser::createExpr(txExprLexer& lexer, txIParseContext* aContext,
262 Expr** aResult) {
263 *aResult = nullptr;
265 nsresult rv = NS_OK;
266 bool done = false;
268 UniquePtr<Expr> expr;
270 txStack exprs;
271 txStack ops;
273 while (!done) {
274 uint16_t negations = 0;
275 while (lexer.peek()->mType == Token::SUBTRACTION_OP) {
276 negations++;
277 lexer.nextToken();
280 rv = createUnionExpr(lexer, aContext, getter_Transfers(expr));
281 if (NS_FAILED(rv)) {
282 break;
285 if (negations > 0) {
286 if (negations % 2 == 0) {
287 auto fcExpr =
288 MakeUnique<txCoreFunctionCall>(txCoreFunctionCall::NUMBER);
290 fcExpr->addParam(expr.release());
291 expr = std::move(fcExpr);
292 } else {
293 expr = MakeUnique<UnaryExpr>(expr.release());
297 short tokPrecedence = precedence(lexer.peek());
298 if (tokPrecedence != 0) {
299 Token* tok = lexer.nextToken();
300 while (!exprs.isEmpty() &&
301 tokPrecedence <= precedence(static_cast<Token*>(ops.peek()))) {
302 // can't use expr as argument due to order of evaluation
303 UniquePtr<Expr> left(static_cast<Expr*>(exprs.pop()));
304 UniquePtr<Expr> right(std::move(expr));
305 rv = createBinaryExpr(left, right, static_cast<Token*>(ops.pop()),
306 getter_Transfers(expr));
307 if (NS_FAILED(rv)) {
308 done = true;
309 break;
312 exprs.push(expr.release());
313 ops.push(tok);
314 } else {
315 done = true;
319 while (NS_SUCCEEDED(rv) && !exprs.isEmpty()) {
320 UniquePtr<Expr> left(static_cast<Expr*>(exprs.pop()));
321 UniquePtr<Expr> right(std::move(expr));
322 rv = createBinaryExpr(left, right, static_cast<Token*>(ops.pop()),
323 getter_Transfers(expr));
325 // clean up on error
326 while (!exprs.isEmpty()) {
327 delete static_cast<Expr*>(exprs.pop());
329 NS_ENSURE_SUCCESS(rv, rv);
331 *aResult = expr.release();
332 return NS_OK;
335 nsresult txExprParser::createFilterOrStep(txExprLexer& lexer,
336 txIParseContext* aContext,
337 Expr** aResult) {
338 *aResult = nullptr;
340 nsresult rv = NS_OK;
341 Token* tok = lexer.peek();
343 UniquePtr<Expr> expr;
344 switch (tok->mType) {
345 case Token::FUNCTION_NAME_AND_PAREN:
346 rv = createFunctionCall(lexer, aContext, getter_Transfers(expr));
347 NS_ENSURE_SUCCESS(rv, rv);
348 break;
349 case Token::VAR_REFERENCE:
350 lexer.nextToken();
352 RefPtr<nsAtom> prefix, lName;
353 int32_t nspace;
354 nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
355 aContext, getter_AddRefs(lName), nspace);
356 NS_ENSURE_SUCCESS(rv, rv);
357 expr = MakeUnique<VariableRefExpr>(prefix, lName, nspace);
359 break;
360 case Token::L_PAREN:
361 lexer.nextToken();
362 rv = createExpr(lexer, aContext, getter_Transfers(expr));
363 NS_ENSURE_SUCCESS(rv, rv);
365 if (lexer.peek()->mType != Token::R_PAREN) {
366 return NS_ERROR_XPATH_PAREN_EXPECTED;
368 lexer.nextToken();
369 break;
370 case Token::LITERAL:
371 lexer.nextToken();
372 expr = MakeUnique<txLiteralExpr>(tok->Value());
373 break;
374 case Token::NUMBER: {
375 lexer.nextToken();
376 expr = MakeUnique<txLiteralExpr>(txDouble::toDouble(tok->Value()));
377 break;
379 default:
380 return createLocationStep(lexer, aContext, aResult);
383 if (lexer.peek()->mType == Token::L_BRACKET) {
384 UniquePtr<FilterExpr> filterExpr(new FilterExpr(expr.get()));
386 Unused << expr.release();
388 //-- handle predicates
389 rv = parsePredicates(filterExpr.get(), lexer, aContext);
390 NS_ENSURE_SUCCESS(rv, rv);
391 expr = std::move(filterExpr);
394 *aResult = expr.release();
395 return NS_OK;
398 nsresult txExprParser::createFunctionCall(txExprLexer& lexer,
399 txIParseContext* aContext,
400 Expr** aResult) {
401 *aResult = nullptr;
403 UniquePtr<FunctionCall> fnCall;
405 Token* tok = lexer.nextToken();
406 NS_ASSERTION(tok->mType == Token::FUNCTION_NAME_AND_PAREN,
407 "FunctionCall expected");
409 //-- compare function names
410 RefPtr<nsAtom> prefix, lName;
411 int32_t namespaceID;
412 nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
413 getter_AddRefs(lName), namespaceID);
414 NS_ENSURE_SUCCESS(rv, rv);
416 txCoreFunctionCall::eType type;
417 if (namespaceID == kNameSpaceID_None &&
418 txCoreFunctionCall::getTypeFromAtom(lName, type)) {
419 // It is a known built-in function.
420 fnCall = MakeUnique<txCoreFunctionCall>(type);
423 // check extension functions and xslt
424 if (!fnCall) {
425 rv = aContext->resolveFunctionCall(lName, namespaceID,
426 getter_Transfers(fnCall));
428 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
429 // this should just happen for unparsed-entity-uri()
430 NS_ASSERTION(!fnCall, "Now is it implemented or not?");
431 rv = parseParameters(0, lexer, aContext);
432 NS_ENSURE_SUCCESS(rv, rv);
434 *aResult = new txLiteralExpr(tok->Value() + u" not implemented."_ns);
436 return NS_OK;
439 NS_ENSURE_SUCCESS(rv, rv);
442 //-- handle parametes
443 rv = parseParameters(fnCall.get(), lexer, aContext);
444 NS_ENSURE_SUCCESS(rv, rv);
446 *aResult = fnCall.release();
447 return NS_OK;
450 nsresult txExprParser::createLocationStep(txExprLexer& lexer,
451 txIParseContext* aContext,
452 Expr** aExpr) {
453 *aExpr = nullptr;
455 //-- child axis is default
456 LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS;
457 UniquePtr<txNodeTest> nodeTest;
459 //-- get Axis Identifier or AbbreviatedStep, if present
460 Token* tok = lexer.peek();
461 switch (tok->mType) {
462 case Token::AXIS_IDENTIFIER: {
463 //-- eat token
464 lexer.nextToken();
465 RefPtr<nsAtom> axis = NS_Atomize(tok->Value());
466 if (axis == nsGkAtoms::ancestor) {
467 axisIdentifier = LocationStep::ANCESTOR_AXIS;
468 } else if (axis == nsGkAtoms::ancestorOrSelf) {
469 axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
470 } else if (axis == nsGkAtoms::attribute) {
471 axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
472 } else if (axis == nsGkAtoms::child) {
473 axisIdentifier = LocationStep::CHILD_AXIS;
474 } else if (axis == nsGkAtoms::descendant) {
475 axisIdentifier = LocationStep::DESCENDANT_AXIS;
476 } else if (axis == nsGkAtoms::descendantOrSelf) {
477 axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
478 } else if (axis == nsGkAtoms::following) {
479 axisIdentifier = LocationStep::FOLLOWING_AXIS;
480 } else if (axis == nsGkAtoms::followingSibling) {
481 axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
482 } else if (axis == nsGkAtoms::_namespace) {
483 axisIdentifier = LocationStep::NAMESPACE_AXIS;
484 } else if (axis == nsGkAtoms::parent) {
485 axisIdentifier = LocationStep::PARENT_AXIS;
486 } else if (axis == nsGkAtoms::preceding) {
487 axisIdentifier = LocationStep::PRECEDING_AXIS;
488 } else if (axis == nsGkAtoms::precedingSibling) {
489 axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
490 } else if (axis == nsGkAtoms::self) {
491 axisIdentifier = LocationStep::SELF_AXIS;
492 } else {
493 return NS_ERROR_XPATH_INVALID_AXIS;
495 break;
497 case Token::AT_SIGN:
498 //-- eat token
499 lexer.nextToken();
500 axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
501 break;
502 case Token::PARENT_NODE:
503 //-- eat token
504 lexer.nextToken();
505 axisIdentifier = LocationStep::PARENT_AXIS;
506 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::NODE_TYPE);
507 break;
508 case Token::SELF_NODE:
509 //-- eat token
510 lexer.nextToken();
511 axisIdentifier = LocationStep::SELF_AXIS;
512 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::NODE_TYPE);
513 break;
514 default:
515 break;
518 //-- get NodeTest unless an AbbreviatedStep was found
519 nsresult rv = NS_OK;
520 if (!nodeTest) {
521 tok = lexer.peek();
523 if (tok->mType == Token::CNAME) {
524 lexer.nextToken();
525 // resolve QName
526 RefPtr<nsAtom> prefix, lName;
527 int32_t nspace;
528 rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
529 getter_AddRefs(lName), nspace, true);
530 NS_ENSURE_SUCCESS(rv, rv);
532 nodeTest = MakeUnique<txNameTest>(
533 prefix, lName, nspace,
534 axisIdentifier == LocationStep::ATTRIBUTE_AXIS
535 ? static_cast<uint16_t>(txXPathNodeType::ATTRIBUTE_NODE)
536 : static_cast<uint16_t>(txXPathNodeType::ELEMENT_NODE));
537 } else {
538 rv = createNodeTypeTest(lexer, getter_Transfers(nodeTest));
539 NS_ENSURE_SUCCESS(rv, rv);
543 UniquePtr<LocationStep> lstep(
544 new LocationStep(nodeTest.get(), axisIdentifier));
546 Unused << nodeTest.release();
548 //-- handle predicates
549 rv = parsePredicates(lstep.get(), lexer, aContext);
550 NS_ENSURE_SUCCESS(rv, rv);
552 *aExpr = lstep.release();
553 return NS_OK;
557 * This method only handles comment(), text(), processing-instructing()
558 * and node()
560 nsresult txExprParser::createNodeTypeTest(txExprLexer& lexer,
561 txNodeTest** aTest) {
562 *aTest = 0;
563 UniquePtr<txNodeTypeTest> nodeTest;
565 Token* nodeTok = lexer.peek();
567 switch (nodeTok->mType) {
568 case Token::COMMENT_AND_PAREN:
569 lexer.nextToken();
570 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::COMMENT_TYPE);
571 break;
572 case Token::NODE_AND_PAREN:
573 lexer.nextToken();
574 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::NODE_TYPE);
575 break;
576 case Token::PROC_INST_AND_PAREN:
577 lexer.nextToken();
578 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::PI_TYPE);
579 break;
580 case Token::TEXT_AND_PAREN:
581 lexer.nextToken();
582 nodeTest = MakeUnique<txNodeTypeTest>(txNodeTypeTest::TEXT_TYPE);
583 break;
584 default:
585 return NS_ERROR_XPATH_NO_NODE_TYPE_TEST;
588 if (nodeTok->mType == Token::PROC_INST_AND_PAREN &&
589 lexer.peek()->mType == Token::LITERAL) {
590 Token* tok = lexer.nextToken();
591 nodeTest->setNodeName(tok->Value());
593 if (lexer.peek()->mType != Token::R_PAREN) {
594 return NS_ERROR_XPATH_PAREN_EXPECTED;
596 lexer.nextToken();
598 *aTest = nodeTest.release();
599 return NS_OK;
603 * Creates a PathExpr using the given txExprLexer
604 * @param lexer the txExprLexer for retrieving Tokens
606 nsresult txExprParser::createPathExpr(txExprLexer& lexer,
607 txIParseContext* aContext,
608 Expr** aResult) {
609 *aResult = nullptr;
611 UniquePtr<Expr> expr;
613 Token* tok = lexer.peek();
615 // is this a root expression?
616 if (tok->mType == Token::PARENT_OP) {
617 if (!isLocationStepToken(lexer.peekAhead())) {
618 lexer.nextToken();
619 *aResult = new RootExpr();
620 return NS_OK;
624 // parse first step (possibly a FilterExpr)
625 nsresult rv = NS_OK;
626 if (tok->mType != Token::PARENT_OP && tok->mType != Token::ANCESTOR_OP) {
627 rv = createFilterOrStep(lexer, aContext, getter_Transfers(expr));
628 NS_ENSURE_SUCCESS(rv, rv);
630 // is this a singlestep path expression?
631 tok = lexer.peek();
632 if (tok->mType != Token::PARENT_OP && tok->mType != Token::ANCESTOR_OP) {
633 *aResult = expr.release();
634 return NS_OK;
636 } else {
637 expr = MakeUnique<RootExpr>();
639 #ifdef TX_TO_STRING
640 static_cast<RootExpr*>(expr.get())->setSerialize(false);
641 #endif
644 // We have a PathExpr containing several steps
645 UniquePtr<PathExpr> pathExpr(new PathExpr());
646 pathExpr->addExpr(expr.release(), PathExpr::RELATIVE_OP);
648 // this is ugly
649 while (1) {
650 PathExpr::PathOperator pathOp;
651 switch (lexer.peek()->mType) {
652 case Token::ANCESTOR_OP:
653 pathOp = PathExpr::DESCENDANT_OP;
654 break;
655 case Token::PARENT_OP:
656 pathOp = PathExpr::RELATIVE_OP;
657 break;
658 default:
659 *aResult = pathExpr.release();
660 return NS_OK;
662 lexer.nextToken();
664 rv = createLocationStep(lexer, aContext, getter_Transfers(expr));
665 NS_ENSURE_SUCCESS(rv, rv);
667 pathExpr->addExpr(expr.release(), pathOp);
669 MOZ_ASSERT_UNREACHABLE("internal xpath parser error");
670 return NS_ERROR_UNEXPECTED;
674 * Creates a PathExpr using the given txExprLexer
675 * @param lexer the txExprLexer for retrieving Tokens
677 nsresult txExprParser::createUnionExpr(txExprLexer& lexer,
678 txIParseContext* aContext,
679 Expr** aResult) {
680 *aResult = nullptr;
682 UniquePtr<Expr> expr;
683 nsresult rv = createPathExpr(lexer, aContext, getter_Transfers(expr));
684 NS_ENSURE_SUCCESS(rv, rv);
686 if (lexer.peek()->mType != Token::UNION_OP) {
687 *aResult = expr.release();
688 return NS_OK;
691 UniquePtr<UnionExpr> unionExpr(new UnionExpr());
692 unionExpr->addExpr(expr.release());
694 while (lexer.peek()->mType == Token::UNION_OP) {
695 lexer.nextToken(); //-- eat token
697 rv = createPathExpr(lexer, aContext, getter_Transfers(expr));
698 NS_ENSURE_SUCCESS(rv, rv);
700 unionExpr->addExpr(expr.release());
703 *aResult = unionExpr.release();
704 return NS_OK;
707 bool txExprParser::isLocationStepToken(Token* aToken) {
708 // We could put these in consecutive order in ExprLexer.h for speed
709 return aToken->mType == Token::AXIS_IDENTIFIER ||
710 aToken->mType == Token::AT_SIGN ||
711 aToken->mType == Token::PARENT_NODE ||
712 aToken->mType == Token::SELF_NODE || aToken->mType == Token::CNAME ||
713 aToken->mType == Token::COMMENT_AND_PAREN ||
714 aToken->mType == Token::NODE_AND_PAREN ||
715 aToken->mType == Token::PROC_INST_AND_PAREN ||
716 aToken->mType == Token::TEXT_AND_PAREN;
720 * Using the given lexer, parses the tokens if they represent a predicate list
721 * If an error occurs a non-zero String pointer will be returned containing the
722 * error message.
723 * @param predicateList, the PredicateList to add predicate expressions to
724 * @param lexer the txExprLexer to use for parsing tokens
725 * @return 0 if successful, or a String pointer to the error message
727 nsresult txExprParser::parsePredicates(PredicateList* aPredicateList,
728 txExprLexer& lexer,
729 txIParseContext* aContext) {
730 UniquePtr<Expr> expr;
731 nsresult rv = NS_OK;
732 while (lexer.peek()->mType == Token::L_BRACKET) {
733 //-- eat Token
734 lexer.nextToken();
736 rv = createExpr(lexer, aContext, getter_Transfers(expr));
737 NS_ENSURE_SUCCESS(rv, rv);
739 aPredicateList->add(expr.release());
741 if (lexer.peek()->mType != Token::R_BRACKET) {
742 return NS_ERROR_XPATH_BRACKET_EXPECTED;
744 lexer.nextToken();
746 return NS_OK;
750 * Using the given lexer, parses the tokens if they represent a parameter list
751 * If an error occurs a non-zero String pointer will be returned containing the
752 * error message.
753 * @param list, the List to add parameter expressions to
754 * @param lexer the txExprLexer to use for parsing tokens
755 * @return NS_OK if successful, or another rv otherwise
757 nsresult txExprParser::parseParameters(FunctionCall* aFnCall,
758 txExprLexer& lexer,
759 txIParseContext* aContext) {
760 if (lexer.peek()->mType == Token::R_PAREN) {
761 lexer.nextToken();
762 return NS_OK;
765 UniquePtr<Expr> expr;
766 nsresult rv = NS_OK;
767 while (1) {
768 rv = createExpr(lexer, aContext, getter_Transfers(expr));
769 NS_ENSURE_SUCCESS(rv, rv);
771 if (aFnCall) {
772 aFnCall->addParam(expr.release());
775 switch (lexer.peek()->mType) {
776 case Token::R_PAREN:
777 lexer.nextToken();
778 return NS_OK;
779 case Token::COMMA: //-- param separator
780 lexer.nextToken();
781 break;
782 default:
783 return NS_ERROR_XPATH_PAREN_EXPECTED;
787 MOZ_ASSERT_UNREACHABLE("internal xpath parser error");
788 return NS_ERROR_UNEXPECTED;
791 short txExprParser::precedence(Token* aToken) {
792 switch (aToken->mType) {
793 case Token::OR_OP:
794 return 1;
795 case Token::AND_OP:
796 return 2;
797 //-- equality
798 case Token::EQUAL_OP:
799 case Token::NOT_EQUAL_OP:
800 return 3;
801 //-- relational
802 case Token::LESS_THAN_OP:
803 case Token::GREATER_THAN_OP:
804 case Token::LESS_OR_EQUAL_OP:
805 case Token::GREATER_OR_EQUAL_OP:
806 return 4;
807 //-- additive operators
808 case Token::ADDITION_OP:
809 case Token::SUBTRACTION_OP:
810 return 5;
811 //-- multiplicative
812 case Token::DIVIDE_OP:
813 case Token::MULTIPLY_OP:
814 case Token::MODULUS_OP:
815 return 6;
816 default:
817 break;
819 return 0;
822 nsresult txExprParser::resolveQName(const nsAString& aQName, nsAtom** aPrefix,
823 txIParseContext* aContext,
824 nsAtom** aLocalName, int32_t& aNamespace,
825 bool aIsNameTest) {
826 int32_t idx = aQName.FindChar(':');
827 if (idx > 0) {
828 *aPrefix = NS_AtomizeMainThread(StringHead(aQName, (uint32_t)idx)).take();
829 *aLocalName = NS_AtomizeMainThread(Substring(aQName, (uint32_t)idx + 1,
830 aQName.Length() - (idx + 1)))
831 .take();
832 aNamespace = aContext->resolveNamespacePrefix(*aPrefix);
833 return aNamespace != kNameSpaceID_Unknown ? NS_OK
834 : NS_ERROR_DOM_NAMESPACE_ERR;
836 aNamespace = kNameSpaceID_None;
837 // the lexer dealt with idx == 0
838 *aPrefix = 0;
839 if (aIsNameTest && aContext->caseInsensitiveNameTests()) {
840 nsAutoString lcname;
841 nsContentUtils::ASCIIToLower(aQName, lcname);
842 *aLocalName = NS_AtomizeMainThread(lcname).take();
843 } else {
844 *aLocalName = NS_AtomizeMainThread(aQName).take();
846 return NS_OK;