/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed 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 #include #include #include #include #include "xalanc/PlatformSupport/XalanMessageLoader.hpp" // Base class header file... #include #include XALAN_CPP_NAMESPACE_BEGIN 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 StringToStringMapType; typedef XalanVector BoolVectorType; XPathProcessorImpl(MemoryManagerType& theManager XALAN_DEFAULT_MEMMGR); virtual ~XPathProcessorImpl(); static XPathProcessorImpl* create(MemoryManagerType& theManager); // These are inherited from XPathProcessor... virtual void initXPath( XPath& pathObj, XPathConstructionContext& constructionContext, const XalanDOMString& expression, const PrefixResolver& resolver, const LocatorType* locator = 0, bool allowVariableReferences = true, bool allowKeyFunction = true); virtual void initMatchPattern( XPath& pathObj, XPathConstructionContext& constructionContext, const XalanDOMString& expression, const PrefixResolver& resolver, const LocatorType* 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. */ int mapNSTokens( const XalanDOMString& pat, int startSubstring, int posOfNSSep, int 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; }; #if defined(XALAN_STRICT_ANSI_HEADERS) typedef std::size_t size_type; #else typedef size_t size_type; #endif 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 charAt(0) 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 LocatorType* 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; }; XALAN_CPP_NAMESPACE_END #endif // XPATHPROCESSORIMPL_HEADER_GUARD_1357924680