1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xslt/xpath/txExprParser.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,922 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/** 1.10 + * ExprParser 1.11 + * This class is used to parse XSL Expressions 1.12 + * @see ExprLexer 1.13 +**/ 1.14 + 1.15 +#include "txExprParser.h" 1.16 +#include "txExprLexer.h" 1.17 +#include "txExpr.h" 1.18 +#include "txStack.h" 1.19 +#include "nsGkAtoms.h" 1.20 +#include "nsError.h" 1.21 +#include "txIXPathContext.h" 1.22 +#include "txStringUtils.h" 1.23 +#include "txXPathNode.h" 1.24 +#include "txXPathOptimizer.h" 1.25 + 1.26 +/** 1.27 + * Creates an Attribute Value Template using the given value 1.28 + * This should move to XSLProcessor class 1.29 + */ 1.30 +nsresult 1.31 +txExprParser::createAVT(const nsSubstring& aAttrValue, 1.32 + txIParseContext* aContext, 1.33 + Expr** aResult) 1.34 +{ 1.35 + *aResult = nullptr; 1.36 + nsresult rv = NS_OK; 1.37 + nsAutoPtr<Expr> expr; 1.38 + FunctionCall* concat = nullptr; 1.39 + 1.40 + nsAutoString literalString; 1.41 + bool inExpr = false; 1.42 + nsSubstring::const_char_iterator iter, start, end, avtStart; 1.43 + aAttrValue.BeginReading(iter); 1.44 + aAttrValue.EndReading(end); 1.45 + avtStart = iter; 1.46 + 1.47 + while (iter != end) { 1.48 + // Every iteration through this loop parses either a literal section 1.49 + // or an expression 1.50 + start = iter; 1.51 + nsAutoPtr<Expr> newExpr; 1.52 + if (!inExpr) { 1.53 + // Parse literal section 1.54 + literalString.Truncate(); 1.55 + while (iter != end) { 1.56 + char16_t q = *iter; 1.57 + if (q == '{' || q == '}') { 1.58 + // Store what we've found so far and set a new |start| to 1.59 + // skip the (first) brace 1.60 + literalString.Append(Substring(start, iter)); 1.61 + start = ++iter; 1.62 + // Unless another brace follows we've found the start of 1.63 + // an expression (in case of '{') or an unbalanced brace 1.64 + // (in case of '}') 1.65 + if (iter == end || *iter != q) { 1.66 + if (q == '}') { 1.67 + aContext->SetErrorOffset(iter - avtStart); 1.68 + return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE; 1.69 + } 1.70 + 1.71 + inExpr = true; 1.72 + break; 1.73 + } 1.74 + // We found a second brace, let that be part of the next 1.75 + // literal section being parsed and continue looping 1.76 + } 1.77 + ++iter; 1.78 + } 1.79 + 1.80 + if (start == iter && literalString.IsEmpty()) { 1.81 + // Restart the loop since we didn't create an expression 1.82 + continue; 1.83 + } 1.84 + newExpr = new txLiteralExpr(literalString + 1.85 + Substring(start, iter)); 1.86 + } 1.87 + else { 1.88 + // Parse expressions, iter is already past the initial '{' when 1.89 + // we get here. 1.90 + while (iter != end) { 1.91 + if (*iter == '}') { 1.92 + rv = createExprInternal(Substring(start, iter), 1.93 + start - avtStart, aContext, 1.94 + getter_Transfers(newExpr)); 1.95 + NS_ENSURE_SUCCESS(rv, rv); 1.96 + 1.97 + inExpr = false; 1.98 + ++iter; // skip closing '}' 1.99 + break; 1.100 + } 1.101 + else if (*iter == '\'' || *iter == '"') { 1.102 + char16_t q = *iter; 1.103 + while (++iter != end && *iter != q) {} /* do nothing */ 1.104 + if (iter == end) { 1.105 + break; 1.106 + } 1.107 + } 1.108 + ++iter; 1.109 + } 1.110 + 1.111 + if (inExpr) { 1.112 + aContext->SetErrorOffset(start - avtStart); 1.113 + return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE; 1.114 + } 1.115 + } 1.116 + 1.117 + // Add expression, create a concat() call if necessary 1.118 + if (!expr) { 1.119 + expr = newExpr; 1.120 + } 1.121 + else { 1.122 + if (!concat) { 1.123 + concat = new txCoreFunctionCall(txCoreFunctionCall::CONCAT); 1.124 + NS_ENSURE_TRUE(concat, NS_ERROR_OUT_OF_MEMORY); 1.125 + 1.126 + rv = concat->addParam(expr.forget()); 1.127 + expr = concat; 1.128 + NS_ENSURE_SUCCESS(rv, rv); 1.129 + } 1.130 + 1.131 + rv = concat->addParam(newExpr.forget()); 1.132 + NS_ENSURE_SUCCESS(rv, rv); 1.133 + } 1.134 + } 1.135 + 1.136 + if (inExpr) { 1.137 + aContext->SetErrorOffset(iter - avtStart); 1.138 + return NS_ERROR_XPATH_UNBALANCED_CURLY_BRACE; 1.139 + } 1.140 + 1.141 + if (!expr) { 1.142 + expr = new txLiteralExpr(EmptyString()); 1.143 + } 1.144 + 1.145 + *aResult = expr.forget(); 1.146 + 1.147 + return NS_OK; 1.148 +} 1.149 + 1.150 +nsresult 1.151 +txExprParser::createExprInternal(const nsSubstring& aExpression, 1.152 + uint32_t aSubStringPos, 1.153 + txIParseContext* aContext, Expr** aExpr) 1.154 +{ 1.155 + NS_ENSURE_ARG_POINTER(aExpr); 1.156 + *aExpr = nullptr; 1.157 + txExprLexer lexer; 1.158 + nsresult rv = lexer.parse(aExpression); 1.159 + if (NS_FAILED(rv)) { 1.160 + nsASingleFragmentString::const_char_iterator start; 1.161 + aExpression.BeginReading(start); 1.162 + aContext->SetErrorOffset(lexer.mPosition - start + aSubStringPos); 1.163 + return rv; 1.164 + } 1.165 + nsAutoPtr<Expr> expr; 1.166 + rv = createExpr(lexer, aContext, getter_Transfers(expr)); 1.167 + if (NS_SUCCEEDED(rv) && lexer.peek()->mType != Token::END) { 1.168 + rv = NS_ERROR_XPATH_BINARY_EXPECTED; 1.169 + } 1.170 + if (NS_FAILED(rv)) { 1.171 + nsASingleFragmentString::const_char_iterator start; 1.172 + aExpression.BeginReading(start); 1.173 + aContext->SetErrorOffset(lexer.peek()->mStart - start + aSubStringPos); 1.174 + 1.175 + return rv; 1.176 + } 1.177 + 1.178 + txXPathOptimizer optimizer; 1.179 + Expr* newExpr = nullptr; 1.180 + rv = optimizer.optimize(expr, &newExpr); 1.181 + NS_ENSURE_SUCCESS(rv, rv); 1.182 + 1.183 + *aExpr = newExpr ? newExpr : expr.forget(); 1.184 + 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +/** 1.189 + * Private Methods 1.190 + */ 1.191 + 1.192 +/** 1.193 + * Creates a binary Expr for the given operator 1.194 + */ 1.195 +nsresult 1.196 +txExprParser::createBinaryExpr(nsAutoPtr<Expr>& left, nsAutoPtr<Expr>& right, 1.197 + Token* op, Expr** aResult) 1.198 +{ 1.199 + NS_ASSERTION(op, "internal error"); 1.200 + *aResult = nullptr; 1.201 + 1.202 + Expr* expr = nullptr; 1.203 + switch (op->mType) { 1.204 + //-- math ops 1.205 + case Token::ADDITION_OP : 1.206 + expr = new txNumberExpr(left, right, txNumberExpr::ADD); 1.207 + break; 1.208 + case Token::SUBTRACTION_OP: 1.209 + expr = new txNumberExpr(left, right, txNumberExpr::SUBTRACT); 1.210 + break; 1.211 + case Token::DIVIDE_OP : 1.212 + expr = new txNumberExpr(left, right, txNumberExpr::DIVIDE); 1.213 + break; 1.214 + case Token::MODULUS_OP : 1.215 + expr = new txNumberExpr(left, right, txNumberExpr::MODULUS); 1.216 + break; 1.217 + case Token::MULTIPLY_OP : 1.218 + expr = new txNumberExpr(left, right, txNumberExpr::MULTIPLY); 1.219 + break; 1.220 + 1.221 + //-- case boolean ops 1.222 + case Token::AND_OP: 1.223 + expr = new BooleanExpr(left, right, BooleanExpr::AND); 1.224 + break; 1.225 + case Token::OR_OP: 1.226 + expr = new BooleanExpr(left, right, BooleanExpr::OR); 1.227 + break; 1.228 + 1.229 + //-- equality ops 1.230 + case Token::EQUAL_OP : 1.231 + expr = new RelationalExpr(left, right, RelationalExpr::EQUAL); 1.232 + break; 1.233 + case Token::NOT_EQUAL_OP : 1.234 + expr = new RelationalExpr(left, right, RelationalExpr::NOT_EQUAL); 1.235 + break; 1.236 + 1.237 + //-- relational ops 1.238 + case Token::LESS_THAN_OP: 1.239 + expr = new RelationalExpr(left, right, RelationalExpr::LESS_THAN); 1.240 + break; 1.241 + case Token::GREATER_THAN_OP: 1.242 + expr = new RelationalExpr(left, right, 1.243 + RelationalExpr::GREATER_THAN); 1.244 + break; 1.245 + case Token::LESS_OR_EQUAL_OP: 1.246 + expr = new RelationalExpr(left, right, 1.247 + RelationalExpr::LESS_OR_EQUAL); 1.248 + break; 1.249 + case Token::GREATER_OR_EQUAL_OP: 1.250 + expr = new RelationalExpr(left, right, 1.251 + RelationalExpr::GREATER_OR_EQUAL); 1.252 + break; 1.253 + 1.254 + default: 1.255 + NS_NOTREACHED("operator tokens should be already checked"); 1.256 + return NS_ERROR_UNEXPECTED; 1.257 + } 1.258 + NS_ENSURE_TRUE(expr, NS_ERROR_OUT_OF_MEMORY); 1.259 + 1.260 + left.forget(); 1.261 + right.forget(); 1.262 + 1.263 + *aResult = expr; 1.264 + return NS_OK; 1.265 +} 1.266 + 1.267 + 1.268 +nsresult 1.269 +txExprParser::createExpr(txExprLexer& lexer, txIParseContext* aContext, 1.270 + Expr** aResult) 1.271 +{ 1.272 + *aResult = nullptr; 1.273 + 1.274 + nsresult rv = NS_OK; 1.275 + bool done = false; 1.276 + 1.277 + nsAutoPtr<Expr> expr; 1.278 + 1.279 + txStack exprs; 1.280 + txStack ops; 1.281 + 1.282 + while (!done) { 1.283 + 1.284 + uint16_t negations = 0; 1.285 + while (lexer.peek()->mType == Token::SUBTRACTION_OP) { 1.286 + negations++; 1.287 + lexer.nextToken(); 1.288 + } 1.289 + 1.290 + rv = createUnionExpr(lexer, aContext, getter_Transfers(expr)); 1.291 + if (NS_FAILED(rv)) { 1.292 + break; 1.293 + } 1.294 + 1.295 + if (negations > 0) { 1.296 + if (negations % 2 == 0) { 1.297 + FunctionCall* fcExpr = new txCoreFunctionCall(txCoreFunctionCall::NUMBER); 1.298 + 1.299 + rv = fcExpr->addParam(expr); 1.300 + if (NS_FAILED(rv)) 1.301 + return rv; 1.302 + expr.forget(); 1.303 + expr = fcExpr; 1.304 + } 1.305 + else { 1.306 + expr = new UnaryExpr(expr.forget()); 1.307 + } 1.308 + } 1.309 + 1.310 + short tokPrecedence = precedence(lexer.peek()); 1.311 + if (tokPrecedence != 0) { 1.312 + Token* tok = lexer.nextToken(); 1.313 + while (!exprs.isEmpty() && tokPrecedence 1.314 + <= precedence(static_cast<Token*>(ops.peek()))) { 1.315 + // can't use expr as argument due to order of evaluation 1.316 + nsAutoPtr<Expr> left(static_cast<Expr*>(exprs.pop())); 1.317 + nsAutoPtr<Expr> right(expr); 1.318 + rv = createBinaryExpr(left, right, 1.319 + static_cast<Token*>(ops.pop()), 1.320 + getter_Transfers(expr)); 1.321 + if (NS_FAILED(rv)) { 1.322 + done = true; 1.323 + break; 1.324 + } 1.325 + } 1.326 + exprs.push(expr.forget()); 1.327 + ops.push(tok); 1.328 + } 1.329 + else { 1.330 + done = true; 1.331 + } 1.332 + } 1.333 + 1.334 + while (NS_SUCCEEDED(rv) && !exprs.isEmpty()) { 1.335 + nsAutoPtr<Expr> left(static_cast<Expr*>(exprs.pop())); 1.336 + nsAutoPtr<Expr> right(expr); 1.337 + rv = createBinaryExpr(left, right, static_cast<Token*>(ops.pop()), 1.338 + getter_Transfers(expr)); 1.339 + } 1.340 + // clean up on error 1.341 + while (!exprs.isEmpty()) { 1.342 + delete static_cast<Expr*>(exprs.pop()); 1.343 + } 1.344 + NS_ENSURE_SUCCESS(rv, rv); 1.345 + 1.346 + *aResult = expr.forget(); 1.347 + return NS_OK; 1.348 +} 1.349 + 1.350 +nsresult 1.351 +txExprParser::createFilterOrStep(txExprLexer& lexer, txIParseContext* aContext, 1.352 + Expr** aResult) 1.353 +{ 1.354 + *aResult = nullptr; 1.355 + 1.356 + nsresult rv = NS_OK; 1.357 + Token* tok = lexer.peek(); 1.358 + 1.359 + nsAutoPtr<Expr> expr; 1.360 + switch (tok->mType) { 1.361 + case Token::FUNCTION_NAME_AND_PAREN: 1.362 + rv = createFunctionCall(lexer, aContext, getter_Transfers(expr)); 1.363 + NS_ENSURE_SUCCESS(rv, rv); 1.364 + break; 1.365 + case Token::VAR_REFERENCE : 1.366 + lexer.nextToken(); 1.367 + { 1.368 + nsCOMPtr<nsIAtom> prefix, lName; 1.369 + int32_t nspace; 1.370 + nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix), 1.371 + aContext, getter_AddRefs(lName), 1.372 + nspace); 1.373 + NS_ENSURE_SUCCESS(rv, rv); 1.374 + expr = new VariableRefExpr(prefix, lName, nspace); 1.375 + } 1.376 + break; 1.377 + case Token::L_PAREN: 1.378 + lexer.nextToken(); 1.379 + rv = createExpr(lexer, aContext, getter_Transfers(expr)); 1.380 + NS_ENSURE_SUCCESS(rv, rv); 1.381 + 1.382 + if (lexer.peek()->mType != Token::R_PAREN) { 1.383 + return NS_ERROR_XPATH_PAREN_EXPECTED; 1.384 + } 1.385 + lexer.nextToken(); 1.386 + break; 1.387 + case Token::LITERAL : 1.388 + lexer.nextToken(); 1.389 + expr = new txLiteralExpr(tok->Value()); 1.390 + break; 1.391 + case Token::NUMBER: 1.392 + { 1.393 + lexer.nextToken(); 1.394 + expr = new txLiteralExpr(txDouble::toDouble(tok->Value())); 1.395 + break; 1.396 + } 1.397 + default: 1.398 + return createLocationStep(lexer, aContext, aResult); 1.399 + } 1.400 + 1.401 + if (lexer.peek()->mType == Token::L_BRACKET) { 1.402 + nsAutoPtr<FilterExpr> filterExpr(new FilterExpr(expr)); 1.403 + 1.404 + expr.forget(); 1.405 + 1.406 + //-- handle predicates 1.407 + rv = parsePredicates(filterExpr, lexer, aContext); 1.408 + NS_ENSURE_SUCCESS(rv, rv); 1.409 + expr = filterExpr.forget(); 1.410 + } 1.411 + 1.412 + *aResult = expr.forget(); 1.413 + return NS_OK; 1.414 +} 1.415 + 1.416 +nsresult 1.417 +txExprParser::createFunctionCall(txExprLexer& lexer, txIParseContext* aContext, 1.418 + Expr** aResult) 1.419 +{ 1.420 + *aResult = nullptr; 1.421 + 1.422 + nsAutoPtr<FunctionCall> fnCall; 1.423 + 1.424 + Token* tok = lexer.nextToken(); 1.425 + NS_ASSERTION(tok->mType == Token::FUNCTION_NAME_AND_PAREN, 1.426 + "FunctionCall expected"); 1.427 + 1.428 + //-- compare function names 1.429 + nsCOMPtr<nsIAtom> prefix, lName; 1.430 + int32_t namespaceID; 1.431 + nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext, 1.432 + getter_AddRefs(lName), namespaceID); 1.433 + NS_ENSURE_SUCCESS(rv, rv); 1.434 + 1.435 + txCoreFunctionCall::eType type; 1.436 + if (namespaceID == kNameSpaceID_None && 1.437 + txCoreFunctionCall::getTypeFromAtom(lName, type)) { 1.438 + // It is a known built-in function. 1.439 + fnCall = new txCoreFunctionCall(type); 1.440 + } 1.441 + 1.442 + // check extension functions and xslt 1.443 + if (!fnCall) { 1.444 + rv = aContext->resolveFunctionCall(lName, namespaceID, 1.445 + getter_Transfers(fnCall)); 1.446 + 1.447 + if (rv == NS_ERROR_NOT_IMPLEMENTED) { 1.448 + // this should just happen for unparsed-entity-uri() 1.449 + NS_ASSERTION(!fnCall, "Now is it implemented or not?"); 1.450 + rv = parseParameters(0, lexer, aContext); 1.451 + NS_ENSURE_SUCCESS(rv, rv); 1.452 + 1.453 + *aResult = new txLiteralExpr(tok->Value() + 1.454 + NS_LITERAL_STRING(" not implemented.")); 1.455 + 1.456 + return NS_OK; 1.457 + } 1.458 + 1.459 + NS_ENSURE_SUCCESS(rv, rv); 1.460 + } 1.461 + 1.462 + //-- handle parametes 1.463 + rv = parseParameters(fnCall, lexer, aContext); 1.464 + NS_ENSURE_SUCCESS(rv, rv); 1.465 + 1.466 + *aResult = fnCall.forget(); 1.467 + return NS_OK; 1.468 +} 1.469 + 1.470 +nsresult 1.471 +txExprParser::createLocationStep(txExprLexer& lexer, txIParseContext* aContext, 1.472 + Expr** aExpr) 1.473 +{ 1.474 + *aExpr = nullptr; 1.475 + 1.476 + //-- child axis is default 1.477 + LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS; 1.478 + nsAutoPtr<txNodeTest> nodeTest; 1.479 + 1.480 + //-- get Axis Identifier or AbbreviatedStep, if present 1.481 + Token* tok = lexer.peek(); 1.482 + switch (tok->mType) { 1.483 + case Token::AXIS_IDENTIFIER: 1.484 + { 1.485 + //-- eat token 1.486 + lexer.nextToken(); 1.487 + nsCOMPtr<nsIAtom> axis = do_GetAtom(tok->Value()); 1.488 + if (axis == nsGkAtoms::ancestor) { 1.489 + axisIdentifier = LocationStep::ANCESTOR_AXIS; 1.490 + } 1.491 + else if (axis == nsGkAtoms::ancestorOrSelf) { 1.492 + axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS; 1.493 + } 1.494 + else if (axis == nsGkAtoms::attribute) { 1.495 + axisIdentifier = LocationStep::ATTRIBUTE_AXIS; 1.496 + } 1.497 + else if (axis == nsGkAtoms::child) { 1.498 + axisIdentifier = LocationStep::CHILD_AXIS; 1.499 + } 1.500 + else if (axis == nsGkAtoms::descendant) { 1.501 + axisIdentifier = LocationStep::DESCENDANT_AXIS; 1.502 + } 1.503 + else if (axis == nsGkAtoms::descendantOrSelf) { 1.504 + axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS; 1.505 + } 1.506 + else if (axis == nsGkAtoms::following) { 1.507 + axisIdentifier = LocationStep::FOLLOWING_AXIS; 1.508 + } 1.509 + else if (axis == nsGkAtoms::followingSibling) { 1.510 + axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS; 1.511 + } 1.512 + else if (axis == nsGkAtoms::_namespace) { 1.513 + axisIdentifier = LocationStep::NAMESPACE_AXIS; 1.514 + } 1.515 + else if (axis == nsGkAtoms::parent) { 1.516 + axisIdentifier = LocationStep::PARENT_AXIS; 1.517 + } 1.518 + else if (axis == nsGkAtoms::preceding) { 1.519 + axisIdentifier = LocationStep::PRECEDING_AXIS; 1.520 + } 1.521 + else if (axis == nsGkAtoms::precedingSibling) { 1.522 + axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS; 1.523 + } 1.524 + else if (axis == nsGkAtoms::self) { 1.525 + axisIdentifier = LocationStep::SELF_AXIS; 1.526 + } 1.527 + else { 1.528 + return NS_ERROR_XPATH_INVALID_AXIS; 1.529 + } 1.530 + break; 1.531 + } 1.532 + case Token::AT_SIGN: 1.533 + //-- eat token 1.534 + lexer.nextToken(); 1.535 + axisIdentifier = LocationStep::ATTRIBUTE_AXIS; 1.536 + break; 1.537 + case Token::PARENT_NODE : 1.538 + //-- eat token 1.539 + lexer.nextToken(); 1.540 + axisIdentifier = LocationStep::PARENT_AXIS; 1.541 + nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); 1.542 + break; 1.543 + case Token::SELF_NODE : 1.544 + //-- eat token 1.545 + lexer.nextToken(); 1.546 + axisIdentifier = LocationStep::SELF_AXIS; 1.547 + nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); 1.548 + break; 1.549 + default: 1.550 + break; 1.551 + } 1.552 + 1.553 + //-- get NodeTest unless an AbbreviatedStep was found 1.554 + nsresult rv = NS_OK; 1.555 + if (!nodeTest) { 1.556 + tok = lexer.peek(); 1.557 + 1.558 + if (tok->mType == Token::CNAME) { 1.559 + lexer.nextToken(); 1.560 + // resolve QName 1.561 + nsCOMPtr<nsIAtom> prefix, lName; 1.562 + int32_t nspace; 1.563 + rv = resolveQName(tok->Value(), getter_AddRefs(prefix), 1.564 + aContext, getter_AddRefs(lName), 1.565 + nspace, true); 1.566 + NS_ENSURE_SUCCESS(rv, rv); 1.567 + 1.568 + nodeTest = 1.569 + new txNameTest(prefix, lName, nspace, 1.570 + axisIdentifier == LocationStep::ATTRIBUTE_AXIS ? 1.571 + static_cast<uint16_t>(txXPathNodeType::ATTRIBUTE_NODE) : 1.572 + static_cast<uint16_t>(txXPathNodeType::ELEMENT_NODE)); 1.573 + } 1.574 + else { 1.575 + rv = createNodeTypeTest(lexer, getter_Transfers(nodeTest)); 1.576 + NS_ENSURE_SUCCESS(rv, rv); 1.577 + } 1.578 + } 1.579 + 1.580 + nsAutoPtr<LocationStep> lstep(new LocationStep(nodeTest, axisIdentifier)); 1.581 + 1.582 + nodeTest.forget(); 1.583 + 1.584 + //-- handle predicates 1.585 + rv = parsePredicates(lstep, lexer, aContext); 1.586 + NS_ENSURE_SUCCESS(rv, rv); 1.587 + 1.588 + *aExpr = lstep.forget(); 1.589 + return NS_OK; 1.590 +} 1.591 + 1.592 +/** 1.593 + * This method only handles comment(), text(), processing-instructing() 1.594 + * and node() 1.595 + */ 1.596 +nsresult 1.597 +txExprParser::createNodeTypeTest(txExprLexer& lexer, txNodeTest** aTest) 1.598 +{ 1.599 + *aTest = 0; 1.600 + nsAutoPtr<txNodeTypeTest> nodeTest; 1.601 + 1.602 + Token* nodeTok = lexer.peek(); 1.603 + 1.604 + switch (nodeTok->mType) { 1.605 + case Token::COMMENT_AND_PAREN: 1.606 + lexer.nextToken(); 1.607 + nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE); 1.608 + break; 1.609 + case Token::NODE_AND_PAREN: 1.610 + lexer.nextToken(); 1.611 + nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); 1.612 + break; 1.613 + case Token::PROC_INST_AND_PAREN: 1.614 + lexer.nextToken(); 1.615 + nodeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE); 1.616 + break; 1.617 + case Token::TEXT_AND_PAREN: 1.618 + lexer.nextToken(); 1.619 + nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE); 1.620 + break; 1.621 + default: 1.622 + return NS_ERROR_XPATH_NO_NODE_TYPE_TEST; 1.623 + } 1.624 + 1.625 + NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY); 1.626 + 1.627 + if (nodeTok->mType == Token::PROC_INST_AND_PAREN && 1.628 + lexer.peek()->mType == Token::LITERAL) { 1.629 + Token* tok = lexer.nextToken(); 1.630 + nodeTest->setNodeName(tok->Value()); 1.631 + } 1.632 + if (lexer.peek()->mType != Token::R_PAREN) { 1.633 + return NS_ERROR_XPATH_PAREN_EXPECTED; 1.634 + } 1.635 + lexer.nextToken(); 1.636 + 1.637 + *aTest = nodeTest.forget(); 1.638 + return NS_OK; 1.639 +} 1.640 + 1.641 +/** 1.642 + * Creates a PathExpr using the given txExprLexer 1.643 + * @param lexer the txExprLexer for retrieving Tokens 1.644 + */ 1.645 +nsresult 1.646 +txExprParser::createPathExpr(txExprLexer& lexer, txIParseContext* aContext, 1.647 + Expr** aResult) 1.648 +{ 1.649 + *aResult = nullptr; 1.650 + 1.651 + nsAutoPtr<Expr> expr; 1.652 + 1.653 + Token* tok = lexer.peek(); 1.654 + 1.655 + // is this a root expression? 1.656 + if (tok->mType == Token::PARENT_OP) { 1.657 + if (!isLocationStepToken(lexer.peekAhead())) { 1.658 + lexer.nextToken(); 1.659 + *aResult = new RootExpr(); 1.660 + return NS_OK; 1.661 + } 1.662 + } 1.663 + 1.664 + // parse first step (possibly a FilterExpr) 1.665 + nsresult rv = NS_OK; 1.666 + if (tok->mType != Token::PARENT_OP && 1.667 + tok->mType != Token::ANCESTOR_OP) { 1.668 + rv = createFilterOrStep(lexer, aContext, getter_Transfers(expr)); 1.669 + NS_ENSURE_SUCCESS(rv, rv); 1.670 + 1.671 + // is this a singlestep path expression? 1.672 + tok = lexer.peek(); 1.673 + if (tok->mType != Token::PARENT_OP && 1.674 + tok->mType != Token::ANCESTOR_OP) { 1.675 + *aResult = expr.forget(); 1.676 + return NS_OK; 1.677 + } 1.678 + } 1.679 + else { 1.680 + expr = new RootExpr(); 1.681 + 1.682 +#ifdef TX_TO_STRING 1.683 + static_cast<RootExpr*>(expr.get())->setSerialize(false); 1.684 +#endif 1.685 + } 1.686 + 1.687 + // We have a PathExpr containing several steps 1.688 + nsAutoPtr<PathExpr> pathExpr(new PathExpr()); 1.689 + 1.690 + rv = pathExpr->addExpr(expr, PathExpr::RELATIVE_OP); 1.691 + NS_ENSURE_SUCCESS(rv, rv); 1.692 + 1.693 + expr.forget(); 1.694 + 1.695 + // this is ugly 1.696 + while (1) { 1.697 + PathExpr::PathOperator pathOp; 1.698 + switch (lexer.peek()->mType) { 1.699 + case Token::ANCESTOR_OP : 1.700 + pathOp = PathExpr::DESCENDANT_OP; 1.701 + break; 1.702 + case Token::PARENT_OP : 1.703 + pathOp = PathExpr::RELATIVE_OP; 1.704 + break; 1.705 + default: 1.706 + *aResult = pathExpr.forget(); 1.707 + return NS_OK; 1.708 + } 1.709 + lexer.nextToken(); 1.710 + 1.711 + rv = createLocationStep(lexer, aContext, getter_Transfers(expr)); 1.712 + NS_ENSURE_SUCCESS(rv, rv); 1.713 + 1.714 + rv = pathExpr->addExpr(expr, pathOp); 1.715 + NS_ENSURE_SUCCESS(rv, rv); 1.716 + 1.717 + expr.forget(); 1.718 + } 1.719 + NS_NOTREACHED("internal xpath parser error"); 1.720 + return NS_ERROR_UNEXPECTED; 1.721 +} 1.722 + 1.723 +/** 1.724 + * Creates a PathExpr using the given txExprLexer 1.725 + * @param lexer the txExprLexer for retrieving Tokens 1.726 + */ 1.727 +nsresult 1.728 +txExprParser::createUnionExpr(txExprLexer& lexer, txIParseContext* aContext, 1.729 + Expr** aResult) 1.730 +{ 1.731 + *aResult = nullptr; 1.732 + 1.733 + nsAutoPtr<Expr> expr; 1.734 + nsresult rv = createPathExpr(lexer, aContext, getter_Transfers(expr)); 1.735 + NS_ENSURE_SUCCESS(rv, rv); 1.736 + 1.737 + if (lexer.peek()->mType != Token::UNION_OP) { 1.738 + *aResult = expr.forget(); 1.739 + return NS_OK; 1.740 + } 1.741 + 1.742 + nsAutoPtr<UnionExpr> unionExpr(new UnionExpr()); 1.743 + 1.744 + rv = unionExpr->addExpr(expr); 1.745 + NS_ENSURE_SUCCESS(rv, rv); 1.746 + 1.747 + expr.forget(); 1.748 + 1.749 + while (lexer.peek()->mType == Token::UNION_OP) { 1.750 + lexer.nextToken(); //-- eat token 1.751 + 1.752 + rv = createPathExpr(lexer, aContext, getter_Transfers(expr)); 1.753 + NS_ENSURE_SUCCESS(rv, rv); 1.754 + 1.755 + rv = unionExpr->addExpr(expr.forget()); 1.756 + NS_ENSURE_SUCCESS(rv, rv); 1.757 + } 1.758 + 1.759 + *aResult = unionExpr.forget(); 1.760 + return NS_OK; 1.761 +} 1.762 + 1.763 +bool 1.764 +txExprParser::isLocationStepToken(Token* aToken) 1.765 +{ 1.766 + // We could put these in consecutive order in ExprLexer.h for speed 1.767 + return aToken->mType == Token::AXIS_IDENTIFIER || 1.768 + aToken->mType == Token::AT_SIGN || 1.769 + aToken->mType == Token::PARENT_NODE || 1.770 + aToken->mType == Token::SELF_NODE || 1.771 + aToken->mType == Token::CNAME || 1.772 + aToken->mType == Token::COMMENT_AND_PAREN || 1.773 + aToken->mType == Token::NODE_AND_PAREN || 1.774 + aToken->mType == Token::PROC_INST_AND_PAREN || 1.775 + aToken->mType == Token::TEXT_AND_PAREN; 1.776 +} 1.777 + 1.778 +/** 1.779 + * Using the given lexer, parses the tokens if they represent a predicate list 1.780 + * If an error occurs a non-zero String pointer will be returned containing the 1.781 + * error message. 1.782 + * @param predicateList, the PredicateList to add predicate expressions to 1.783 + * @param lexer the txExprLexer to use for parsing tokens 1.784 + * @return 0 if successful, or a String pointer to the error message 1.785 + */ 1.786 +nsresult 1.787 +txExprParser::parsePredicates(PredicateList* aPredicateList, 1.788 + txExprLexer& lexer, txIParseContext* aContext) 1.789 +{ 1.790 + nsAutoPtr<Expr> expr; 1.791 + nsresult rv = NS_OK; 1.792 + while (lexer.peek()->mType == Token::L_BRACKET) { 1.793 + //-- eat Token 1.794 + lexer.nextToken(); 1.795 + 1.796 + rv = createExpr(lexer, aContext, getter_Transfers(expr)); 1.797 + NS_ENSURE_SUCCESS(rv, rv); 1.798 + 1.799 + rv = aPredicateList->add(expr); 1.800 + NS_ENSURE_SUCCESS(rv, rv); 1.801 + 1.802 + expr.forget(); 1.803 + 1.804 + if (lexer.peek()->mType != Token::R_BRACKET) { 1.805 + return NS_ERROR_XPATH_BRACKET_EXPECTED; 1.806 + } 1.807 + lexer.nextToken(); 1.808 + } 1.809 + return NS_OK; 1.810 +} 1.811 + 1.812 + 1.813 +/** 1.814 + * Using the given lexer, parses the tokens if they represent a parameter list 1.815 + * If an error occurs a non-zero String pointer will be returned containing the 1.816 + * error message. 1.817 + * @param list, the List to add parameter expressions to 1.818 + * @param lexer the txExprLexer to use for parsing tokens 1.819 + * @return NS_OK if successful, or another rv otherwise 1.820 + */ 1.821 +nsresult 1.822 +txExprParser::parseParameters(FunctionCall* aFnCall, txExprLexer& lexer, 1.823 + txIParseContext* aContext) 1.824 +{ 1.825 + if (lexer.peek()->mType == Token::R_PAREN) { 1.826 + lexer.nextToken(); 1.827 + return NS_OK; 1.828 + } 1.829 + 1.830 + nsAutoPtr<Expr> expr; 1.831 + nsresult rv = NS_OK; 1.832 + while (1) { 1.833 + rv = createExpr(lexer, aContext, getter_Transfers(expr)); 1.834 + NS_ENSURE_SUCCESS(rv, rv); 1.835 + 1.836 + if (aFnCall) { 1.837 + rv = aFnCall->addParam(expr.forget()); 1.838 + NS_ENSURE_SUCCESS(rv, rv); 1.839 + } 1.840 + 1.841 + switch (lexer.peek()->mType) { 1.842 + case Token::R_PAREN : 1.843 + lexer.nextToken(); 1.844 + return NS_OK; 1.845 + case Token::COMMA: //-- param separator 1.846 + lexer.nextToken(); 1.847 + break; 1.848 + default: 1.849 + return NS_ERROR_XPATH_PAREN_EXPECTED; 1.850 + } 1.851 + } 1.852 + 1.853 + NS_NOTREACHED("internal xpath parser error"); 1.854 + return NS_ERROR_UNEXPECTED; 1.855 +} 1.856 + 1.857 +short 1.858 +txExprParser::precedence(Token* aToken) 1.859 +{ 1.860 + switch (aToken->mType) { 1.861 + case Token::OR_OP: 1.862 + return 1; 1.863 + case Token::AND_OP: 1.864 + return 2; 1.865 + //-- equality 1.866 + case Token::EQUAL_OP: 1.867 + case Token::NOT_EQUAL_OP: 1.868 + return 3; 1.869 + //-- relational 1.870 + case Token::LESS_THAN_OP: 1.871 + case Token::GREATER_THAN_OP: 1.872 + case Token::LESS_OR_EQUAL_OP: 1.873 + case Token::GREATER_OR_EQUAL_OP: 1.874 + return 4; 1.875 + //-- additive operators 1.876 + case Token::ADDITION_OP: 1.877 + case Token::SUBTRACTION_OP: 1.878 + return 5; 1.879 + //-- multiplicative 1.880 + case Token::DIVIDE_OP: 1.881 + case Token::MULTIPLY_OP: 1.882 + case Token::MODULUS_OP: 1.883 + return 6; 1.884 + default: 1.885 + break; 1.886 + } 1.887 + return 0; 1.888 +} 1.889 + 1.890 +nsresult 1.891 +txExprParser::resolveQName(const nsAString& aQName, 1.892 + nsIAtom** aPrefix, txIParseContext* aContext, 1.893 + nsIAtom** aLocalName, int32_t& aNamespace, 1.894 + bool aIsNameTest) 1.895 +{ 1.896 + aNamespace = kNameSpaceID_None; 1.897 + int32_t idx = aQName.FindChar(':'); 1.898 + if (idx > 0) { 1.899 + *aPrefix = NS_NewAtom(StringHead(aQName, (uint32_t)idx)).take(); 1.900 + if (!*aPrefix) { 1.901 + return NS_ERROR_OUT_OF_MEMORY; 1.902 + } 1.903 + *aLocalName = NS_NewAtom(Substring(aQName, (uint32_t)idx + 1, 1.904 + aQName.Length() - (idx + 1))).take(); 1.905 + if (!*aLocalName) { 1.906 + NS_RELEASE(*aPrefix); 1.907 + return NS_ERROR_OUT_OF_MEMORY; 1.908 + } 1.909 + return aContext->resolveNamespacePrefix(*aPrefix, aNamespace); 1.910 + } 1.911 + // the lexer dealt with idx == 0 1.912 + *aPrefix = 0; 1.913 + if (aIsNameTest && aContext->caseInsensitiveNameTests()) { 1.914 + nsAutoString lcname; 1.915 + nsContentUtils::ASCIIToLower(aQName, lcname); 1.916 + *aLocalName = NS_NewAtom(lcname).take(); 1.917 + } 1.918 + else { 1.919 + *aLocalName = NS_NewAtom(aQName).take(); 1.920 + } 1.921 + if (!*aLocalName) { 1.922 + return NS_ERROR_OUT_OF_MEMORY; 1.923 + } 1.924 + return NS_OK; 1.925 +}