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/. */
8 * This class is used to parse XSL Expressions
12 #include "txExprParser.h"
16 #include "mozilla/UniquePtrExtensions.h"
18 #include "nsGkAtoms.h"
20 #include "txExprLexer.h"
21 #include "txIXPathContext.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
;
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
) {
41 FunctionCall
* concat
= nullptr;
43 nsAutoString literalString
;
45 nsAString::const_char_iterator iter
, start
, end
, avtStart
;
46 aAttrValue
.BeginReading(iter
);
47 aAttrValue
.EndReading(end
);
51 // Every iteration through this loop parses either a literal section
54 UniquePtr
<Expr
> newExpr
;
56 // Parse literal section
57 literalString
.Truncate();
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
));
65 // Unless another brace follows we've found the start of
66 // an expression (in case of '{') or an unbalanced brace
68 if (iter
== end
|| *iter
!= q
) {
70 aContext
->SetErrorOffset(iter
- avtStart
);
71 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE
;
77 // We found a second brace, let that be part of the next
78 // literal section being parsed and continue looping
83 if (start
== iter
&& literalString
.IsEmpty()) {
84 // Restart the loop since we didn't create an expression
88 MakeUnique
<txLiteralExpr
>(literalString
+ Substring(start
, iter
));
90 // Parse expressions, iter is already past the initial '{' when
94 rv
= createExprInternal(Substring(start
, iter
), start
- avtStart
,
95 aContext
, getter_Transfers(newExpr
));
96 NS_ENSURE_SUCCESS(rv
, rv
);
99 ++iter
; // skip closing '}'
101 } else if (*iter
== '\'' || *iter
== '"') {
103 while (++iter
!= end
&& *iter
!= q
) {
113 aContext
->SetErrorOffset(start
- avtStart
);
114 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE
;
118 // Add expression, create a concat() call if necessary
120 expr
= std::move(newExpr
);
123 concat
= new txCoreFunctionCall(txCoreFunctionCall::CONCAT
);
124 concat
->addParam(expr
.release());
125 expr
= WrapUnique(concat
);
128 concat
->addParam(newExpr
.release());
133 aContext
->SetErrorOffset(iter
- avtStart
);
134 return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE
;
138 expr
= MakeUnique
<txLiteralExpr
>(u
""_ns
);
141 *aResult
= expr
.release();
146 nsresult
txExprParser::createExprInternal(const nsAString
& aExpression
,
147 uint32_t aSubStringPos
,
148 txIParseContext
* aContext
,
150 NS_ENSURE_ARG_POINTER(aExpr
);
153 nsresult rv
= lexer
.parse(aExpression
);
155 nsAString::const_char_iterator start
;
156 aExpression
.BeginReading(start
);
157 aContext
->SetErrorOffset(lexer
.mPosition
- start
+ aSubStringPos
);
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
;
166 nsAString::const_char_iterator start
;
167 aExpression
.BeginReading(start
);
168 aContext
->SetErrorOffset(lexer
.peek()->mStart
- start
+ aSubStringPos
);
173 txXPathOptimizer optimizer
;
174 Expr
* newExpr
= nullptr;
175 optimizer
.optimize(expr
.get(), &newExpr
);
177 *aExpr
= newExpr
? newExpr
: expr
.release();
187 * Creates a binary Expr for the given operator
189 nsresult
txExprParser::createBinaryExpr(UniquePtr
<Expr
>& left
,
190 UniquePtr
<Expr
>& right
, Token
* op
,
192 NS_ASSERTION(op
, "internal error");
195 Expr
* expr
= nullptr;
198 case Token::ADDITION_OP
:
199 expr
= new txNumberExpr(left
.get(), right
.get(), txNumberExpr::ADD
);
201 case Token::SUBTRACTION_OP
:
202 expr
= new txNumberExpr(left
.get(), right
.get(), txNumberExpr::SUBTRACT
);
204 case Token::DIVIDE_OP
:
205 expr
= new txNumberExpr(left
.get(), right
.get(), txNumberExpr::DIVIDE
);
207 case Token::MODULUS_OP
:
208 expr
= new txNumberExpr(left
.get(), right
.get(), txNumberExpr::MODULUS
);
210 case Token::MULTIPLY_OP
:
211 expr
= new txNumberExpr(left
.get(), right
.get(), txNumberExpr::MULTIPLY
);
214 //-- case boolean ops
216 expr
= new BooleanExpr(left
.get(), right
.get(), BooleanExpr::AND
);
219 expr
= new BooleanExpr(left
.get(), right
.get(), BooleanExpr::OR
);
223 case Token::EQUAL_OP
:
224 expr
= new RelationalExpr(left
.get(), right
.get(), RelationalExpr::EQUAL
);
226 case Token::NOT_EQUAL_OP
:
227 expr
= new RelationalExpr(left
.get(), right
.get(),
228 RelationalExpr::NOT_EQUAL
);
232 case Token::LESS_THAN_OP
:
233 expr
= new RelationalExpr(left
.get(), right
.get(),
234 RelationalExpr::LESS_THAN
);
236 case Token::GREATER_THAN_OP
:
237 expr
= new RelationalExpr(left
.get(), right
.get(),
238 RelationalExpr::GREATER_THAN
);
240 case Token::LESS_OR_EQUAL_OP
:
241 expr
= new RelationalExpr(left
.get(), right
.get(),
242 RelationalExpr::LESS_OR_EQUAL
);
244 case Token::GREATER_OR_EQUAL_OP
:
245 expr
= new RelationalExpr(left
.get(), right
.get(),
246 RelationalExpr::GREATER_OR_EQUAL
);
250 MOZ_ASSERT_UNREACHABLE("operator tokens should be already checked");
251 return NS_ERROR_UNEXPECTED
;
254 Unused
<< left
.release();
255 Unused
<< right
.release();
261 nsresult
txExprParser::createExpr(txExprLexer
& lexer
, txIParseContext
* aContext
,
268 UniquePtr
<Expr
> expr
;
274 uint16_t negations
= 0;
275 while (lexer
.peek()->mType
== Token::SUBTRACTION_OP
) {
280 rv
= createUnionExpr(lexer
, aContext
, getter_Transfers(expr
));
286 if (negations
% 2 == 0) {
288 MakeUnique
<txCoreFunctionCall
>(txCoreFunctionCall::NUMBER
);
290 fcExpr
->addParam(expr
.release());
291 expr
= std::move(fcExpr
);
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
));
312 exprs
.push(expr
.release());
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
));
326 while (!exprs
.isEmpty()) {
327 delete static_cast<Expr
*>(exprs
.pop());
329 NS_ENSURE_SUCCESS(rv
, rv
);
331 *aResult
= expr
.release();
335 nsresult
txExprParser::createFilterOrStep(txExprLexer
& lexer
,
336 txIParseContext
* aContext
,
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
);
349 case Token::VAR_REFERENCE
:
352 RefPtr
<nsAtom
> prefix
, lName
;
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
);
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
;
372 expr
= MakeUnique
<txLiteralExpr
>(tok
->Value());
374 case Token::NUMBER
: {
376 expr
= MakeUnique
<txLiteralExpr
>(txDouble::toDouble(tok
->Value()));
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();
398 nsresult
txExprParser::createFunctionCall(txExprLexer
& lexer
,
399 txIParseContext
* aContext
,
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
;
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
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
);
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();
450 nsresult
txExprParser::createLocationStep(txExprLexer
& lexer
,
451 txIParseContext
* aContext
,
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
: {
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
;
493 return NS_ERROR_XPATH_INVALID_AXIS
;
500 axisIdentifier
= LocationStep::ATTRIBUTE_AXIS
;
502 case Token::PARENT_NODE
:
505 axisIdentifier
= LocationStep::PARENT_AXIS
;
506 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::NODE_TYPE
);
508 case Token::SELF_NODE
:
511 axisIdentifier
= LocationStep::SELF_AXIS
;
512 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::NODE_TYPE
);
518 //-- get NodeTest unless an AbbreviatedStep was found
523 if (tok
->mType
== Token::CNAME
) {
526 RefPtr
<nsAtom
> prefix
, lName
;
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
));
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();
557 * This method only handles comment(), text(), processing-instructing()
560 nsresult
txExprParser::createNodeTypeTest(txExprLexer
& lexer
,
561 txNodeTest
** aTest
) {
563 UniquePtr
<txNodeTypeTest
> nodeTest
;
565 Token
* nodeTok
= lexer
.peek();
567 switch (nodeTok
->mType
) {
568 case Token::COMMENT_AND_PAREN
:
570 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::COMMENT_TYPE
);
572 case Token::NODE_AND_PAREN
:
574 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::NODE_TYPE
);
576 case Token::PROC_INST_AND_PAREN
:
578 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::PI_TYPE
);
580 case Token::TEXT_AND_PAREN
:
582 nodeTest
= MakeUnique
<txNodeTypeTest
>(txNodeTypeTest::TEXT_TYPE
);
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
;
598 *aTest
= nodeTest
.release();
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
,
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())) {
619 *aResult
= new RootExpr();
624 // parse first step (possibly a FilterExpr)
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?
632 if (tok
->mType
!= Token::PARENT_OP
&& tok
->mType
!= Token::ANCESTOR_OP
) {
633 *aResult
= expr
.release();
637 expr
= MakeUnique
<RootExpr
>();
640 static_cast<RootExpr
*>(expr
.get())->setSerialize(false);
644 // We have a PathExpr containing several steps
645 UniquePtr
<PathExpr
> pathExpr(new PathExpr());
646 pathExpr
->addExpr(expr
.release(), PathExpr::RELATIVE_OP
);
650 PathExpr::PathOperator pathOp
;
651 switch (lexer
.peek()->mType
) {
652 case Token::ANCESTOR_OP
:
653 pathOp
= PathExpr::DESCENDANT_OP
;
655 case Token::PARENT_OP
:
656 pathOp
= PathExpr::RELATIVE_OP
;
659 *aResult
= pathExpr
.release();
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
,
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();
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();
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
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
,
729 txIParseContext
* aContext
) {
730 UniquePtr
<Expr
> expr
;
732 while (lexer
.peek()->mType
== Token::L_BRACKET
) {
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
;
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
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
,
759 txIParseContext
* aContext
) {
760 if (lexer
.peek()->mType
== Token::R_PAREN
) {
765 UniquePtr
<Expr
> expr
;
768 rv
= createExpr(lexer
, aContext
, getter_Transfers(expr
));
769 NS_ENSURE_SUCCESS(rv
, rv
);
772 aFnCall
->addParam(expr
.release());
775 switch (lexer
.peek()->mType
) {
779 case Token::COMMA
: //-- param separator
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
) {
798 case Token::EQUAL_OP
:
799 case Token::NOT_EQUAL_OP
:
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
:
807 //-- additive operators
808 case Token::ADDITION_OP
:
809 case Token::SUBTRACTION_OP
:
812 case Token::DIVIDE_OP
:
813 case Token::MULTIPLY_OP
:
814 case Token::MODULUS_OP
:
822 nsresult
txExprParser::resolveQName(const nsAString
& aQName
, nsAtom
** aPrefix
,
823 txIParseContext
* aContext
,
824 nsAtom
** aLocalName
, int32_t& aNamespace
,
826 int32_t idx
= aQName
.FindChar(':');
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)))
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
839 if (aIsNameTest
&& aContext
->caseInsensitiveNameTests()) {
841 nsContentUtils::ASCIIToLower(aQName
, lcname
);
842 *aLocalName
= NS_AtomizeMainThread(lcname
).take();
844 *aLocalName
= NS_AtomizeMainThread(aQName
).take();