1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
46 // This file is not part of the Qt API. It exists purely as an
47 // implementation detail. This header file may change from version to
48 // version without notice, or even be removed.
52 #ifndef Patternist_ParserContext_H
53 #define Patternist_ParserContext_H
56 #include <QSharedData>
58 #include <QStringList>
62 #include <private/qbuiltintypes_p.h>
63 #include <private/qfunctionsignature_p.h>
64 #include <private/qorderby_p.h>
65 #include <private/qtemplatemode_p.h>
66 #include <private/quserfunctioncallsite_p.h>
67 #include <private/quserfunction_p.h>
68 #include <private/qvariabledeclaration_p.h>
79 * @short Contains data used when parsing and tokenizing.
81 * When ExpressionFactory::create() is called, an instance of this class
82 * is passed to the scanner and parser. It holds all information that is
83 * needed to create the expression.
85 * @author Frans Englich <frans.englich@nokia.com>
87 class ParserContext : public QSharedData
90 typedef QExplicitlySharedDataPointer<ParserContext> Ptr;
92 enum PrologDeclaration
94 BoundarySpaceDecl = 1,
95 DefaultCollationDecl = 2,
98 OrderingModeDecl = 16,
100 CopyNamespacesDecl = 64,
101 DeclareDefaultElementNamespace = 128,
102 DeclareDefaultFunctionNamespace = 256
105 typedef QFlags<PrologDeclaration> PrologDeclarations;
108 * Constructs a ParserContext instance.
110 * @param context the static context as defined in XPath. This contain
111 * namespace bindings, error handler, and other information necessary
112 * for creating an XPath expression.
113 * @param lang the particular XPath language sub-set that should be parsed
114 * @param tokenizer the Tokenizer to use.
115 * @see ExpressionFactory::LanguageAccent
117 ParserContext(const StaticContext::Ptr &context,
118 const QXmlQuery::QueryLanguage lang,
119 Tokenizer *const tokenizer);
122 * @short Removes the recently pushed variables from
123 * scope. The amount of removed variables is @p amount.
125 * finalizePushedVariable() can be seen as popping the variable.
128 void finalizePushedVariable(const int amount = 1,
129 const bool shouldPop = true);
131 inline VariableSlotID allocatePositionalSlot()
134 return m_positionSlot;
137 inline VariableSlotID allocateExpressionSlot()
139 const VariableSlotID retval = m_expressionSlot;
144 inline VariableSlotID allocateGlobalVariableSlot()
146 ++m_globalVariableSlot;
147 return m_globalVariableSlot;
150 inline bool hasDeclaration(const PrologDeclaration decl) const
152 return m_prologDeclarations.testFlag(decl);
155 inline void registerDeclaration(const PrologDeclaration decl)
157 m_prologDeclarations |= decl;
161 * The namespaces declared with <tt>declare namespace</tt>.
163 QStringList declaredPrefixes;
166 * This is a temporary stack, used for keeping variables in scope,
167 * such as for function arguments & let clauses.
169 VariableDeclaration::Stack variables;
171 inline bool isXSLT() const
173 return languageAccent == QXmlQuery::XSLT20;
176 const StaticContext::Ptr staticContext;
178 * We don't store a Tokenizer::Ptr here, because then we would get a
179 * circular referencing between ParserContext and XSLTTokenizer, and
180 * hence they would never destruct.
182 Tokenizer *const tokenizer;
183 const QXmlQuery::QueryLanguage languageAccent;
186 * Only used in the case of XSL-T. Is the name of the initial template
187 * to call. If null, no name was provided, and regular template
188 * matching should be done.
190 QXmlName initialTemplateName;
193 * Used when parsing direct element constructors. It is used
194 * for ensuring tags are well-balanced.
196 QStack<QXmlName> tagStack;
199 * The actual expression, the Query. This member may be @c null,
200 * such as in the case of an XQuery library module.
202 Expression::Ptr queryBody;
205 * The user functions declared in the prolog.
207 UserFunction::List userFunctions;
210 * Contains all calls to user defined functions.
212 UserFunctionCallsite::List userFunctionCallsites;
215 * All variables declared with <tt>declare variable</tt>.
217 VariableDeclaration::List declaredVariables;
219 inline VariableSlotID currentPositionSlot() const
221 return m_positionSlot;
224 inline VariableSlotID currentExpressionSlot() const
226 return m_expressionSlot;
229 inline void restoreNodeTestSource()
231 nodeTestSource = BuiltinTypes::element;
234 inline VariableSlotID allocateCacheSlot()
236 return ++m_evaluationCacheSlot;
239 inline VariableSlotID allocateCacheSlots(const int count)
241 const VariableSlotID retval = m_evaluationCacheSlot + 1;
242 m_evaluationCacheSlot += count + 1;
246 ItemType::Ptr nodeTestSource;
248 QStack<Expression::Ptr> typeswitchSource;
251 * The library module namespace set with <tt>declare module</tt>.
253 QXmlName::NamespaceCode moduleNamespace;
256 * When a direct element constructor is processed, resolvers are
257 * created in order to carry the namespace declarations. In such case,
258 * the old resolver is pushed here.
260 QStack<NamespaceResolver::Ptr> resolvers;
263 * This is used for handling the following obscene case:
265 * - <tt>\<e\>{1}{1}\<\/e\></tt> produce <tt>\<e\>11\</e\></tt>
266 * - <tt>\<e\>{1, 1}\<\/e\></tt> produce <tt>\<e\>1 1\</e\></tt>
268 * This boolean tracks whether the previous reduction inside element
269 * content was done with an enclosed expression.
271 bool isPreviousEnclosedExpr;
273 int elementConstructorDepth;
275 QStack<bool> scanOnlyStack;
277 QStack<OrderBy::Stability> orderStability;
280 * Whether any prolog declaration that must occur after the first
281 * group has been encountered.
283 bool hasSecondPrologPart;
285 bool preserveNamespacesMode;
286 bool inheritNamespacesMode;
289 * Contains all named templates. Since named templates
290 * can also have rules, each body may also be in templateRules.
292 QHash<QXmlName, Template::Ptr> namedTemplates;
295 * All the @c xsl:call-template instructions that we have encountered.
297 QVector<Expression::Ptr> templateCalls;
300 * If we're in XSL-T, and a variable reference is encountered
301 * which isn't in-scope, it's added to this hash since a global
302 * variable declaration may appear later on.
304 * We use a multi hash, since we can encounter several references to
305 * the same variable before it's declared.
307 QMultiHash<QXmlName, Expression::Ptr> unresolvedVariableReferences;
311 * Contains the encountered template rules, as opposed
312 * to named templates.
314 * The key is the name of the template mode. If it's a default
315 * constructed value, it's the default mode.
317 * Since templates rules may also be named, each body may also be in
320 * To be specific, the values are not the templates, the values are
321 * modes, and the TemplateMode contains the patterns and bodies.
323 QHash<QXmlName, TemplateMode::Ptr> templateRules;
326 * @short Returns the TemplateMode for @p modeName or @c null if the
327 * mode being asked for is @c #current.
329 TemplateMode::Ptr modeFor(const QXmlName &modeName)
331 /* #current is not a mode, so it cannot contain templates. #current
332 * specifies how to look up templates wrt. mode. This check helps
333 * code that calls us, asking for the mode it needs to lookup in.
335 if(modeName == QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current))
336 return TemplateMode::Ptr();
338 TemplateMode::Ptr &mode = templateRules[modeName];
341 mode = TemplateMode::Ptr(new TemplateMode(modeName));
343 Q_ASSERT(templateRules[modeName]);
347 inline TemplatePattern::ID allocateTemplateID()
349 ++m_currentTemplateID;
350 return m_currentTemplateID;
354 * The @c xsl:param appearing inside template.
356 VariableDeclaration::List templateParameters;
359 * The @c xsl:with-param appearing in template calling instruction.
361 WithParam::Hash templateWithParams;
363 inline void templateParametersHandled()
365 finalizePushedVariable(templateParameters.count());
366 templateParameters.clear();
369 inline void templateWithParametersHandled()
371 templateWithParams.clear();
374 inline bool isParsingWithParam() const
376 return m_isParsingWithParam.top();
379 void startParsingWithParam()
381 m_isParsingWithParam.push(true);
384 void endParsingWithParam()
386 m_isParsingWithParam.pop();
390 * This is used to deal with XSL-T's exception to the @c node() type,
391 * which doesn't match document nodes.
393 bool isParsingPattern;
395 ImportPrecedence currentImportPrecedence;
397 bool isFirstTemplate() const
399 return m_currentTemplateID == InitialTemplateID;
403 * Whether we're processing XSL-T 1.0 code.
405 QStack<bool> isBackwardsCompat;
410 InitialTemplateID = -1
413 VariableSlotID m_evaluationCacheSlot;
414 VariableSlotID m_expressionSlot;
415 VariableSlotID m_positionSlot;
416 PrologDeclarations m_prologDeclarations;
417 VariableSlotID m_globalVariableSlot;
418 TemplatePattern::ID m_currentTemplateID;
421 * The default is @c false. If we're not parsing @c xsl:with-param,
422 * hence parsing @c xsl:param, the value has changed.
424 QStack<bool> m_isParsingWithParam;
425 Q_DISABLE_COPY(ParserContext)