LCOV - code coverage report
Current view: directory - content/xslt/src/xpath - txExprParser.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 450 93 20.7 %
Date: 2012-06-02 Functions: 15 8 53.3 %

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

Generated by: LCOV version 1.7