6e19b8fda6f9083d556fa268d4e55fddafc373e4
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / parser / qparsercontext_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 //
43 //  W A R N I N G
44 //  -------------
45 //
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.
49 //
50 // We mean it.
51
52 #ifndef Patternist_ParserContext_H
53 #define Patternist_ParserContext_H
54
55 #include <QFlags>
56 #include <QSharedData>
57 #include <QStack>
58 #include <QStringList>
59 #include <QtGlobal>
60 #include <QXmlQuery>
61
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>
69
70 QT_BEGIN_HEADER
71
72 QT_BEGIN_NAMESPACE
73
74 namespace QPatternist
75 {
76     class Tokenizer;
77
78     /**
79      * @short Contains data used when parsing and tokenizing.
80      *
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.
84      *
85      * @author Frans Englich <frans.englich@nokia.com>
86      */
87     class ParserContext : public QSharedData
88     {
89     public:
90         typedef QExplicitlySharedDataPointer<ParserContext> Ptr;
91
92         enum PrologDeclaration
93         {
94             BoundarySpaceDecl               = 1,
95             DefaultCollationDecl            = 2,
96             BaseURIDecl                     = 4,
97             ConstructionDecl                = 8,
98             OrderingModeDecl                = 16,
99             EmptyOrderDecl                  = 32,
100             CopyNamespacesDecl              = 64,
101             DeclareDefaultElementNamespace  = 128,
102             DeclareDefaultFunctionNamespace = 256
103         };
104
105         typedef QFlags<PrologDeclaration> PrologDeclarations;
106
107         /**
108          * Constructs a ParserContext instance.
109          *
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
116          */
117         ParserContext(const StaticContext::Ptr &context,
118                       const QXmlQuery::QueryLanguage lang,
119                       Tokenizer *const tokenizer);
120
121         /**
122          * @short Removes the recently pushed variables from
123          * scope. The amount of removed variables is @p amount.
124          *
125          * finalizePushedVariable() can be seen as popping the variable.
126          *
127          */
128         void finalizePushedVariable(const int amount = 1,
129                                     const bool shouldPop = true);
130
131         inline VariableSlotID allocatePositionalSlot()
132         {
133             ++m_positionSlot;
134             return m_positionSlot;
135         }
136
137         inline VariableSlotID allocateExpressionSlot()
138         {
139             const VariableSlotID retval = m_expressionSlot;
140             ++m_expressionSlot;
141             return retval;
142         }
143
144         inline VariableSlotID allocateGlobalVariableSlot()
145         {
146             ++m_globalVariableSlot;
147             return m_globalVariableSlot;
148         }
149
150         inline bool hasDeclaration(const PrologDeclaration decl) const
151         {
152             return m_prologDeclarations.testFlag(decl);
153         }
154
155         inline void registerDeclaration(const PrologDeclaration decl)
156         {
157             m_prologDeclarations |= decl;
158         }
159
160         /**
161          * The namespaces declared with <tt>declare namespace</tt>.
162          */
163         QStringList declaredPrefixes;
164
165         /**
166          * This is a temporary stack, used for keeping variables in scope,
167          * such as for function arguments & let clauses.
168          */
169         VariableDeclaration::Stack variables;
170
171         inline bool isXSLT() const
172         {
173             return languageAccent == QXmlQuery::XSLT20;
174         }
175
176         const StaticContext::Ptr staticContext;
177         /**
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.
181          */
182         Tokenizer *const tokenizer;
183         const QXmlQuery::QueryLanguage languageAccent;
184
185         /**
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.
189          */
190         QXmlName initialTemplateName;
191
192         /**
193          * Used when parsing direct element constructors. It is used
194          * for ensuring tags are well-balanced.
195          */
196         QStack<QXmlName> tagStack;
197
198         /**
199          * The actual expression, the Query. This member may be @c null,
200          * such as in the case of an XQuery library module.
201          */
202         Expression::Ptr queryBody;
203
204         /**
205          * The user functions declared in the prolog.
206          */
207         UserFunction::List userFunctions;
208
209         /**
210          * Contains all calls to user defined functions.
211          */
212         UserFunctionCallsite::List userFunctionCallsites;
213
214         /**
215          * All variables declared with <tt>declare variable</tt>.
216          */
217         VariableDeclaration::List declaredVariables;
218
219         inline VariableSlotID currentPositionSlot() const
220         {
221             return m_positionSlot;
222         }
223
224         inline VariableSlotID currentExpressionSlot() const
225         {
226             return m_expressionSlot;
227         }
228
229         inline void restoreNodeTestSource()
230         {
231             nodeTestSource = BuiltinTypes::element;
232         }
233
234         inline VariableSlotID allocateCacheSlot()
235         {
236             return ++m_evaluationCacheSlot;
237         }
238
239         inline VariableSlotID allocateCacheSlots(const int count)
240         {
241             const VariableSlotID retval = m_evaluationCacheSlot + 1;
242             m_evaluationCacheSlot += count + 1;
243             return retval;
244         }
245
246         ItemType::Ptr nodeTestSource;
247
248         QStack<Expression::Ptr> typeswitchSource;
249
250         /**
251          * The library module namespace set with <tt>declare module</tt>.
252          */
253         QXmlName::NamespaceCode moduleNamespace;
254
255         /**
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.
259          */
260         QStack<NamespaceResolver::Ptr> resolvers;
261
262         /**
263          * This is used for handling the following obscene case:
264          *
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>
267          *
268          * This boolean tracks whether the previous reduction inside element
269          * content was done with an enclosed expression.
270          */
271         bool isPreviousEnclosedExpr;
272
273         int elementConstructorDepth;
274
275         QStack<bool> scanOnlyStack;
276
277         QStack<OrderBy::Stability> orderStability;
278
279         /**
280          * Whether any prolog declaration that must occur after the first
281          * group has been encountered.
282          */
283         bool hasSecondPrologPart;
284
285         bool preserveNamespacesMode;
286         bool inheritNamespacesMode;
287
288         /**
289          * Contains all named templates. Since named templates
290          * can also have rules, each body may also be in templateRules.
291          */
292         QHash<QXmlName, Template::Ptr>  namedTemplates;
293
294         /**
295          * All the @c xsl:call-template instructions that we have encountered.
296          */
297         QVector<Expression::Ptr>         templateCalls;
298
299         /**
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.
303          *
304          * We use a multi hash, since we can encounter several references to
305          * the same variable before it's declared.
306          */
307         QMultiHash<QXmlName, Expression::Ptr> unresolvedVariableReferences;
308
309         /**
310          *
311          * Contains the encountered template rules, as opposed
312          * to named templates.
313          *
314          * The key is the name of the template mode. If it's a default
315          * constructed value, it's the default mode.
316          *
317          * Since templates rules may also be named, each body may also be in
318          * namedTemplates.
319          *
320          * To be specific, the values are not the templates, the values are
321          * modes, and the TemplateMode contains the patterns and bodies.
322          */
323         QHash<QXmlName, TemplateMode::Ptr>  templateRules;
324
325         /**
326          * @short Returns the TemplateMode for @p modeName or @c null if the
327          * mode being asked for is @c #current.
328          */
329         TemplateMode::Ptr modeFor(const QXmlName &modeName)
330         {
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.
334              */
335             if(modeName == QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current))
336                 return TemplateMode::Ptr();
337
338             TemplateMode::Ptr &mode = templateRules[modeName];
339
340             if(!mode)
341                 mode = TemplateMode::Ptr(new TemplateMode(modeName));
342
343             Q_ASSERT(templateRules[modeName]);
344             return mode;
345         }
346
347         inline TemplatePattern::ID allocateTemplateID()
348         {
349             ++m_currentTemplateID;
350             return m_currentTemplateID;
351         }
352
353         /**
354          * The @c xsl:param appearing inside template.
355          */
356         VariableDeclaration::List templateParameters;
357
358         /**
359          * The @c xsl:with-param appearing in template calling instruction.
360          */
361         WithParam::Hash templateWithParams;
362
363         inline void templateParametersHandled()
364         {
365             finalizePushedVariable(templateParameters.count());
366             templateParameters.clear();
367         }
368
369         inline void templateWithParametersHandled()
370         {
371             templateWithParams.clear();
372         }
373
374         inline bool isParsingWithParam() const
375         {
376             return m_isParsingWithParam.top();
377         }
378
379         void startParsingWithParam()
380         {
381             m_isParsingWithParam.push(true);
382         }
383
384         void endParsingWithParam()
385         {
386             m_isParsingWithParam.pop();
387         }
388
389         /**
390          * This is used to deal with XSL-T's exception to the @c node() type,
391          * which doesn't match document nodes.
392          */
393         bool                                isParsingPattern;
394
395         ImportPrecedence                    currentImportPrecedence;
396
397         bool isFirstTemplate() const
398         {
399             return m_currentTemplateID == InitialTemplateID;
400         }
401
402         /**
403          * Whether we're processing XSL-T 1.0 code.
404          */
405         QStack<bool> isBackwardsCompat;
406
407     private:
408         enum
409         {
410             InitialTemplateID = -1
411         };
412
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;
419
420         /**
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.
423          */
424         QStack<bool>                        m_isParsingWithParam;
425         Q_DISABLE_COPY(ParserContext)
426     };
427 }
428
429 QT_END_NAMESPACE
430
431 QT_END_HEADER
432
433 #endif