LCOV - code coverage report
Current view: top level - dom/xslt/xpath - txExprParser.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 473 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13