зеркало из https://github.com/mozilla/gecko-dev.git
bug 206445, nsresult based error reporting in XPath expression parser and lexer, r=sicking, sr=peterv
This commit is contained in:
Родитель
e608b7e0f4
Коммит
9ee5c3e892
|
@ -38,7 +38,7 @@
|
|||
1 = Parsing an XSLT stylesheet failed.
|
||||
2 = Parsing an XPath expression failed.
|
||||
4 = XSLT transformation failed.
|
||||
5 = XSLT/XPath tried to call an unknown function.
|
||||
5 = Invalid XSLT/XPath function.
|
||||
6 = XSLT Stylesheet (possibly) contains a recursion.
|
||||
7 = Attribute value illegal in XSLT 1.0.
|
||||
8 = An XPath expression was expected to return a NodeSet.
|
||||
|
@ -47,6 +47,19 @@
|
|||
11 = An XSLT stylesheet does not have an XML mimetype:
|
||||
12 = An XSLT stylesheet directly or indirectly imports or includes itself:
|
||||
13 = An XPath function was called with the wrong number of arguments.
|
||||
14 = An unknown XPath extension function was called.
|
||||
15 = XPath parse failure: ')' expected:
|
||||
16 = XPath parse failure: invalid axis:
|
||||
17 = XPath parse failure: Name or Nodetype test expected:
|
||||
18 = XPath parse failure: ']' expected:
|
||||
19 = XPath parse failure: invalid variable name:
|
||||
20 = XPath parse failure: unexpected end of expression:
|
||||
21 = XPath parse failure: operator expected:
|
||||
22 = XPath parse failure: unclosed literal:
|
||||
23 = XPath parse failure: ':' unexpected:
|
||||
24 = XPath parse failure: '!' unexpected, negation is not():
|
||||
25 = XPath parse failure: illegal character found:
|
||||
26 = XPath parse failure: binary operator expected:
|
||||
|
||||
LoadingError = Error loading stylesheet: %S
|
||||
TransformError = Error during XSLT transformation: %S
|
||||
|
|
|
@ -90,4 +90,43 @@
|
|||
#define NS_ERROR_XPATH_BAD_ARGUMENT_COUNT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 13)
|
||||
|
||||
#define NS_ERROR_XPATH_BAD_EXTENSION_FUNCTION \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 14)
|
||||
|
||||
#define NS_ERROR_XPATH_PAREN_EXPECTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 15)
|
||||
|
||||
#define NS_ERROR_XPATH_INVALID_AXIS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 16)
|
||||
|
||||
#define NS_ERROR_XPATH_NO_NODE_TYPE_TEST \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 17)
|
||||
|
||||
#define NS_ERROR_XPATH_BRACKET_EXPECTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 18)
|
||||
|
||||
#define NS_ERROR_XPATH_INVALID_VAR_NAME \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 19)
|
||||
|
||||
#define NS_ERROR_XPATH_UNEXPECTED_END \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 20)
|
||||
|
||||
#define NS_ERROR_XPATH_OPERATOR_EXPECTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 21)
|
||||
|
||||
#define NS_ERROR_XPATH_UNCLOSED_LITERAL \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 22)
|
||||
|
||||
#define NS_ERROR_XPATH_BAD_COLON \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 23)
|
||||
|
||||
#define NS_ERROR_XPATH_BAD_BANG \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 24)
|
||||
|
||||
#define NS_ERROR_XPATH_ILLEGAL_CHAR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 25)
|
||||
|
||||
#define NS_ERROR_XPATH_BINARY_EXPECTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 26)
|
||||
|
||||
#endif // __TX_ERROR
|
||||
|
|
|
@ -26,7 +26,8 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
SIMPLE_PROGRAMS = transformiix$(BIN_SUFFIX) testXalan$(BIN_SUFFIX)
|
||||
SIMPLE_PROGRAMS = transformiix$(BIN_SUFFIX) testXalan$(BIN_SUFFIX) \
|
||||
txTestExpr$(BIN_SUFFIX)
|
||||
ifdef MARK_INC
|
||||
SIMPLE_PROGRAMS += txXSLTMarkDriver$(BIN_SUFFIX)
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is TransforMiiX XSLT Processor.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Axel Hecht.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Axel Hecht <axel@pike.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "txStandaloneXSLTProcessor.h"
|
||||
#include "nsString.h"
|
||||
#include "ExprParser.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
/**
|
||||
* A ExprParser test exe
|
||||
*/
|
||||
|
||||
static const char* kTokens[] = {"(", "concat", "(", "foo", ",", "'", "bar",
|
||||
"'",")", "//", ".", "[", "preceding-sibling",
|
||||
"::", "bar", "]", "/", "*", "[", "23", "]",
|
||||
"|", "node", "(", ")", ")", "<", "3"};
|
||||
static const PRUint8 kCount = sizeof(kTokens)/sizeof(char*);
|
||||
|
||||
class ParseContextImpl : public txIParseContext
|
||||
{
|
||||
public:
|
||||
nsresult
|
||||
resolveNamespacePrefix(nsIAtom* aPrefix, PRInt32& aID)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsresult
|
||||
resolveFunctionCall(nsIAtom* aName, PRInt32 aID, FunctionCall*& aFunction)
|
||||
{
|
||||
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
|
||||
}
|
||||
PRBool
|
||||
caseInsensitiveNameTests()
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
void
|
||||
SetErrorOffset(PRUint32 aOffset)
|
||||
{
|
||||
mOff = aOffset;
|
||||
}
|
||||
PRUint32 mOff;
|
||||
};
|
||||
|
||||
static void doTest(const nsASingleFragmentString& aExpr)
|
||||
{
|
||||
ParseContextImpl ct;
|
||||
nsAutoPtr<Expr> expression;
|
||||
cout << NS_LossyConvertUTF16toASCII(aExpr).get() << endl;
|
||||
ct.mOff = 0;
|
||||
nsresult rv = txExprParser::createExpr(aExpr, &ct,
|
||||
getter_Transfers(expression));
|
||||
|
||||
cout << "createExpr returned " << hex << rv << dec;
|
||||
cout << " at " << ct.mOff << endl;
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_LossyConvertUTF16toASCII cstring(aExpr);
|
||||
cout << NS_LossyConvertUTF16toASCII(StringHead(aExpr, ct.mOff)).get();
|
||||
cout << " ^ ";
|
||||
cout << NS_LossyConvertUTF16toASCII(StringTail(aExpr, aExpr.Length()-ct.mOff)).get();
|
||||
cout << endl << endl;
|
||||
}
|
||||
else {
|
||||
nsAutoString expr;
|
||||
expression->toString(expr);
|
||||
cout << "parsed expression: ";
|
||||
cout << NS_LossyConvertUTF16toASCII(expr).get() << endl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using namespace std;
|
||||
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!txXSLTProcessor::init())
|
||||
return 1;
|
||||
|
||||
nsAutoString exprOrig, expr;
|
||||
nsStringArray exprHead, exprTail;
|
||||
PRUint8 i, dropStart, dropEnd;
|
||||
exprHead.AppendString(NS_ConvertASCIItoUTF16(kTokens[0]));
|
||||
exprTail.AppendString(NS_ConvertASCIItoUTF16(kTokens[kCount - 1]));
|
||||
for (i = 2; i < kCount; ++i) {
|
||||
exprHead.AppendString(*exprHead[i - 2] +
|
||||
NS_ConvertASCIItoUTF16(kTokens[i - 1]));
|
||||
exprTail.AppendString(NS_ConvertASCIItoUTF16(kTokens[kCount - i]) +
|
||||
*exprTail[i - 2]);
|
||||
}
|
||||
exprOrig = NS_ConvertASCIItoUTF16(kTokens[0]) + *exprTail[kCount - 2];
|
||||
cout << NS_LossyConvertUTF16toASCII(exprOrig).get() << endl << endl;
|
||||
for (dropStart = 0; dropStart < kCount - 2; ++dropStart) {
|
||||
doTest(*exprTail[kCount - 2 - dropStart]);
|
||||
for (dropEnd = kCount - 3 - dropStart; dropEnd > 0; --dropEnd) {
|
||||
expr = *exprHead[dropStart] + *exprTail[dropEnd];
|
||||
doTest(expr);
|
||||
}
|
||||
doTest(*exprHead[dropStart]);
|
||||
}
|
||||
doTest(*exprHead[kCount - 2]);
|
||||
|
||||
txXSLTProcessor::shutdown();
|
||||
rv = NS_ShutdownXPCOM(nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return 0;
|
||||
}
|
|
@ -35,20 +35,6 @@
|
|||
#include "primitives.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
/**
|
||||
* Creates a new AdditiveExpr using the given operator
|
||||
**/
|
||||
AdditiveExpr::AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op) {
|
||||
this->op = op;
|
||||
this->leftExpr = leftExpr;
|
||||
this->rightExpr = rightExpr;
|
||||
} //-- AdditiveExpr
|
||||
|
||||
AdditiveExpr::~AdditiveExpr() {
|
||||
delete leftExpr;
|
||||
delete rightExpr;
|
||||
} //-- ~AdditiveExpr
|
||||
|
||||
/**
|
||||
* Evaluates this Expr based on the given context node and processor state
|
||||
* @param context the context node for evaluation of this Expr
|
||||
|
|
|
@ -38,20 +38,6 @@
|
|||
#include "ExprResult.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
/**
|
||||
* Creates a new BooleanExpr using the given operator
|
||||
**/
|
||||
BooleanExpr::BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op) {
|
||||
this->op = op;
|
||||
this->leftExpr = leftExpr;
|
||||
this->rightExpr = rightExpr;
|
||||
} //-- BooleanExpr
|
||||
|
||||
BooleanExpr::~BooleanExpr() {
|
||||
delete leftExpr;
|
||||
delete rightExpr;
|
||||
} //-- ~BooleanExpr
|
||||
|
||||
/**
|
||||
* Evaluates this Expr based on the given context node and processor state
|
||||
* @param context the context node for evaluation of this Expr
|
||||
|
|
|
@ -116,9 +116,12 @@ public:
|
|||
void toString(nsAString& aDest);
|
||||
|
||||
/**
|
||||
* Adds the given parameter to this FunctionCall's parameter list
|
||||
* @param expr the Expr to add to this FunctionCall's parameter list
|
||||
**/
|
||||
* Adds the given parameter to this FunctionCall's parameter list.
|
||||
* The ownership of the given Expr is passed over to the FunctionCall,
|
||||
* even on failure.
|
||||
* @param aExpr the Expr to add to this FunctionCall's parameter list
|
||||
* @return nsresult indicating out of memory
|
||||
*/
|
||||
nsresult addParam(Expr* aExpr);
|
||||
|
||||
/**
|
||||
|
@ -294,10 +297,13 @@ public:
|
|||
virtual ~PredicateList();
|
||||
|
||||
/**
|
||||
* Adds the given Expr to the list
|
||||
* @param expr the Expr to add to the list
|
||||
**/
|
||||
void add(Expr* expr);
|
||||
* Adds the given Expr to the list.
|
||||
* The ownership of the given Expr is passed over the PredicateList,
|
||||
* even on failure.
|
||||
* @param aExpr the Expr to add to the list
|
||||
* @return nsresult indicating out of memory
|
||||
*/
|
||||
nsresult add(Expr* aExpr);
|
||||
|
||||
nsresult evaluatePredicates(NodeSet* aNodes, txIMatchContext* aContext);
|
||||
|
||||
|
@ -348,7 +354,12 @@ public:
|
|||
* @param nodeExpr the NodeExpr to use when matching Nodes
|
||||
* @param axisIdentifier the Axis Identifier in which to search for nodes
|
||||
**/
|
||||
LocationStep(nsAutoPtr<txNodeTest> aNodeTest, LocationStepType aAxisIdentifier);
|
||||
LocationStep(nsAutoPtr<txNodeTest>& aNodeTest,
|
||||
LocationStepType aAxisIdentifier)
|
||||
: mNodeTest(aNodeTest),
|
||||
mAxisIdentifier(aAxisIdentifier)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
|
@ -372,18 +383,16 @@ public:
|
|||
/**
|
||||
* Creates a new FilterExpr using the given Expr
|
||||
* @param expr the Expr to use for evaluation
|
||||
**/
|
||||
FilterExpr(Expr* aExpr);
|
||||
|
||||
/**
|
||||
* Destructor, will delete all predicates and the given Expr
|
||||
**/
|
||||
virtual ~FilterExpr();
|
||||
*/
|
||||
FilterExpr(nsAutoPtr<Expr>& aExpr)
|
||||
: expr(aExpr)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
Expr* expr;
|
||||
nsAutoPtr<Expr> expr;
|
||||
|
||||
}; //-- FilterExpr
|
||||
|
||||
|
@ -413,15 +422,19 @@ public:
|
|||
//-- LF, changed from static const short to enum
|
||||
enum _AdditiveExprType { ADDITION = 1, SUBTRACTION };
|
||||
|
||||
AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op);
|
||||
~AdditiveExpr();
|
||||
AdditiveExpr(nsAutoPtr<Expr>& aLeftExpr, nsAutoPtr<Expr>& aRightExpr,
|
||||
short aOp)
|
||||
: op(aOp),
|
||||
leftExpr(aLeftExpr),
|
||||
rightExpr(aRightExpr)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
short op;
|
||||
Expr* leftExpr;
|
||||
Expr* rightExpr;
|
||||
nsAutoPtr<Expr> leftExpr, rightExpr;
|
||||
}; //-- AdditiveExpr
|
||||
|
||||
/**
|
||||
|
@ -431,13 +444,15 @@ class UnaryExpr : public Expr {
|
|||
|
||||
public:
|
||||
|
||||
UnaryExpr(Expr* expr);
|
||||
~UnaryExpr();
|
||||
UnaryExpr(nsAutoPtr<Expr>& aExpr)
|
||||
: expr(aExpr)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
Expr* expr;
|
||||
nsAutoPtr<Expr> expr;
|
||||
}; //-- UnaryExpr
|
||||
|
||||
/**
|
||||
|
@ -451,15 +466,19 @@ public:
|
|||
//-- BooleanExpr Types
|
||||
enum _BooleanExprType { AND = 1, OR };
|
||||
|
||||
BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op);
|
||||
~BooleanExpr();
|
||||
BooleanExpr(nsAutoPtr<Expr>& aLeftExpr, nsAutoPtr<Expr>& aRightExpr,
|
||||
short aOp)
|
||||
: op(aOp),
|
||||
leftExpr(aLeftExpr),
|
||||
rightExpr(aRightExpr)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
short op;
|
||||
Expr* leftExpr;
|
||||
Expr* rightExpr;
|
||||
nsAutoPtr<Expr> leftExpr, rightExpr;
|
||||
}; //-- BooleanExpr
|
||||
|
||||
/**
|
||||
|
@ -478,15 +497,20 @@ public:
|
|||
//-- LF, changed from static const short to enum
|
||||
enum _MultiplicativeExprType { DIVIDE = 1, MULTIPLY, MODULUS };
|
||||
|
||||
MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op);
|
||||
~MultiplicativeExpr();
|
||||
MultiplicativeExpr(nsAutoPtr<Expr>& aLeftExpr,
|
||||
nsAutoPtr<Expr>& aRightExpr,
|
||||
short aOp)
|
||||
: op(aOp),
|
||||
leftExpr(aLeftExpr),
|
||||
rightExpr(aRightExpr)
|
||||
{
|
||||
}
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
short op;
|
||||
Expr* leftExpr;
|
||||
Expr* rightExpr;
|
||||
nsAutoPtr<Expr> leftExpr, rightExpr;
|
||||
}; //-- MultiplicativeExpr
|
||||
|
||||
/**
|
||||
|
@ -511,7 +535,14 @@ public:
|
|||
GREATER_OR_EQUAL
|
||||
};
|
||||
|
||||
RelationalExpr(Expr* aLeftExpr, Expr* aRightExpr, RelationalExprType aOp);
|
||||
RelationalExpr(nsAutoPtr<Expr>& aLeftExpr, nsAutoPtr<Expr>& aRightExpr,
|
||||
RelationalExprType aOp)
|
||||
: mLeftExpr(aLeftExpr),
|
||||
mRightExpr(aRightExpr),
|
||||
mOp(aOp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
|
@ -567,15 +598,23 @@ public:
|
|||
|
||||
/**
|
||||
* Adds the Expr to this PathExpr
|
||||
* @param expr the Expr to add to this PathExpr
|
||||
**/
|
||||
void addExpr(Expr* expr, PathOperator pathOp);
|
||||
* The ownership of the given Expr is passed over the PathExpr,
|
||||
* even on failure.
|
||||
* @param aExpr the Expr to add to this PathExpr
|
||||
* @return nsresult indicating out of memory
|
||||
*/
|
||||
nsresult addExpr(Expr* aExpr, PathOperator pathOp);
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
private:
|
||||
struct PathExprItem {
|
||||
Expr* expr;
|
||||
class PathExprItem {
|
||||
public:
|
||||
PathExprItem(Expr* aExpr, PathOperator aOp)
|
||||
: expr(aExpr),
|
||||
pathOp(aOp)
|
||||
{}
|
||||
nsAutoPtr<Expr> expr;
|
||||
PathOperator pathOp;
|
||||
};
|
||||
|
||||
|
@ -631,9 +670,12 @@ public:
|
|||
|
||||
/**
|
||||
* Adds the PathExpr to this UnionExpr
|
||||
* @param expr the Expr to add to this UnionExpr
|
||||
**/
|
||||
void addExpr(Expr* expr);
|
||||
* The ownership of the given Expr is passed over the UnionExpr,
|
||||
* even on failure.
|
||||
* @param aExpr the Expr to add to this UnionExpr
|
||||
* @return nsresult indicating out of memory
|
||||
*/
|
||||
nsresult addExpr(Expr* aExpr);
|
||||
|
||||
TX_DECL_EXPR;
|
||||
|
||||
|
@ -643,7 +685,6 @@ private:
|
|||
|
||||
}; //-- UnionExpr
|
||||
|
||||
/* */
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -36,451 +36,363 @@
|
|||
|
||||
/**
|
||||
* Lexical analyzer for XPath expressions
|
||||
**/
|
||||
*/
|
||||
|
||||
#include "ExprLexer.h"
|
||||
#include "txAtoms.h"
|
||||
#include "txStringUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "XMLUtils.h"
|
||||
|
||||
//---------------------------/
|
||||
//- Implementation of Token -/
|
||||
//---------------------------/
|
||||
|
||||
/**
|
||||
* Creates a new ExprLexer
|
||||
*/
|
||||
txExprLexer::txExprLexer()
|
||||
: mCurrentItem(nsnull),
|
||||
mFirstItem(nsnull),
|
||||
mLastItem(nsnull),
|
||||
mTokenCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for Token
|
||||
**/
|
||||
Token::Token()
|
||||
{
|
||||
this->type =0;
|
||||
} //-- Token;
|
||||
|
||||
/**
|
||||
* Constructor for Token
|
||||
* @param type, the type of Token being represented
|
||||
**/
|
||||
Token::Token(short type)
|
||||
{
|
||||
this->type = type;
|
||||
} //-- Token;
|
||||
|
||||
/**
|
||||
* Constructor for Token
|
||||
* @param value the value of this Token
|
||||
* @param type, the type of Token being represented
|
||||
**/
|
||||
Token::Token(const nsAString& value, short type)
|
||||
{
|
||||
this->type = type;
|
||||
//-- make copy of value String
|
||||
this->value = value;
|
||||
} //-- Token
|
||||
|
||||
Token::Token(PRUnichar uniChar, short type)
|
||||
{
|
||||
this->type = type;
|
||||
this->value.Append(uniChar);
|
||||
} //-- Token
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
**/
|
||||
Token::Token(const Token& token)
|
||||
{
|
||||
this->type = token.type;
|
||||
this->value = token.value;
|
||||
} //-- Token
|
||||
|
||||
/**
|
||||
* Destructor for Token
|
||||
**/
|
||||
Token::~Token()
|
||||
{
|
||||
//-- currently nothing is needed
|
||||
} //-- ~Token
|
||||
|
||||
|
||||
//--------------------------------/
|
||||
//- Implementation of ExprLexer -/
|
||||
//-------------------------------/
|
||||
|
||||
//---------------/
|
||||
//- Contructors -/
|
||||
//---------------/
|
||||
|
||||
/**
|
||||
* Creates a new ExprLexer using the given string
|
||||
**/
|
||||
ExprLexer::ExprLexer(const nsAFlatString& pattern)
|
||||
{
|
||||
firstItem = 0;
|
||||
lastItem = 0;
|
||||
tokenCount = 0;
|
||||
prevToken = 0;
|
||||
endToken.type = Token::END;
|
||||
parse(pattern);
|
||||
currentItem = firstItem;
|
||||
} //-- ExprLexer
|
||||
|
||||
/**
|
||||
* Destroys this instance of an ExprLexer
|
||||
**/
|
||||
ExprLexer::~ExprLexer()
|
||||
* Destroys this instance of an txExprLexer
|
||||
*/
|
||||
txExprLexer::~txExprLexer()
|
||||
{
|
||||
//-- delete tokens
|
||||
currentItem = firstItem;
|
||||
while (currentItem) {
|
||||
TokenListItem* temp = currentItem->next;
|
||||
delete currentItem->token;
|
||||
delete currentItem;
|
||||
currentItem = temp;
|
||||
Token* tok = mFirstItem;
|
||||
while (tok) {
|
||||
Token* temp = tok->mNext;
|
||||
delete tok;
|
||||
tok = temp;
|
||||
}
|
||||
} //-- ~ExprLexer
|
||||
mCurrentItem = nsnull;
|
||||
}
|
||||
|
||||
|
||||
MBool ExprLexer::hasMoreTokens()
|
||||
Token*
|
||||
txExprLexer::nextToken()
|
||||
{
|
||||
return (currentItem != 0);
|
||||
} //-- hasMoreTokens
|
||||
NS_ASSERTION(mCurrentItem, "nextToken called beyoned the end");
|
||||
Token* token = mCurrentItem;
|
||||
mCurrentItem = mCurrentItem->mNext;
|
||||
return token;
|
||||
}
|
||||
|
||||
Token* ExprLexer::nextToken()
|
||||
void
|
||||
txExprLexer::pushBack()
|
||||
{
|
||||
if (currentItem) {
|
||||
Token* token = currentItem->token;
|
||||
currentItem = currentItem->next;
|
||||
return token;
|
||||
mCurrentItem = mCurrentItem ? mCurrentItem->mPrevious : mLastItem;
|
||||
}
|
||||
|
||||
void
|
||||
txExprLexer::addToken(Token* aToken)
|
||||
{
|
||||
if (mLastItem) {
|
||||
aToken->mPrevious = mLastItem;
|
||||
mLastItem->mNext = aToken;
|
||||
}
|
||||
return &endToken;
|
||||
} //-- nextToken
|
||||
|
||||
void ExprLexer::pushBack()
|
||||
{
|
||||
if (!currentItem)
|
||||
currentItem = lastItem;
|
||||
else
|
||||
currentItem = currentItem->previous;
|
||||
} //-- pushBack
|
||||
|
||||
Token* ExprLexer::peek()
|
||||
{
|
||||
if (currentItem)
|
||||
return currentItem->token;
|
||||
return &endToken;
|
||||
} //-- peek
|
||||
|
||||
void ExprLexer::addToken(Token* token)
|
||||
{
|
||||
TokenListItem* tlItem = new TokenListItem;
|
||||
tlItem->token = token;
|
||||
tlItem->next = 0;
|
||||
if (lastItem) {
|
||||
tlItem->previous = lastItem;
|
||||
lastItem->next = tlItem;
|
||||
if (!mFirstItem) {
|
||||
mFirstItem = aToken;
|
||||
mCurrentItem = aToken;
|
||||
}
|
||||
if (!firstItem)
|
||||
firstItem = tlItem;
|
||||
lastItem = tlItem;
|
||||
prevToken = token;
|
||||
++tokenCount;
|
||||
} //-- addToken
|
||||
mLastItem = aToken;
|
||||
++mTokenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the following Token should be an operator.
|
||||
* This is a helper for the first bullet of [XPath 3.7]
|
||||
* Lexical Structure
|
||||
**/
|
||||
MBool ExprLexer::nextIsOperatorToken(Token* token)
|
||||
*/
|
||||
PRBool
|
||||
txExprLexer::nextIsOperatorToken(Token* aToken)
|
||||
{
|
||||
if (!token || token->type == Token::NULL_TOKEN)
|
||||
return MB_FALSE;
|
||||
if (!aToken || aToken->mType == Token::NULL_TOKEN) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* This relies on the tokens having the right order in ExprLexer.h */
|
||||
if (token->type >= Token::COMMA &&
|
||||
token->type <= Token::UNION_OP)
|
||||
return MB_FALSE;
|
||||
return MB_TRUE;
|
||||
} //-- nextIsOperatorToken
|
||||
return aToken->mType < Token::COMMA ||
|
||||
aToken->mType > Token::UNION_OP;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given string into the set of Tokens
|
||||
**/
|
||||
void ExprLexer::parse(const nsAFlatString& pattern)
|
||||
* Parses the given string into a sequence of Tokens
|
||||
*/
|
||||
nsresult
|
||||
txExprLexer::parse(const nsASingleFragmentString& aPattern)
|
||||
{
|
||||
if (pattern.IsEmpty())
|
||||
return;
|
||||
|
||||
nsAutoString tokenBuffer;
|
||||
PRUint32 iter = 0, start;
|
||||
PRUint32 size = pattern.Length();
|
||||
short defType;
|
||||
PRUnichar ch;
|
||||
iterator start, end;
|
||||
start = aPattern.BeginReading(mPosition);
|
||||
aPattern.EndReading(end);
|
||||
if (start == end) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-- initialize previous token, this will automatically get
|
||||
//-- deleted when it goes out of scope
|
||||
Token nullToken('\0', Token::NULL_TOKEN);
|
||||
Token nullToken(nsnull, nsnull, Token::NULL_TOKEN);
|
||||
|
||||
prevToken = &nullToken;
|
||||
Token::Type defType;
|
||||
Token* newToken = nsnull;
|
||||
Token* prevToken = &nullToken;
|
||||
PRBool isToken;
|
||||
|
||||
while (iter < size) {
|
||||
while (mPosition < end) {
|
||||
|
||||
ch = pattern.CharAt(iter);
|
||||
defType = Token::CNAME;
|
||||
isToken = PR_TRUE;
|
||||
|
||||
if (ch==DOLLAR_SIGN) {
|
||||
if (++iter == size || !XMLUtils::isLetter(ch=pattern.CharAt(iter))) {
|
||||
// Error, VariableReference expected
|
||||
errorPos = iter;
|
||||
errorCode = ERROR_UNRESOLVED_VAR_REFERENCE;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
if (*mPosition == DOLLAR_SIGN) {
|
||||
if (++mPosition == end || !XMLUtils::isLetter(*mPosition)) {
|
||||
return NS_ERROR_XPATH_INVALID_VAR_NAME;
|
||||
}
|
||||
else
|
||||
defType = Token::VAR_REFERENCE;
|
||||
defType = Token::VAR_REFERENCE;
|
||||
}
|
||||
// just reuse the QName parsing, which will use defType
|
||||
// the token to construct
|
||||
|
||||
if (XMLUtils::isLetter(ch)) {
|
||||
if (XMLUtils::isLetter(*mPosition)) {
|
||||
// NCName, can get QName or OperatorName;
|
||||
// FunctionName, NodeName, and AxisSpecifier may want whitespace,
|
||||
// and are dealt with below
|
||||
start = iter;
|
||||
while (++iter < size &&
|
||||
XMLUtils::isNCNameChar(pattern.CharAt(iter))) /* just go */ ;
|
||||
if (iter < size && pattern.CharAt(iter)==COLON) {
|
||||
// try QName or wildcard, might need to step back for axis
|
||||
if (++iter < size)
|
||||
if (XMLUtils::isLetter(pattern.CharAt(iter)))
|
||||
while (++iter < size &&
|
||||
XMLUtils::isNCNameChar(pattern.CharAt(iter))) /* just go */ ;
|
||||
else if (pattern.CharAt(iter)=='*'
|
||||
&& defType != Token::VAR_REFERENCE)
|
||||
++iter; /* eat wildcard for NameTest, bail for var ref at COLON */
|
||||
else
|
||||
iter--; // step back
|
||||
start = mPosition;
|
||||
while (++mPosition < end && XMLUtils::isNCNameChar(*mPosition)) {
|
||||
/* just go */
|
||||
}
|
||||
if (nextIsOperatorToken(prevToken)) {
|
||||
if (TX_StringEqualsAtom(Substring(pattern, start, iter - start),
|
||||
txXPathAtoms::_and))
|
||||
defType = Token::AND_OP;
|
||||
else if (TX_StringEqualsAtom(Substring(pattern, start, iter - start),
|
||||
txXPathAtoms::_or))
|
||||
defType = Token::OR_OP;
|
||||
else if (TX_StringEqualsAtom(Substring(pattern, start, iter - start),
|
||||
txXPathAtoms::mod))
|
||||
defType = Token::MODULUS_OP;
|
||||
else if (TX_StringEqualsAtom(Substring(pattern, start, iter - start),
|
||||
txXPathAtoms::div))
|
||||
defType = Token::DIVIDE_OP;
|
||||
if (mPosition < end && *mPosition == COLON) {
|
||||
// try QName or wildcard, might need to step back for axis
|
||||
if (++mPosition == end) {
|
||||
return NS_ERROR_XPATH_UNEXPECTED_END;
|
||||
}
|
||||
if (XMLUtils::isLetter(*mPosition)) {
|
||||
while (++mPosition < end && XMLUtils::isNCNameChar(*mPosition)) {
|
||||
/* just go */
|
||||
}
|
||||
}
|
||||
else if (*mPosition == '*' && defType != Token::VAR_REFERENCE) {
|
||||
// eat wildcard for NameTest, bail for var ref at COLON
|
||||
++mPosition;
|
||||
}
|
||||
else {
|
||||
// Error "operator expected"
|
||||
// XXX QUESTION: spec is not too precise
|
||||
// badops is sure an error, but is bad:ops, too? We say yes!
|
||||
errorPos = iter;
|
||||
errorCode = ERROR_OP_EXPECTED;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
--mPosition; // step back
|
||||
}
|
||||
}
|
||||
addToken(new Token(Substring(pattern, start, iter - start), defType));
|
||||
if (nextIsOperatorToken(prevToken)) {
|
||||
NS_ConvertUTF16toUTF8 opUTF8(Substring(start, mPosition));
|
||||
if (txXPathAtoms::_and->EqualsUTF8(opUTF8)) {
|
||||
defType = Token::AND_OP;
|
||||
}
|
||||
else if (txXPathAtoms::_or->EqualsUTF8(opUTF8)) {
|
||||
defType = Token::OR_OP;
|
||||
}
|
||||
else if (txXPathAtoms::mod->EqualsUTF8(opUTF8)) {
|
||||
defType = Token::MODULUS_OP;
|
||||
}
|
||||
else if (txXPathAtoms::div->EqualsUTF8(opUTF8)) {
|
||||
defType = Token::DIVIDE_OP;
|
||||
}
|
||||
else {
|
||||
// XXX QUESTION: spec is not too precise
|
||||
// badops is sure an error, but is bad:ops, too? We say yes!
|
||||
return NS_ERROR_XPATH_OPERATOR_EXPECTED;
|
||||
}
|
||||
}
|
||||
newToken = new Token(start, mPosition, defType);
|
||||
}
|
||||
else if (isXPathDigit(ch)) {
|
||||
start = iter;
|
||||
while (++iter < size &&
|
||||
isXPathDigit(pattern.CharAt(iter))) /* just go */;
|
||||
if (iter < size && pattern.CharAt(iter) == '.')
|
||||
while (++iter < size &&
|
||||
isXPathDigit(pattern.CharAt(iter))) /* just go */;
|
||||
addToken(new Token(Substring(pattern, start, iter - start),
|
||||
Token::NUMBER));
|
||||
else if (isXPathDigit(*mPosition)) {
|
||||
start = mPosition;
|
||||
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
||||
/* just go */
|
||||
}
|
||||
if (mPosition < end && *mPosition == '.') {
|
||||
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
||||
/* just go */
|
||||
}
|
||||
}
|
||||
newToken = new Token(start, mPosition, Token::NUMBER);
|
||||
}
|
||||
else {
|
||||
switch (ch) {
|
||||
switch (*mPosition) {
|
||||
//-- ignore whitespace
|
||||
case SPACE:
|
||||
case TX_TAB:
|
||||
case TX_CR:
|
||||
case TX_LF:
|
||||
++iter;
|
||||
++mPosition;
|
||||
isToken = PR_FALSE;
|
||||
break;
|
||||
case S_QUOTE :
|
||||
case D_QUOTE :
|
||||
start=iter;
|
||||
iter = pattern.FindChar(ch, start + 1);
|
||||
if ((PRInt32)iter == kNotFound) {
|
||||
// XXX Error reporting "unclosed literal"
|
||||
errorPos = start;
|
||||
errorCode = ERROR_UNCLOSED_LITERAL;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
start = mPosition;
|
||||
while (++mPosition < end && *mPosition != *start) {
|
||||
// eat literal
|
||||
}
|
||||
else {
|
||||
addToken(new Token(Substring(pattern, start + 1, iter - (start + 1)),
|
||||
Token::LITERAL));
|
||||
++iter;
|
||||
if (mPosition == end) {
|
||||
mPosition = start;
|
||||
return NS_ERROR_XPATH_UNCLOSED_LITERAL;
|
||||
}
|
||||
newToken = new Token(start + 1, mPosition, Token::LITERAL);
|
||||
++mPosition;
|
||||
break;
|
||||
case PERIOD:
|
||||
// period can be .., .(DIGITS)+ or ., check next
|
||||
if (++iter < size) {
|
||||
ch=pattern.CharAt(iter);
|
||||
if (isXPathDigit(ch)) {
|
||||
start=iter-1;
|
||||
while (++iter < size &&
|
||||
isXPathDigit(pattern.CharAt(iter))) /* just go */;
|
||||
addToken(new Token(Substring(pattern, start, iter - start),
|
||||
Token::NUMBER));
|
||||
}
|
||||
else if (ch==PERIOD) {
|
||||
addToken(new Token(Substring(pattern, ++iter - 2, 2),
|
||||
Token::PARENT_NODE));
|
||||
}
|
||||
else
|
||||
addToken(new Token(PERIOD, Token::SELF_NODE));
|
||||
if (++mPosition == end) {
|
||||
newToken = new Token(mPosition - 1, Token::SELF_NODE);
|
||||
}
|
||||
else if (isXPathDigit(*mPosition)) {
|
||||
start = mPosition - 1;
|
||||
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
||||
/* just go */
|
||||
}
|
||||
newToken = new Token(start, mPosition, Token::NUMBER);
|
||||
}
|
||||
else if (*mPosition == PERIOD) {
|
||||
++mPosition;
|
||||
newToken = new Token(mPosition - 2, mPosition, Token::PARENT_NODE);
|
||||
}
|
||||
else {
|
||||
newToken = new Token(mPosition - 1, Token::SELF_NODE);
|
||||
}
|
||||
else
|
||||
addToken(new Token(ch, Token::SELF_NODE));
|
||||
// iter++ is already in the number test
|
||||
|
||||
break;
|
||||
case COLON: // QNames are dealt above, must be axis ident
|
||||
if (++iter < size && pattern.CharAt(iter) == COLON &&
|
||||
prevToken->type == Token::CNAME) {
|
||||
prevToken->type = Token::AXIS_IDENTIFIER;
|
||||
++iter;
|
||||
}
|
||||
else {
|
||||
// XXX Error report "colon is neither QName nor axis"
|
||||
errorPos = iter;
|
||||
errorCode = ERROR_COLON;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
if (++mPosition >= end || *mPosition != COLON ||
|
||||
prevToken->mType != Token::CNAME) {
|
||||
return NS_ERROR_XPATH_BAD_COLON;
|
||||
}
|
||||
prevToken->mType = Token::AXIS_IDENTIFIER;
|
||||
++mPosition;
|
||||
isToken = PR_FALSE;
|
||||
break;
|
||||
case FORWARD_SLASH :
|
||||
if (++iter < size && pattern.CharAt(iter) == ch) {
|
||||
addToken(new Token(Substring(pattern, ++iter - 2, 2),
|
||||
Token::ANCESTOR_OP));
|
||||
if (++mPosition < end && *mPosition == FORWARD_SLASH) {
|
||||
++mPosition;
|
||||
newToken = new Token(mPosition - 2, mPosition, Token::ANCESTOR_OP);
|
||||
}
|
||||
else {
|
||||
addToken(new Token(ch, Token::PARENT_OP));
|
||||
newToken = new Token(mPosition - 1, Token::PARENT_OP);
|
||||
}
|
||||
break;
|
||||
case BANG : // can only be !=
|
||||
if (++iter < size && pattern.CharAt(iter) == EQUAL) {
|
||||
addToken(new Token(Substring(pattern, ++iter - 2, 2),
|
||||
Token::NOT_EQUAL_OP));
|
||||
if (++mPosition < end && *mPosition == EQUAL) {
|
||||
++mPosition;
|
||||
newToken = new Token(mPosition - 2, mPosition, Token::NOT_EQUAL_OP);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Error ! is not not()
|
||||
errorPos = iter;
|
||||
errorCode = ERROR_BANG;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
}
|
||||
break;
|
||||
// Error ! is not not()
|
||||
return NS_ERROR_XPATH_BAD_BANG;
|
||||
case EQUAL:
|
||||
addToken(new Token(ch,Token::EQUAL_OP));
|
||||
++iter;
|
||||
newToken = new Token(mPosition, Token::EQUAL_OP);
|
||||
++mPosition;
|
||||
break;
|
||||
case L_ANGLE:
|
||||
if (++iter < size && pattern.CharAt(iter) == EQUAL) {
|
||||
addToken(new Token(Substring(pattern, ++iter - 2, 2),
|
||||
Token::LESS_OR_EQUAL_OP));
|
||||
if (++mPosition == end) {
|
||||
return NS_ERROR_XPATH_UNEXPECTED_END;
|
||||
}
|
||||
if (*mPosition == EQUAL) {
|
||||
++mPosition;
|
||||
newToken = new Token(mPosition - 2, mPosition,
|
||||
Token::LESS_OR_EQUAL_OP);
|
||||
}
|
||||
else {
|
||||
newToken = new Token(mPosition - 1, Token::LESS_THAN_OP);
|
||||
}
|
||||
else
|
||||
addToken(new Token(ch,Token::LESS_THAN_OP));
|
||||
break;
|
||||
case R_ANGLE:
|
||||
if (++iter < size && pattern.CharAt(iter) == EQUAL) {
|
||||
addToken(new Token(Substring(pattern, ++iter - 2, 2),
|
||||
Token::GREATER_OR_EQUAL_OP));
|
||||
if (++mPosition == end) {
|
||||
return NS_ERROR_XPATH_UNEXPECTED_END;
|
||||
}
|
||||
if (*mPosition == EQUAL) {
|
||||
++mPosition;
|
||||
newToken = new Token(mPosition - 2, mPosition,
|
||||
Token::GREATER_OR_EQUAL_OP);
|
||||
}
|
||||
else {
|
||||
newToken = new Token(mPosition - 1, Token::GREATER_THAN_OP);
|
||||
}
|
||||
else
|
||||
addToken(new Token(ch,Token::GREATER_THAN_OP));
|
||||
break;
|
||||
case HYPHEN :
|
||||
addToken(new Token(ch,Token::SUBTRACTION_OP));
|
||||
++iter;
|
||||
newToken = new Token(mPosition, Token::SUBTRACTION_OP);
|
||||
++mPosition;
|
||||
break;
|
||||
case ASTERIX:
|
||||
if (nextIsOperatorToken(prevToken))
|
||||
addToken(new Token(ch,Token::MULTIPLY_OP));
|
||||
else
|
||||
addToken(new Token(ch,Token::CNAME));
|
||||
++iter;
|
||||
if (nextIsOperatorToken(prevToken)) {
|
||||
newToken = new Token(mPosition, Token::MULTIPLY_OP);
|
||||
}
|
||||
else {
|
||||
newToken = new Token(mPosition, Token::CNAME);
|
||||
}
|
||||
++mPosition;
|
||||
break;
|
||||
case L_PAREN:
|
||||
if (prevToken->type == Token::CNAME) {
|
||||
if (TX_StringEqualsAtom(prevToken->value, txXPathAtoms::comment))
|
||||
prevToken->type = Token::COMMENT;
|
||||
else if (TX_StringEqualsAtom(prevToken->value, txXPathAtoms::node))
|
||||
prevToken->type = Token::NODE;
|
||||
else if (TX_StringEqualsAtom(prevToken->value,
|
||||
txXPathAtoms::processingInstruction))
|
||||
prevToken->type = Token::PROC_INST;
|
||||
else if (TX_StringEqualsAtom(prevToken->value, txXPathAtoms::text))
|
||||
prevToken->type = Token::TEXT;
|
||||
else
|
||||
prevToken->type = Token::FUNCTION_NAME;
|
||||
if (prevToken->mType == Token::CNAME) {
|
||||
NS_ConvertUTF16toUTF8 utf8Value(prevToken->Value());
|
||||
if (txXPathAtoms::comment->EqualsUTF8(utf8Value)) {
|
||||
prevToken->mType = Token::COMMENT;
|
||||
}
|
||||
else if (txXPathAtoms::node->EqualsUTF8(utf8Value)) {
|
||||
prevToken->mType = Token::NODE;
|
||||
}
|
||||
else if (txXPathAtoms::processingInstruction->EqualsUTF8(utf8Value)) {
|
||||
prevToken->mType = Token::PROC_INST;
|
||||
}
|
||||
else if (txXPathAtoms::text->EqualsUTF8(utf8Value)) {
|
||||
prevToken->mType = Token::TEXT;
|
||||
}
|
||||
else {
|
||||
prevToken->mType = Token::FUNCTION_NAME;
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::L_PAREN));
|
||||
newToken = new Token(mPosition, Token::L_PAREN);
|
||||
++mPosition;
|
||||
break;
|
||||
case R_PAREN:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::R_PAREN));
|
||||
newToken = new Token(mPosition, Token::R_PAREN);
|
||||
++mPosition;
|
||||
break;
|
||||
case L_BRACKET:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::L_BRACKET));
|
||||
newToken = new Token(mPosition, Token::L_BRACKET);
|
||||
++mPosition;
|
||||
break;
|
||||
case R_BRACKET:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::R_BRACKET));
|
||||
newToken = new Token(mPosition, Token::R_BRACKET);
|
||||
++mPosition;
|
||||
break;
|
||||
case COMMA:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::COMMA));
|
||||
newToken = new Token(mPosition, Token::COMMA);
|
||||
++mPosition;
|
||||
break;
|
||||
case AT_SIGN :
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::AT_SIGN));
|
||||
newToken = new Token(mPosition, Token::AT_SIGN);
|
||||
++mPosition;
|
||||
break;
|
||||
case PLUS:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::ADDITION_OP));
|
||||
newToken = new Token(mPosition, Token::ADDITION_OP);
|
||||
++mPosition;
|
||||
break;
|
||||
case VERT_BAR:
|
||||
++iter;
|
||||
addToken(new Token(ch,Token::UNION_OP));
|
||||
newToken = new Token(mPosition, Token::UNION_OP);
|
||||
++mPosition;
|
||||
break;
|
||||
default:
|
||||
// Error, don't grok character :-(
|
||||
errorPos = iter;
|
||||
errorCode = ERROR_UNKNOWN_CHAR;
|
||||
if (firstItem)
|
||||
firstItem->token->type=Token::ERROR;
|
||||
else
|
||||
addToken(new Token('\0',Token::ERROR));
|
||||
iter=size; // bail
|
||||
return NS_ERROR_XPATH_ILLEGAL_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //-- parse
|
||||
if (isToken) {
|
||||
NS_ENSURE_TRUE(newToken, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(newToken != mLastItem, NS_ERROR_FAILURE);
|
||||
prevToken = newToken;
|
||||
addToken(newToken);
|
||||
}
|
||||
}
|
||||
|
||||
// add a endToken to the list
|
||||
newToken = new Token(end, end, Token::END);
|
||||
if (!newToken) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
addToken(newToken);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,18 +39,15 @@
|
|||
*
|
||||
* This class was ported from XSL:P, an open source Java based
|
||||
* XSLT processor, written by yours truly.
|
||||
**/
|
||||
class Token {
|
||||
|
||||
*/
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
|
||||
//---------------/
|
||||
//- Token Types -/
|
||||
//---------------/
|
||||
|
||||
//-- LF - changed from static const short declarations to enum
|
||||
//-- token types
|
||||
enum TokenType {
|
||||
/**
|
||||
* Token types
|
||||
*/
|
||||
enum Type {
|
||||
//-- Trivial Tokens
|
||||
ERROR = 0,
|
||||
NULL_TOKEN,
|
||||
|
@ -67,16 +64,16 @@ public:
|
|||
* start of tokens for 3.7, bullet 1
|
||||
* ExprLexer::nextIsOperatorToken bails if the tokens aren't
|
||||
* consecutive.
|
||||
**/
|
||||
*/
|
||||
COMMA,
|
||||
AT_SIGN,
|
||||
L_PAREN,
|
||||
L_BRACKET,
|
||||
AXIS_IDENTIFIER,
|
||||
//-------------/
|
||||
//- operators -/
|
||||
//-------------/
|
||||
|
||||
/**
|
||||
* operators
|
||||
*/
|
||||
//-- boolean ops
|
||||
AND_OP, // 16
|
||||
OR_OP,
|
||||
|
@ -101,7 +98,7 @@ public:
|
|||
UNION_OP,
|
||||
/**
|
||||
* end of tokens for 3.7, bullet 1 -/
|
||||
**/
|
||||
*/
|
||||
//-- node type tokens
|
||||
COMMENT, // 32
|
||||
NODE,
|
||||
|
@ -114,36 +111,83 @@ public:
|
|||
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
**/
|
||||
Token();
|
||||
Token(short type);
|
||||
Token(const nsAString& value, short type);
|
||||
Token(PRUnichar uniChar, short type);
|
||||
/**
|
||||
* Copy Constructor
|
||||
**/
|
||||
Token(const Token& token);
|
||||
* Constructors
|
||||
*/
|
||||
typedef nsASingleFragmentString::const_char_iterator iterator;
|
||||
|
||||
~Token();
|
||||
nsString value;
|
||||
short type;
|
||||
}; //--Token
|
||||
Token(iterator aStart, iterator aEnd, Type aType)
|
||||
: mStart(aStart),
|
||||
mEnd(aEnd),
|
||||
mType(aType),
|
||||
mNext(nsnull),
|
||||
mPrevious(nsnull)
|
||||
{
|
||||
}
|
||||
Token(iterator aChar, Type aType)
|
||||
: mStart(aChar),
|
||||
mEnd(aChar + 1),
|
||||
mType(aType),
|
||||
mNext(nsnull),
|
||||
mPrevious(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
const nsDependentSingleFragmentSubstring Value()
|
||||
{
|
||||
return Substring(mStart, mEnd);
|
||||
}
|
||||
|
||||
iterator mStart, mEnd;
|
||||
Type mType;
|
||||
Token* mNext;
|
||||
// XXX mPrevious needed for pushBack(), do we pushBack more than once?
|
||||
Token* mPrevious;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class for splitting an "Expr" String into tokens and
|
||||
* performing basic Lexical Analysis.
|
||||
*
|
||||
* This class was ported from XSL:P, an open source Java based XSL processor
|
||||
**/
|
||||
class ExprLexer {
|
||||
|
||||
*/
|
||||
|
||||
class txExprLexer
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
txExprLexer();
|
||||
~txExprLexer();
|
||||
|
||||
/**
|
||||
* Parse the given string.
|
||||
* returns an error result if lexing failed.
|
||||
* The given string must outlive the use of the lexer, as the
|
||||
* generated Tokens point to Substrings of it.
|
||||
* mPosition points to the offending location in case of an error.
|
||||
*/
|
||||
nsresult parse(const nsASingleFragmentString& aPattern);
|
||||
|
||||
typedef nsASingleFragmentString::const_char_iterator iterator;
|
||||
iterator mPosition;
|
||||
|
||||
/**
|
||||
* Functions for iterating over the TokenList
|
||||
*/
|
||||
|
||||
Token* nextToken();
|
||||
Token* peek()
|
||||
{
|
||||
return mCurrentItem;
|
||||
}
|
||||
void pushBack();
|
||||
PRBool hasMoreTokens()
|
||||
{
|
||||
return (mCurrentItem->mType != Token::END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trivial Tokens
|
||||
*/
|
||||
*/
|
||||
//-- LF, changed to enum
|
||||
enum _TrivialTokens {
|
||||
D_QUOTE = '\"',
|
||||
|
@ -173,77 +217,32 @@ public:
|
|||
TX_LF = '\r'
|
||||
};
|
||||
|
||||
enum _error_consts {
|
||||
ERROR_UNRESOLVED_VAR_REFERENCE = 0,
|
||||
ERROR_OP_EXPECTED,
|
||||
ERROR_UNCLOSED_LITERAL,
|
||||
ERROR_COLON,
|
||||
ERROR_BANG,
|
||||
ERROR_UNKNOWN_CHAR
|
||||
};
|
||||
PRUint32 errorPos;
|
||||
short errorCode;
|
||||
|
||||
/*
|
||||
* Default Token Set
|
||||
*/
|
||||
static const Token TOKENS[];
|
||||
static const short NUMBER_OF_TOKENS;
|
||||
|
||||
/**
|
||||
* Constructor for ExprLexer
|
||||
**/
|
||||
ExprLexer(const nsAFlatString& pattern);
|
||||
|
||||
~ExprLexer();
|
||||
|
||||
/**
|
||||
* Functions for iterating over the TokenList
|
||||
**/
|
||||
|
||||
Token* nextToken();
|
||||
Token* peek();
|
||||
void pushBack();
|
||||
MBool hasMoreTokens();
|
||||
|
||||
private:
|
||||
|
||||
struct TokenListItem {
|
||||
Token* token;
|
||||
TokenListItem* next;
|
||||
TokenListItem* previous;
|
||||
};
|
||||
Token* mCurrentItem;
|
||||
Token* mFirstItem;
|
||||
Token* mLastItem;
|
||||
|
||||
TokenListItem* currentItem;
|
||||
TokenListItem* firstItem;
|
||||
TokenListItem* lastItem;
|
||||
int mTokenCount;
|
||||
|
||||
int tokenCount;
|
||||
|
||||
Token* prevToken;
|
||||
Token endToken;
|
||||
|
||||
void addToken(Token* token);
|
||||
void addToken(Token* aToken);
|
||||
|
||||
/**
|
||||
* Returns true if the following Token should be an operator.
|
||||
* This is a helper for the first bullet of [XPath 3.7]
|
||||
* Lexical Structure
|
||||
**/
|
||||
MBool nextIsOperatorToken(Token* token);
|
||||
*/
|
||||
PRBool nextIsOperatorToken(Token* aToken);
|
||||
|
||||
/**
|
||||
* Returns true if the given character represents a numeric letter (digit)
|
||||
* Implemented in ExprLexerChars.cpp
|
||||
**/
|
||||
static MBool isXPathDigit(PRUnichar ch)
|
||||
*/
|
||||
static PRBool isXPathDigit(PRUnichar ch)
|
||||
{
|
||||
return (ch >= '0' && ch <= '9');
|
||||
}
|
||||
|
||||
void parse(const nsAFlatString& pattern);
|
||||
|
||||
}; //-- ExprLexer
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -35,10 +35,11 @@
|
|||
#include "baseutils.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "txError.h"
|
||||
#include "Expr.h"
|
||||
|
||||
class AttributeValueTemplate;
|
||||
class Expr;
|
||||
class ExprLexer;
|
||||
class txExprLexer;
|
||||
class FunctionCall;
|
||||
class LocationStep;
|
||||
class PredicateList;
|
||||
|
@ -46,42 +47,57 @@ class Token;
|
|||
class txIParseContext;
|
||||
class txNodeTypeTest;
|
||||
|
||||
class ExprParser
|
||||
class txExprParser
|
||||
{
|
||||
public:
|
||||
|
||||
static Expr* createExpr(const nsAFlatString& aExpression,
|
||||
txIParseContext* aContext);
|
||||
static nsresult createExpr(const nsASingleFragmentString& aExpression,
|
||||
txIParseContext* aContext, Expr** aExpr);
|
||||
|
||||
/**
|
||||
* Creates an Attribute Value Template using the given value
|
||||
**/
|
||||
*/
|
||||
static AttributeValueTemplate* createAttributeValueTemplate
|
||||
(const nsAFlatString& attValue, txIParseContext* aContext);
|
||||
|
||||
|
||||
protected:
|
||||
static Expr* createBinaryExpr(Expr* left, Expr* right, Token* op);
|
||||
static Expr* createExpr(ExprLexer& lexer, txIParseContext* aContext);
|
||||
static Expr* createFilterExpr(ExprLexer& lexer, txIParseContext* aContext);
|
||||
static Expr* createFunctionCall(ExprLexer& lexer,
|
||||
txIParseContext* aContext);
|
||||
static LocationStep* createLocationStep(ExprLexer& lexer,
|
||||
txIParseContext* aContext);
|
||||
static txNodeTypeTest* createNodeTypeTest(ExprLexer& lexer);
|
||||
static Expr* createPathExpr(ExprLexer& lexer, txIParseContext* aContext);
|
||||
static Expr* createUnionExpr(ExprLexer& lexer, txIParseContext* aContext);
|
||||
/**
|
||||
* Using nsAutoPtr& to optimize passing the ownership to the
|
||||
* created binary expression objects.
|
||||
*/
|
||||
static nsresult createBinaryExpr(nsAutoPtr<Expr>& left,
|
||||
nsAutoPtr<Expr>& right, Token* op,
|
||||
Expr** aResult);
|
||||
static nsresult createExpr(txExprLexer& lexer, txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
static nsresult createFilter(txExprLexer& lexer, txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
static nsresult createFunctionCall(txExprLexer& lexer,
|
||||
txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
static nsresult createLocationStep(txExprLexer& lexer,
|
||||
txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
static nsresult createNodeTypeTest(txExprLexer& lexer,
|
||||
txNodeTest** aResult);
|
||||
static nsresult createPathExpr(txExprLexer& lexer,
|
||||
txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
static nsresult createUnionExpr(txExprLexer& lexer,
|
||||
txIParseContext* aContext,
|
||||
Expr** aResult);
|
||||
|
||||
static MBool isFilterExprToken (Token* tok);
|
||||
static MBool isLocationStepToken(Token* tok);
|
||||
static MBool isNodeTypeToken (Token* tok);
|
||||
static PRBool isFilterExprToken(Token* aToken);
|
||||
static PRBool isLocationStepToken(Token* aToken);
|
||||
static PRBool isNodeTypeToken(Token* aToken);
|
||||
|
||||
static short precedenceLevel (short tokenType);
|
||||
static short precedence(Token* aToken);
|
||||
|
||||
/**
|
||||
* Resolve a QName, given the mContext parse context.
|
||||
* Returns prefix and localName as well as namespace ID
|
||||
**/
|
||||
*/
|
||||
static nsresult resolveQName(const nsAString& aQName, nsIAtom** aPrefix,
|
||||
txIParseContext* aContext,
|
||||
nsIAtom** aLocalName, PRInt32& aNamespace,
|
||||
|
@ -95,12 +111,13 @@ protected:
|
|||
* @param predicateList, the PredicateList to add predicate expressions to
|
||||
* @param lexer the ExprLexer to use for parsing tokens
|
||||
* @return 0 if successful, or a String pointer to the error message
|
||||
**/
|
||||
static MBool parsePredicates(PredicateList* predicateList,
|
||||
ExprLexer& lexer, txIParseContext* aContext);
|
||||
static MBool parseParameters(FunctionCall* fnCall,
|
||||
ExprLexer& lexer, txIParseContext* aContext);
|
||||
*/
|
||||
static nsresult parsePredicates(PredicateList* aPredicateList,
|
||||
txExprLexer& lexer,
|
||||
txIParseContext* aContext);
|
||||
static nsresult parseParameters(FunctionCall* aFnCall, txExprLexer& lexer,
|
||||
txIParseContext* aContext);
|
||||
|
||||
}; //-- ExprParser
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,21 +31,6 @@
|
|||
|
||||
//-- Implementation of FilterExpr --/
|
||||
|
||||
/**
|
||||
* Creates a new FilterExpr using the given Expr
|
||||
* @param expr the Expr to use for evaluation
|
||||
**/
|
||||
FilterExpr::FilterExpr(Expr* expr) : PredicateList() {
|
||||
this->expr = expr;
|
||||
} //-- FilterExpr
|
||||
|
||||
/**
|
||||
* Destroys this FilterExpr, all predicates and the expr will be deleted
|
||||
**/
|
||||
FilterExpr::~FilterExpr() {
|
||||
delete expr;
|
||||
} //-- ~FilterExpr
|
||||
|
||||
//-----------------------------/
|
||||
//- Virtual methods from Expr -/
|
||||
//-----------------------------/
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "Expr.h"
|
||||
#include "FunctionLib.h"
|
||||
#include "ExprResult.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
@ -55,12 +55,16 @@ FunctionCall::~FunctionCall()
|
|||
/**
|
||||
* Adds the given parameter to this FunctionCall's parameter list
|
||||
* @param expr the Expr to add to this FunctionCall's parameter list
|
||||
**/
|
||||
nsresult FunctionCall::addParam(Expr* aExpr)
|
||||
*/
|
||||
nsresult
|
||||
FunctionCall::addParam(Expr* aExpr)
|
||||
{
|
||||
if (aExpr)
|
||||
params.add(aExpr);
|
||||
return NS_OK;
|
||||
NS_ASSERTION(aExpr, "missing expression");
|
||||
nsresult rv = params.add(aExpr);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete aExpr;
|
||||
}
|
||||
return rv;
|
||||
} //-- addParam
|
||||
|
||||
/*
|
||||
|
@ -183,3 +187,27 @@ void FunctionCall::toString(nsAString& aDest)
|
|||
}
|
||||
aDest.Append(PRUnichar(')'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of txErrorFunctionCall
|
||||
*
|
||||
* Used for fcp and unknown extension functions.
|
||||
*/
|
||||
|
||||
nsresult
|
||||
txErrorFunctionCall::evaluate(txIEvalContext* aContext,
|
||||
txAExprResult** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
return NS_ERROR_XPATH_BAD_EXTENSION_FUNCTION;
|
||||
}
|
||||
|
||||
nsresult
|
||||
txErrorFunctionCall::getNameAtom(nsIAtom** aAtom)
|
||||
{
|
||||
*aAtom = mLName;
|
||||
NS_IF_ADDREF(*aAtom);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -85,24 +85,26 @@ private:
|
|||
}; //-- BooleanFunctionCall
|
||||
|
||||
/**
|
||||
* Internal Function created when there is an Error during parsing
|
||||
* an Expression
|
||||
**/
|
||||
class ErrorFunctionCall : public FunctionCall {
|
||||
* Error Function to be used for unknown extension functions and
|
||||
* forwards-compatible-processing (not implemented, bug XXX)
|
||||
*
|
||||
* txErrorFunctionCall returns NS_ERROR_XPATH_UNKNOWN_FUNCTION
|
||||
* (see FunctionCall.cpp)
|
||||
*/
|
||||
class txErrorFunctionCall : public FunctionCall
|
||||
{
|
||||
public:
|
||||
|
||||
ErrorFunctionCall();
|
||||
ErrorFunctionCall(const nsAString& errorMsg);
|
||||
txErrorFunctionCall(nsIAtom* aLName, const PRInt32 aID)
|
||||
: mLName(aLName),
|
||||
mID(aID)
|
||||
{}
|
||||
|
||||
TX_DECL_FUNCTION;
|
||||
|
||||
void setErrorMessage(nsAString& errorMsg);
|
||||
|
||||
private:
|
||||
|
||||
nsString errorMessage;
|
||||
|
||||
}; //-- ErrorFunctionCall
|
||||
nsCOMPtr<nsIAtom> mLName;
|
||||
PRInt32 mID;
|
||||
};
|
||||
|
||||
/*
|
||||
* A representation of the XPath NodeSet funtions
|
||||
|
|
|
@ -31,17 +31,6 @@
|
|||
#include "NodeSet.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
/**
|
||||
* Creates a new LocationStep using the given NodeExpr and Axis Identifier
|
||||
* @param nodeExpr the NodeExpr to use when matching Nodes
|
||||
* @param axisIdentifier the Axis Identifier in which to search for nodes
|
||||
**/
|
||||
LocationStep::LocationStep(nsAutoPtr<txNodeTest> aNodeTest,
|
||||
LocationStepType aAxisIdentifier)
|
||||
: mNodeTest(aNodeTest), mAxisIdentifier(aAxisIdentifier)
|
||||
{
|
||||
} //-- LocationStep
|
||||
|
||||
//-----------------------------/
|
||||
//- Virtual methods from Expr -/
|
||||
//-----------------------------/
|
||||
|
|
|
@ -41,20 +41,6 @@
|
|||
#include "primitives.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
/**
|
||||
* Creates a new MultiplicativeExpr using the given operator
|
||||
**/
|
||||
MultiplicativeExpr::MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op) {
|
||||
this->op = op;
|
||||
this->leftExpr = leftExpr;
|
||||
this->rightExpr = rightExpr;
|
||||
} //-- MultiplicativeExpr
|
||||
|
||||
MultiplicativeExpr::~MultiplicativeExpr() {
|
||||
delete leftExpr;
|
||||
delete rightExpr;
|
||||
} //-- ~MultiplicativeExpr
|
||||
|
||||
/**
|
||||
* Evaluates this Expr based on the given context node and processor state
|
||||
* @param context the context node for evaluation of this Expr
|
||||
|
|
|
@ -56,9 +56,7 @@ PathExpr::~PathExpr()
|
|||
{
|
||||
txListIterator iter(&expressions);
|
||||
while (iter.hasNext()) {
|
||||
PathExprItem* pxi = (PathExprItem*)iter.next();
|
||||
delete pxi->expr;
|
||||
delete pxi;
|
||||
delete NS_STATIC_CAST(PathExprItem*, iter.next());
|
||||
}
|
||||
} //-- ~PathExpr
|
||||
|
||||
|
@ -66,22 +64,22 @@ PathExpr::~PathExpr()
|
|||
* Adds the Expr to this PathExpr
|
||||
* @param expr the Expr to add to this PathExpr
|
||||
**/
|
||||
void PathExpr::addExpr(Expr* expr, PathOperator pathOp)
|
||||
nsresult
|
||||
PathExpr::addExpr(Expr* aExpr, PathOperator pathOp)
|
||||
{
|
||||
NS_ASSERTION(expressions.getLength() > 0 || pathOp == RELATIVE_OP,
|
||||
"First step has to be relative in PathExpr");
|
||||
if (expr) {
|
||||
PathExprItem* pxi = new PathExprItem;
|
||||
if (!pxi) {
|
||||
// XXX ErrorReport: out of memory
|
||||
NS_ASSERTION(0, "out of memory");
|
||||
return;
|
||||
}
|
||||
pxi->expr = expr;
|
||||
pxi->pathOp = pathOp;
|
||||
expressions.add(pxi);
|
||||
PathExprItem* pxi = new PathExprItem(aExpr, pathOp);
|
||||
if (!pxi) {
|
||||
delete aExpr;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} //-- addPattenExpr
|
||||
nsresult rv = expressions.add(pxi);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete pxi;
|
||||
}
|
||||
return rv;
|
||||
} //-- addExpr
|
||||
|
||||
//-----------------------------/
|
||||
//- Virtual methods from Expr -/
|
||||
|
|
|
@ -51,9 +51,15 @@ PredicateList::~PredicateList()
|
|||
* Adds the given Expr to the list
|
||||
* @param expr the Expr to add to the list
|
||||
*/
|
||||
void PredicateList::add(Expr* expr)
|
||||
nsresult
|
||||
PredicateList::add(Expr* aExpr)
|
||||
{
|
||||
predicates.add(expr);
|
||||
NS_ASSERTION(aExpr, "missing expression");
|
||||
nsresult rv = predicates.add(aExpr);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete aExpr;
|
||||
}
|
||||
return rv;
|
||||
} // add
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -32,12 +32,6 @@
|
|||
#include "XMLDOMUtils.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
RelationalExpr::RelationalExpr(Expr* aLeftExpr, Expr* aRightExpr,
|
||||
RelationalExprType aOp)
|
||||
: mLeftExpr(aLeftExpr), mRightExpr(aRightExpr), mOp(aOp)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4)
|
||||
*/
|
||||
|
|
|
@ -27,16 +27,6 @@
|
|||
#include "ExprResult.h"
|
||||
#include "txIXPathContext.h"
|
||||
|
||||
UnaryExpr::UnaryExpr(Expr* expr)
|
||||
{
|
||||
this->expr = expr;
|
||||
}
|
||||
|
||||
UnaryExpr::~UnaryExpr()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluates this Expr based on the given context node and processor state
|
||||
* @param context the context node for evaluation of this Expr
|
||||
|
|
|
@ -53,9 +53,14 @@ UnionExpr::~UnionExpr() {
|
|||
* Adds the Expr to this UnionExpr
|
||||
* @param expr the Expr to add to this UnionExpr
|
||||
**/
|
||||
void UnionExpr::addExpr(Expr* expr) {
|
||||
if (expr)
|
||||
expressions.add(expr);
|
||||
nsresult
|
||||
UnionExpr::addExpr(Expr* aExpr)
|
||||
{
|
||||
nsresult rv = expressions.add(aExpr);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete aExpr;
|
||||
}
|
||||
return rv;
|
||||
} //-- addExpr
|
||||
|
||||
//-----------------------------/
|
||||
|
|
|
@ -89,10 +89,12 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
|
|||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
ParseContextImpl pContext(aResolver, !doc || doc->IsCaseSensitive());
|
||||
Expr* expression = ExprParser::createExpr(PromiseFlatString(aExpression),
|
||||
&pContext);
|
||||
if (!expression)
|
||||
Expr* expression;
|
||||
rv = ExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
|
||||
&expression);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
|
||||
}
|
||||
|
||||
*aResult = new nsXPathExpression(expression, mRecycler);
|
||||
if (!*aResult) {
|
||||
|
@ -179,11 +181,12 @@ nsresult nsXPathEvaluator::ParseContextImpl::resolveNamespacePrefix
|
|||
return gTxNameSpaceManager->RegisterNameSpace(ns, aID);
|
||||
}
|
||||
|
||||
nsresult nsXPathEvaluator::ParseContextImpl::resolveFunctionCall(nsIAtom* aName,
|
||||
PRInt32 aID,
|
||||
FunctionCall*& aFn)
|
||||
nsresult
|
||||
nsXPathEvaluator::ParseContextImpl::resolveFunctionCall(nsIAtom* aName,
|
||||
PRInt32 aID,
|
||||
FunctionCall*& aFn)
|
||||
{
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
|
||||
}
|
||||
|
||||
PRBool nsXPathEvaluator::ParseContextImpl::caseInsensitiveNameTests()
|
||||
|
@ -191,9 +194,7 @@ PRBool nsXPathEvaluator::ParseContextImpl::caseInsensitiveNameTests()
|
|||
return !mIsCaseSensitive;
|
||||
}
|
||||
|
||||
void nsXPathEvaluator::ParseContextImpl::receiveError(const nsAString& aMsg,
|
||||
nsresult aRes)
|
||||
void
|
||||
nsXPathEvaluator::ParseContextImpl::SetErrorOffset(PRUint32 aOffset)
|
||||
{
|
||||
mLastError = aRes;
|
||||
// forward aMsg to console service?
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ private:
|
|||
nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID,
|
||||
FunctionCall*& aFunction);
|
||||
PRBool caseInsensitiveNameTests();
|
||||
void receiveError(const nsAString& aMsg, nsresult aRes);
|
||||
void SetErrorOffset(PRUint32 aOffset);
|
||||
|
||||
private:
|
||||
nsIDOMXPathNSResolver* mResolver;
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
/*
|
||||
* Callback to be used by the Parser if errors are detected.
|
||||
*/
|
||||
virtual void receiveError(const nsAString& aMsg, nsresult aRes) = 0;
|
||||
virtual void SetErrorOffset(PRUint32 aOffset) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -47,8 +47,13 @@ txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern,
|
|||
txIParseContext* aContext)
|
||||
{
|
||||
txPattern* pattern = 0;
|
||||
ExprLexer lexer(aPattern);
|
||||
nsresult rv = createUnionPattern(lexer, aContext, pattern);
|
||||
txExprLexer lexer;
|
||||
nsresult rv = lexer.parse(aPattern);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX error report parsing error
|
||||
return 0;
|
||||
}
|
||||
rv = createUnionPattern(lexer, aContext, pattern);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX error report parsing error
|
||||
return 0;
|
||||
|
@ -56,7 +61,7 @@ txPattern* txPatternParser::createPattern(const nsAFlatString& aPattern,
|
|||
return pattern;
|
||||
}
|
||||
|
||||
nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer,
|
||||
nsresult txPatternParser::createUnionPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern)
|
||||
{
|
||||
|
@ -67,7 +72,7 @@ nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
short type = aLexer.peek()->type;
|
||||
Token::Type type = aLexer.peek()->mType;
|
||||
if (type == Token::END) {
|
||||
aPattern = locPath;
|
||||
return NS_OK;
|
||||
|
@ -107,7 +112,7 @@ nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer,
|
|||
return rv;
|
||||
}
|
||||
#endif
|
||||
type = aLexer.nextToken()->type;
|
||||
type = aLexer.nextToken()->mType;
|
||||
} while (type == Token::UNION_OP);
|
||||
|
||||
if (type != Token::END) {
|
||||
|
@ -119,7 +124,7 @@ nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
||||
nsresult txPatternParser::createLocPathPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern)
|
||||
{
|
||||
|
@ -130,7 +135,7 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
|||
txPattern* stepPattern = 0;
|
||||
txLocPathPattern* pathPattern = 0;
|
||||
|
||||
short type = aLexer.peek()->type;
|
||||
Token::Type type = aLexer.peek()->mType;
|
||||
switch (type) {
|
||||
case Token::ANCESTOR_OP:
|
||||
isChild = MB_FALSE;
|
||||
|
@ -140,8 +145,8 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
|||
case Token::PARENT_OP:
|
||||
aLexer.nextToken();
|
||||
isAbsolute = MB_TRUE;
|
||||
if (aLexer.peek()->type == Token::END ||
|
||||
aLexer.peek()->type == Token::UNION_OP) {
|
||||
if (aLexer.peek()->mType == Token::END ||
|
||||
aLexer.peek()->mType == Token::UNION_OP) {
|
||||
aPattern = new txRootPattern(MB_TRUE);
|
||||
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -149,7 +154,8 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
|||
case Token::FUNCTION_NAME:
|
||||
// id(Literal) or key(Literal, Literal)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLexer.nextToken()->value);
|
||||
nsCOMPtr<nsIAtom> nameAtom =
|
||||
do_GetAtom(aLexer.nextToken()->Value());
|
||||
if (nameAtom == txXPathAtoms::id) {
|
||||
rv = createIdPattern(aLexer, stepPattern);
|
||||
}
|
||||
|
@ -169,7 +175,7 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
type = aLexer.peek()->type;
|
||||
type = aLexer.peek()->mType;
|
||||
if (!isAbsolute && type != Token::PARENT_OP
|
||||
&& type != Token::ANCESTOR_OP) {
|
||||
aPattern = stepPattern;
|
||||
|
@ -221,40 +227,43 @@ nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
stepPattern = 0; // stepPattern is part of pathPattern now
|
||||
type = aLexer.peek()->type;
|
||||
type = aLexer.peek()->mType;
|
||||
}
|
||||
aPattern = pathPattern;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult txPatternParser::createIdPattern(ExprLexer& aLexer,
|
||||
nsresult txPatternParser::createIdPattern(txExprLexer& aLexer,
|
||||
txPattern*& aPattern)
|
||||
{
|
||||
// check for '(' Literal ')'
|
||||
if (aLexer.nextToken()->type != Token::L_PAREN &&
|
||||
aLexer.peek()->type != Token::LITERAL)
|
||||
if (aLexer.nextToken()->mType != Token::L_PAREN &&
|
||||
aLexer.peek()->mType != Token::LITERAL)
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
const nsString& value = aLexer.nextToken()->value;
|
||||
if (aLexer.nextToken()->type != Token::R_PAREN)
|
||||
const nsDependentSingleFragmentSubstring& value =
|
||||
aLexer.nextToken()->Value();
|
||||
if (aLexer.nextToken()->mType != Token::R_PAREN)
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
aPattern = new txIdPattern(value);
|
||||
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer,
|
||||
nsresult txPatternParser::createKeyPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern)
|
||||
{
|
||||
// check for '(' Literal, Literal ')'
|
||||
if (aLexer.nextToken()->type != Token::L_PAREN &&
|
||||
aLexer.peek()->type != Token::LITERAL)
|
||||
if (aLexer.nextToken()->mType != Token::L_PAREN &&
|
||||
aLexer.peek()->mType != Token::LITERAL)
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
const nsString& key = aLexer.nextToken()->value;
|
||||
if (aLexer.nextToken()->type != Token::COMMA &&
|
||||
aLexer.peek()->type != Token::LITERAL)
|
||||
const nsDependentSingleFragmentSubstring& key =
|
||||
aLexer.nextToken()->Value();
|
||||
if (aLexer.nextToken()->mType != Token::COMMA &&
|
||||
aLexer.peek()->mType != Token::LITERAL)
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
const nsString& value = aLexer.nextToken()->value;
|
||||
if (aLexer.nextToken()->type != Token::R_PAREN)
|
||||
const nsDependentSingleFragmentSubstring& value =
|
||||
aLexer.nextToken()->Value();
|
||||
if (aLexer.nextToken()->mType != Token::R_PAREN)
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
|
||||
if (!XMLUtils::isValidQName(key))
|
||||
|
@ -271,36 +280,36 @@ nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer,
|
|||
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult txPatternParser::createStepPattern(ExprLexer& aLexer,
|
||||
nsresult txPatternParser::createStepPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
MBool isAttr = MB_FALSE;
|
||||
Token* tok = aLexer.peek();
|
||||
if (tok->type == Token::AXIS_IDENTIFIER) {
|
||||
if (TX_StringEqualsAtom(tok->value, txXPathAtoms::attribute)) {
|
||||
if (tok->mType == Token::AXIS_IDENTIFIER) {
|
||||
if (TX_StringEqualsAtom(tok->Value(), txXPathAtoms::attribute)) {
|
||||
isAttr = MB_TRUE;
|
||||
}
|
||||
else if (!TX_StringEqualsAtom(tok->value, txXPathAtoms::child)) {
|
||||
else if (!TX_StringEqualsAtom(tok->Value(), txXPathAtoms::child)) {
|
||||
// all done already for CHILD_AXIS, for all others
|
||||
// XXX report unexpected axis error
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
}
|
||||
aLexer.nextToken();
|
||||
}
|
||||
else if (tok->type == Token::AT_SIGN) {
|
||||
else if (tok->mType == Token::AT_SIGN) {
|
||||
aLexer.nextToken();
|
||||
isAttr = MB_TRUE;
|
||||
}
|
||||
tok = aLexer.nextToken();
|
||||
|
||||
txNodeTest* nodeTest = 0;
|
||||
if (tok->type == Token::CNAME) {
|
||||
if (tok->mType == Token::CNAME) {
|
||||
// resolve QName
|
||||
nsCOMPtr<nsIAtom> prefix, lName;
|
||||
PRInt32 nspace;
|
||||
rv = resolveQName(tok->value, getter_AddRefs(prefix), aContext,
|
||||
rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
|
||||
getter_AddRefs(lName), nspace, PR_TRUE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX error report namespace resolve failed
|
||||
|
@ -320,11 +329,8 @@ nsresult txPatternParser::createStepPattern(ExprLexer& aLexer,
|
|||
}
|
||||
else {
|
||||
aLexer.pushBack();
|
||||
nodeTest = createNodeTypeTest(aLexer);
|
||||
if (!nodeTest) {
|
||||
// XXX error report NodeTest expected
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
}
|
||||
rv = createNodeTypeTest(aLexer, &nodeTest);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
txStepPattern* step = new txStepPattern(nodeTest, isAttr);
|
||||
|
@ -333,9 +339,10 @@ nsresult txPatternParser::createStepPattern(ExprLexer& aLexer,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
nodeTest = 0;
|
||||
if (!parsePredicates(step, aLexer, aContext)) {
|
||||
rv = parsePredicates(step, aLexer, aContext);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete step;
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
aPattern = step;
|
||||
|
|
|
@ -42,24 +42,24 @@
|
|||
#include "txXSLTPatterns.h"
|
||||
#include "ExprParser.h"
|
||||
|
||||
class txPatternParser : public ExprParser
|
||||
class txPatternParser : public txExprParser
|
||||
{
|
||||
public:
|
||||
static txPattern* createPattern(const nsAFlatString& aPattern,
|
||||
txIParseContext* aContext);
|
||||
protected:
|
||||
static nsresult createUnionPattern(ExprLexer& aLexer,
|
||||
static nsresult createUnionPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern);
|
||||
static nsresult createLocPathPattern(ExprLexer& aLexer,
|
||||
static nsresult createLocPathPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern);
|
||||
static nsresult createIdPattern(ExprLexer& aLexer,
|
||||
static nsresult createIdPattern(txExprLexer& aLexer,
|
||||
txPattern*& aPattern);
|
||||
static nsresult createKeyPattern(ExprLexer& aLexer,
|
||||
static nsresult createKeyPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern);
|
||||
static nsresult createStepPattern(ExprLexer& aLexer,
|
||||
static nsresult createStepPattern(txExprLexer& aLexer,
|
||||
txIParseContext* aContext,
|
||||
txPattern*& aPattern);
|
||||
};
|
||||
|
|
|
@ -189,13 +189,14 @@ getExprAttr(txStylesheetAttr* aAttributes,
|
|||
return rv;
|
||||
}
|
||||
|
||||
aExpr = ExprParser::createExpr(attr->mValue, &aState);
|
||||
if (!aExpr && (aRequired || !aState.fcp())) {
|
||||
// XXX ErrorReport: XPath parse failure
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
rv = txExprParser::createExpr(attr->mValue, &aState,
|
||||
getter_Transfers(aExpr));
|
||||
if (NS_SUCCEEDED(rv) && !aExpr && (aRequired || !aState.fcp())) {
|
||||
// XXX ErrorReport: empty required attr
|
||||
return NS_ERROR_XSLT_PARSE_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -214,7 +215,7 @@ getAVTAttr(txStylesheetAttr* aAttributes,
|
|||
return rv;
|
||||
}
|
||||
|
||||
aAVT = ExprParser::createAttributeValueTemplate(attr->mValue, &aState);
|
||||
aAVT = txExprParser::createAttributeValueTemplate(attr->mValue, &aState);
|
||||
if (!aAVT && (aRequired || !aState.fcp())) {
|
||||
// XXX ErrorReport: XPath parse failure
|
||||
return NS_ERROR_XPATH_PARSE_FAILURE;
|
||||
|
@ -1214,7 +1215,7 @@ txFnStartLRE(PRInt32 aNamespaceID,
|
|||
}
|
||||
|
||||
nsAutoPtr<Expr> avt(
|
||||
ExprParser::createAttributeValueTemplate(attr->mValue, &aState));
|
||||
txExprParser::createAttributeValueTemplate(attr->mValue, &aState));
|
||||
NS_ENSURE_TRUE(avt, NS_ERROR_XPATH_PARSE_FAILURE);
|
||||
|
||||
instr = new txLREAttribute(attr->mNamespaceID, attr->mLocalName,
|
||||
|
|
|
@ -941,7 +941,7 @@ txStylesheetCompilerState::caseInsensitiveNameTests()
|
|||
}
|
||||
|
||||
void
|
||||
txStylesheetCompilerState::receiveError(const nsAString& aMsg, nsresult aRes)
|
||||
txStylesheetCompilerState::SetErrorOffset(PRUint32 aOffset)
|
||||
{
|
||||
// XXX implement me
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ public:
|
|||
nsresult resolveFunctionCall(nsIAtom* aName, PRInt32 aID,
|
||||
FunctionCall*& aFunction);
|
||||
PRBool caseInsensitiveNameTests();
|
||||
void receiveError(const nsAString& aMsg, nsresult aRes);
|
||||
void SetErrorOffset(PRUint32 aOffset);
|
||||
|
||||
|
||||
nsRefPtr<txStylesheet> mStylesheet;
|
||||
|
|
Загрузка…
Ссылка в новой задаче