blob: 51a7b8f70c83a1518b34007a33d5001bb5c5420a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(XPATHPROCESSORIMPL_HEADER_GUARD_1357924680)
#define XPATHPROCESSORIMPL_HEADER_GUARD_1357924680
// Base header file. Must be first.
#include <xalanc/XPath/XPathDefinitions.hpp>
#include <cstdlib>
#include <xalanc/XalanDOM/XalanDOMString.hpp>
#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanMap.hpp>
#include "xalanc/PlatformSupport/XalanMessageLoader.hpp"
// Base class header file...
#include <xalanc/XPath/XPathProcessor.hpp>
#include <xalanc/XPath/XPath.hpp>
namespace XALAN_CPP_NAMESPACE {
class XalanNode;
/**
* The XPathProcessorImpl class responsibilities include tokenizing and
* parsing the XPath expression, and acting as a general interface to XPaths.
*/
class XALAN_XPATH_EXPORT XPathProcessorImpl : public XPathProcessor
{
public:
typedef XalanMap<XalanDOMString,
const XalanDOMString*> StringToStringMapType;
typedef XalanVector<bool> BoolVectorType;
typedef XalanDOMString::size_type t_size_type;
XPathProcessorImpl(MemoryManager& theManager XALAN_DEFAULT_MEMMGR);
virtual
~XPathProcessorImpl();
static XPathProcessorImpl*
create(MemoryManager& theManager);
// These are inherited from XPathProcessor...
virtual void
initXPath(
XPath& pathObj,
XPathConstructionContext& constructionContext,
const XalanDOMString& expression,
const PrefixResolver& resolver,
const Locator* locator = 0,
bool allowVariableReferences = true,
bool allowKeyFunction = true);
virtual void
initMatchPattern(
XPath& pathObj,
XPathConstructionContext& constructionContext,
const XalanDOMString& expression,
const PrefixResolver& resolver,
const Locator* locator = 0,
bool allowVariableReferences = true,
bool allowKeyFunction = true);
private:
/**
* Walk through the expression and build a token queue, and a map of the
* top-level elements.
*
* @param pat XSLT Expression.
*/
void
tokenize(const XalanDOMString& pat);
void
addToTokenQueue(const XalanDOMString& s) const;
void
replaceTokenWithNamespaceToken() const;
/**
* When a separator token is found, see if there's a element name or the
* like to map.
*/
t_size_type
mapNSTokens(
const XalanDOMString& pat,
t_size_type startSubstring,
t_size_type posOfNSSep,
t_size_type posOfScan);
/**
* Check if m_token==s. If m_token is null, this won't throw
* an exception, instead it just returns false (or true
* if s is also null).
*/
bool
tokenIs(const XalanDOMString& s) const;
/**
* Check if m_token==s. If m_token is null, this won't throw
* an exception, instead it just returns false (or true
* if s is also null).
*/
bool
tokenIs(const XalanDOMChar* s) const;
/**
* Check if m_token==s. If m_token is null, this won't throw
* an exception, instead it just returns false (or true
* if s is also null).
*/
bool
tokenIs(XalanDOMChar c) const;
/**
* Lookahead of the current token in order to
* make a branching decision.
* @param s the string to compare it to.
* @param n number of tokens to lookahead. Must be
* greater than 1.
*/
bool
lookahead(
XalanDOMChar c,
int n) const;
/**
* Lookahead of the current token in order to
* make a branching decision.
* @param s the string to compare it to.
* @param n number of tokens to lookahead. Must be
* greater than 1.
*/
bool
lookahead(
const XalanDOMChar* s,
int n) const;
/**
* Lookahead of the current token in order to
* make a branching decision.
* @param s the string to compare it to.
* @param n number of tokens to lookahead. Must be
* greater than 1.
*/
bool
lookahead(
const XalanDOMString& s,
int n) const;
/**
* Lookbehind the first character of the current token in order to
* make a branching decision.
* @param c the character to compare it to.
* @param n number of tokens to lookbehind. Must be
* greater than 1. Note that the lookbehind terminates
* at either the beginning of the string or on a '|'
* character. Because of this, this method should only
* be used for pattern matching.
*/
bool
lookbehind(
char c,
int n) const;
/**
* look behind the current token in order to
* see if there is a useable token.
* @param n number of tokens to lookahead. Must be
* greater than 1. Note that the lookbehind terminates
* at either the beginning of the string or on a '|'
* character. Because of this, this method should only
* be used for pattern matching.
* @return true if lookbehind has a token, false otherwise.
*/
bool
lookbehindHasToken(int n) const;
/**
* Retrieve the next token from the command and
* store it in m_token string.
*/
bool
nextToken();
/**
* Retrieve the next token from the command and
* store it in m_token string.
*/
const XalanDOMString&
getTokenRelative(int theOffset) const;
/**
* Retrieve the previous token from the command and
* store it in m_token string.
*/
void
prevToken();
/**
* Consume an expected token, throwing an exception if it
* isn't there.
*/
void
consumeExpected(XalanDOMChar expected);
bool
isCurrentLiteral() const;
/**
* Determine if the token is an axis
*
* @param theToken The token to test
* @return true if the token is a valid axis, false if not.
*/
static bool
isAxis(const XalanDOMString& theToken);
/**
* Determine if the token could be a node test
*
* @param theToken The token to test
* @return true if the token is a valid node test, false if not.
*/
static bool
isNodeTest(const XalanDOMString& theToken);
/**
* Throw an exception using the provided message text.
*/
void
error(const XalanDOMString& msg) const;
/**
* Throw an exception using the provided message text.
*/
void
error(XalanMessages::Codes theCode) const;
void
error(
XalanMessages::Codes theCode,
const XalanDOMString& theToken) const;
void
error(
XalanMessages::Codes theCode,
const XalanDOMChar* theToken) const;
void
error(
XalanMessages::Codes theCode,
XalanDOMChar theToken1,
const XalanDOMString& theToken2) const;
/**
* Given a string, return the corresponding token.
*/
static XPathExpression::eOpCodes
getFunctionToken(const XalanDOMString& key)
{
return searchTable(s_functionTable, s_functionTableSize, key).m_opCode;
}
/**
* Given a string, return the corresponding token.
*/
static XPathExpression::eOpCodes
getNodeTypeToken(const XalanDOMString& key)
{
return searchTable(s_nodeTypeTable, s_nodeTypeTableSize, key).m_opCode;
}
/**
* Given a string, return the corresponding token.
*/
static XPathExpression::eOpCodes
getAxisToken(const XalanDOMString& key)
{
return searchTable(s_axisTable, s_axisTableSize, key).m_opCode;
}
/**
*
* --------------------------------------------------------------------------------
Expr ::= OrExpr
* --------------------------------------------------------------------------------
*/
void
Expr();
/**
*
* --------------------------------------------------------------------------------
OrExpr ::= AndExpr
| OrExpr 'or' AndExpr
* --------------------------------------------------------------------------------
*/
void
OrExpr();
/**
*
* --------------------------------------------------------------------------------
AndExpr ::= EqualityExpr
| AndExpr 'and' EqualityExpr
* --------------------------------------------------------------------------------
*/
void
AndExpr() ;
/**
* XXXX.
* @returns an Object which is either a String, a Number, a Boolean, or a vector
* of nodes.
* --------------------------------------------------------------------------------
EqualityExpr ::= RelationalExpr
| EqualityExpr '=' RelationalExpr
* --------------------------------------------------------------------------------
*/
int
EqualityExpr(int opCodePos = -1);
/**
* XXXX.
* @returns an Object which is either a String, a Number, a Boolean, or a vector
* of nodes.
* --------------------------------------------------------------------------------
RelationalExpr ::= AdditiveExpr
| RelationalExpr '<' AdditiveExpr
| RelationalExpr '>' AdditiveExpr
| RelationalExpr '<=' AdditiveExpr
| RelationalExpr '>=' AdditiveExpr
* --------------------------------------------------------------------------------
*/
int
RelationalExpr(int opCodePos = -1);
/**
* XXXX.
* @returns an Object which is either a String, a Number, a Boolean, or a vector
* of nodes.
* --------------------------------------------------------------------------------
AdditiveExpr ::= MultiplicativeExpr
| AdditiveExpr '+' MultiplicativeExpr
| AdditiveExpr '-' MultiplicativeExpr
* --------------------------------------------------------------------------------
*/
int
AdditiveExpr(int opCodePos = -1);
/**
* XXXX.
* @returns an Object which is either a String, a Number, a Boolean, or a vector
* of nodes.
* --------------------------------------------------------------------------------
MultiplicativeExpr ::= UnaryExpr
| MultiplicativeExpr MultiplyOperator UnaryExpr
| MultiplicativeExpr 'div' UnaryExpr
| MultiplicativeExpr 'mod' UnaryExpr
| MultiplicativeExpr 'quo' UnaryExpr
* --------------------------------------------------------------------------------
*/
int
MultiplicativeExpr(int opCodePos = -1);
/**
* XXXX.
* @returns an Object which is either a String, a Number, a Boolean, or a vector
* of nodes.
* --------------------------------------------------------------------------------
UnaryExpr ::= UnionExpr
| '-' UnaryExpr
* --------------------------------------------------------------------------------
*/
void
UnaryExpr();
/**
* The context of the right hand side expressions is the context of the
* left hand side expression. The results of the right hand side expressions
* are node sets. The result of the left hand side UnionExpr is the union
* of the results of the right hand side expressions.
*
* --------------------------------------------------------------------------------
UnionExpr ::= PathExpr
| UnionExpr '|' PathExpr
* --------------------------------------------------------------------------------
*/
void
UnionExpr();
/**
*
* --------------------------------------------------------------------------------
PathExpr ::= LocationPath
| FilterExpr
| FilterExpr '/' RelativeLocationPath
| FilterExpr '//' RelativeLocationPath
* --------------------------------------------------------------------------------
* @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
* the error condition is severe enough to halt processing.
*/
void
PathExpr();
/**
*
* --------------------------------------------------------------------------------
FilterExpr ::= PrimaryExpr
| FilterExpr Predicate
* --------------------------------------------------------------------------------
* @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
* the error condition is severe enough to halt processing.
*/
void
FilterExpr();
/**
* --------------------------------------------------------------------------------
PrimaryExpr ::= VariableReference
| '(' Expr ')'
| Literal
| Number
| FunctionCall
* --------------------------------------------------------------------------------
*/
void
PrimaryExpr();
/**
* --------------------------------------------------------------------------------
Argument ::= Expr
* --------------------------------------------------------------------------------
*/
void
Argument();
/**
* --------------------------------------------------------------------------------
FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')'
* --------------------------------------------------------------------------------
*/
void
FunctionCall();
void
FunctionPosition();
void
FunctionLast();
void
FunctionCount();
void
FunctionNot();
void
FunctionTrue();
void
FunctionFalse();
void
FunctionBoolean();
void
FunctionName(int opPos);
void
FunctionLocalName(int opPos);
void
FunctionNumber(int opPos);
void
FunctionFloor();
void
FunctionCeiling();
void
FunctionRound();
void
FunctionString(int opPos);
void
FunctionStringLength(int opPos);
void
FunctionSum();
void
FunctionNamespaceURI(int opPos);
/**
* --------------------------------------------------------------------------------
LocationPath ::= RelativeLocationPath
| AbsoluteLocationPath
* --------------------------------------------------------------------------------
*/
void
LocationPath();
/**
* --------------------------------------------------------------------------------
RelativeLocationPath ::= Step
| RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath
* --------------------------------------------------------------------------------
*/
void
RelativeLocationPath();
/**
* --------------------------------------------------------------------------------
Step ::= Basis Predicate*
| AbbreviatedStep
*/
void
Step();
/**
* --------------------------------------------------------------------------------
Basis ::= AxisName '::' NodeTest
| AbbreviatedBasis
*/
void
Basis();
/**
* --------------------------------------------------------------------------------
Basis ::= AxisName '::' NodeTest
| AbbreviatedBasis
*/
XPathExpression::eOpCodes
AxisName();
/**
* --------------------------------------------------------------------------------
NodeTest ::= WildcardName
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
*/
int
NodeTest();
/**
* --------------------------------------------------------------------------------
Predicate ::= '[' PredicateExpr ']'
* --------------------------------------------------------------------------------
*/
void
Predicate();
/**
*--------------------------------------------------------------------------------
PredicateExpr ::= Expr
*--------------------------------------------------------------------------------
*/
void
PredicateExpr();
/**
* QName ::= (Prefix ':')? LocalPart
* Prefix ::= NCName
* LocalPart ::= NCName
*/
void
QName();
/**
* NCName ::= (Letter | '_') (NCNameChar)*
* NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
*/
void
NCName();
/**
* The value of the Literal is the sequence of characters inside
* the " or ' characters>.
* --------------------------------------------------------------------------------
Literal ::= '"' [^"]* '"'
| "'" [^']* "'"
* --------------------------------------------------------------------------------
*/
void
Literal();
/**
* --------------------------------------------------------------------------------
* Number ::= [0-9]+('.'[0-9]+)? | '.'[0-9]+
* --------------------------------------------------------------------------------
*/
void
Number();
/**
* --------------------------------------------------------------------------------
Pattern ::= LocationPathPattern
| Pattern '|' LocationPathPattern
* --------------------------------------------------------------------------------
*/
void
Pattern();
/**
*
* --------------------------------------------------------------------------------
LocationPathPattern ::= '/' RelativePathPattern?
| IdKeyPattern (('/' | '//') RelativePathPattern)?
| '//'? RelativePathPattern
* --------------------------------------------------------------------------------
*/
void
LocationPathPattern();
/**
* --------------------------------------------------------------------------------
IdKeyPattern ::= 'id' '(' Literal ')'
| 'key' '(' Literal ',' Literal ')'
* (Also handle doc())
* --------------------------------------------------------------------------------
*/
void
IdKeyPattern();
/**
* --------------------------------------------------------------------------------
RelativePathPattern ::= StepPattern
| RelativePathPattern '/' StepPattern
| RelativePathPattern '//' StepPattern
* --------------------------------------------------------------------------------
*/
void
RelativePathPattern();
/**
* --------------------------------------------------------------------------------
StepPattern ::= AbbreviatedNodeTestStep
* --------------------------------------------------------------------------------
*/
void
StepPattern();
/**
* --------------------------------------------------------------------------------
AbbreviatedNodeTestStep ::= '@'? NodeTest Predicate*
* --------------------------------------------------------------------------------
*/
void
AbbreviatedNodeTestStep();
static bool
isValidFunction(const XalanDOMString& key);
private:
int
FunctionCallArguments();
struct TableEntry
{
const XalanDOMChar* m_string;
XPathExpression::eOpCodes m_opCode;
};
typedef std::size_t size_type;
static const TableEntry&
searchTable(
const TableEntry theTable[],
size_type theTableSize,
const XalanDOMString& theString);
/**
* The current input token.
*/
XalanDOMString m_token;
/**
* The first char in m_token, the theory being that this
* is an optimization because we won't have to do index
* into the string as often.
*/
XalanDOMChar m_tokenChar;
/**
* A pointer to the current XPath.
*/
XPath* m_xpath;
/**
* A pointer to the current XPathConstructionContext.
*/
XPathConstructionContext* m_constructionContext;
/**
* A pointer to the current XPath's expression.
*/
XPathExpression* m_expression;
/**
* A pointer to the current executionContext.
*/
const PrefixResolver* m_prefixResolver;
bool m_requireLiterals;
bool m_isMatchPattern;
const Locator* m_locator;
BoolVectorType m_positionPredicateStack;
StringToStringMapType m_namespaces;
bool m_allowVariableReferences;
bool m_allowKeyFunction;
// Static stuff here...
static const XalanDOMString s_emptyString;
static const XalanDOMChar s_functionIDString[];
// This shouldn't really be here, since it's not part of the XPath standard,
// but rather a part ofthe XSLT standard.
static const XalanDOMChar s_functionKeyString[];
static const XalanDOMChar s_orString[];
static const XalanDOMChar s_andString[];
static const XalanDOMChar s_divString[];
static const XalanDOMChar s_modString[];
static const XalanDOMChar s_dotString[];
static const XalanDOMChar s_dotDotString[];
static const XalanDOMChar s_axisString[];
static const XalanDOMChar s_attributeString[];
static const XalanDOMChar s_childString[];
static const XalanDOMChar s_lastString[];
static const XalanDOMChar s_positionString[];
static const XalanDOMChar s_asteriskString[];
static const XalanDOMChar s_commentString[];
static const XalanDOMChar s_piString[];
static const XalanDOMChar s_nodeString[];
static const XalanDOMChar s_textString[];
static const XalanDOMChar s_ancestorString[];
static const XalanDOMChar s_ancestorOrSelfString[];
static const XalanDOMChar s_descendantString[];
static const XalanDOMChar s_descendantOrSelfString[];
static const XalanDOMChar s_followingString[];
static const XalanDOMChar s_followingSiblingString[];
static const XalanDOMChar s_parentString[];
static const XalanDOMChar s_precedingString[];
static const XalanDOMChar s_precedingSiblingString[];
static const XalanDOMChar s_selfString[];
static const XalanDOMChar s_namespaceString[];
static const TableEntry s_functionTable[];
static const size_type s_functionTableSize;
static const TableEntry s_nodeTypeTable[];
static const size_type s_nodeTypeTableSize;
static const TableEntry s_axisTable[];
static const size_type s_axisTableSize;
static const TableEntry s_dummyEntry;
};
}
#endif // XPATHPROCESSORIMPL_HEADER_GUARD_1357924680