bug 206445, nsresult based error reporting in XPath expression parser and lexer, r=sicking, sr=peterv

This commit is contained in:
axel%pike.org 2003-09-26 12:32:42 +00:00
Родитель e608b7e0f4
Коммит 9ee5c3e892
29 изменённых файлов: 1314 добавлений и 1140 удалений

Просмотреть файл

@ -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;