dom/xslt/xpath/txExprParser.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial