1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//
41// W A R N I N G
42// -------------
43//
44// This file is not part of the Qt API. It exists purely as an
45// implementation detail. This header file may change from version to
46// version without notice, or even be removed.
47//
48// We mean it.
49
50#ifndef Patternist_ParserContext_H
51#define Patternist_ParserContext_H
52
53#include <QFlags>
54#include <QSharedData>
55#include <QStack>
56#include <QStringList>
57#include <QtGlobal>
58#include <QXmlQuery>
59
60#include <private/qbuiltintypes_p.h>
61#include <private/qfunctionsignature_p.h>
62#include <private/qorderby_p.h>
63#include <private/qtemplatemode_p.h>
64#include <private/quserfunctioncallsite_p.h>
65#include <private/quserfunction_p.h>
66#include <private/qvariabledeclaration_p.h>
67#include <private/qtokenvalue_p.h>
68
69QT_BEGIN_NAMESPACE
70
71namespace QPatternist
72{
73 class Tokenizer;
74
75 /**
76 * @short Contains data used when parsing and tokenizing.
77 *
78 * When ExpressionFactory::create() is called, an instance of this class
79 * is passed to the scanner and parser. It holds all information that is
80 * needed to create the expression.
81 *
82 * @author Frans Englich <frans.englich@nokia.com>
83 */
84 class ParserContext : public QSharedData
85 {
86 public:
87 typedef QExplicitlySharedDataPointer<ParserContext> Ptr;
88
89 enum PrologDeclaration
90 {
91 BoundarySpaceDecl = 1,
92 DefaultCollationDecl = 2,
93 BaseURIDecl = 4,
94 ConstructionDecl = 8,
95 OrderingModeDecl = 16,
96 EmptyOrderDecl = 32,
97 CopyNamespacesDecl = 64,
98 DeclareDefaultElementNamespace = 128,
99 DeclareDefaultFunctionNamespace = 256
100 };
101
102 typedef QFlags<PrologDeclaration> PrologDeclarations;
103
104 /**
105 * Constructs a ParserContext instance.
106 *
107 * @param context the static context as defined in XPath. This contain
108 * namespace bindings, error handler, and other information necessary
109 * for creating an XPath expression.
110 * @param lang the particular XPath language sub-set that should be parsed
111 * @param tokenizer the Tokenizer to use.
112 * @see ExpressionFactory::LanguageAccent
113 */
114 ParserContext(const StaticContext::Ptr &context,
115 const QXmlQuery::QueryLanguage lang,
116 Tokenizer *const tokenizer);
117
118 /**
119 * @short Removes the recently pushed variables from
120 * scope. The amount of removed variables is @p amount.
121 *
122 * finalizePushedVariable() can be seen as popping the variable.
123 *
124 */
125 void finalizePushedVariable(const int amount = 1,
126 const bool shouldPop = true);
127
128 inline VariableSlotID allocatePositionalSlot()
129 {
130 ++m_positionSlot;
131 return m_positionSlot;
132 }
133
134 inline VariableSlotID allocateExpressionSlot()
135 {
136 const VariableSlotID retval = m_expressionSlot;
137 ++m_expressionSlot;
138 return retval;
139 }
140
141 inline VariableSlotID allocateGlobalVariableSlot()
142 {
143 ++m_globalVariableSlot;
144 return m_globalVariableSlot;
145 }
146
147 inline bool hasDeclaration(const PrologDeclaration decl) const
148 {
149 return m_prologDeclarations.testFlag(flag: decl);
150 }
151
152 inline void registerDeclaration(const PrologDeclaration decl)
153 {
154 m_prologDeclarations |= decl;
155 }
156
157 /**
158 * The namespaces declared with <tt>declare namespace</tt>.
159 */
160 QStringList declaredPrefixes;
161
162 /**
163 * This is a temporary stack, used for keeping variables in scope,
164 * such as for function arguments & let clauses.
165 */
166 VariableDeclaration::Stack variables;
167
168 inline bool isXSLT() const
169 {
170 return languageAccent == QXmlQuery::XSLT20;
171 }
172
173 const StaticContext::Ptr staticContext;
174 /**
175 * We don't store a Tokenizer::Ptr here, because then we would get a
176 * circular referencing between ParserContext and XSLTTokenizer, and
177 * hence they would never destruct.
178 */
179 Tokenizer *const tokenizer;
180 const QXmlQuery::QueryLanguage languageAccent;
181
182 /**
183 * Only used in the case of XSL-T. Is the name of the initial template
184 * to call. If null, no name was provided, and regular template
185 * matching should be done.
186 */
187 QXmlName initialTemplateName;
188
189 /**
190 * Used when parsing direct element constructors. It is used
191 * for ensuring tags are well-balanced.
192 */
193 QStack<QXmlName> tagStack;
194
195 /**
196 * The actual expression, the Query. This member may be @c null,
197 * such as in the case of an XQuery library module.
198 */
199 Expression::Ptr queryBody;
200
201 /**
202 * The user functions declared in the prolog.
203 */
204 UserFunction::List userFunctions;
205
206 /**
207 * Contains all calls to user defined functions.
208 */
209 UserFunctionCallsite::List userFunctionCallsites;
210
211 /**
212 * All variables declared with <tt>declare variable</tt>.
213 */
214 VariableDeclaration::List declaredVariables;
215
216 QVector<qint16> parserStack_yyss;
217 QVector<TokenValue> parserStack_yyvs;
218 QVector<XPATHLTYPE> parserStack_yyls;
219
220 void handleStackOverflow(const char*, short **yyss, size_t, TokenValue **yyvs, size_t,
221 XPATHLTYPE **yyls, size_t, size_t *yystacksize);
222
223 inline VariableSlotID currentPositionSlot() const
224 {
225 return m_positionSlot;
226 }
227
228 inline VariableSlotID currentExpressionSlot() const
229 {
230 return m_expressionSlot;
231 }
232
233 inline void restoreNodeTestSource()
234 {
235 nodeTestSource = BuiltinTypes::element;
236 }
237
238 inline VariableSlotID allocateCacheSlot()
239 {
240 return ++m_evaluationCacheSlot;
241 }
242
243 inline VariableSlotID allocateCacheSlots(const int count)
244 {
245 const VariableSlotID retval = m_evaluationCacheSlot + 1;
246 m_evaluationCacheSlot += count + 1;
247 return retval;
248 }
249
250 ItemType::Ptr nodeTestSource;
251
252 QStack<Expression::Ptr> typeswitchSource;
253
254 /**
255 * The library module namespace set with <tt>declare module</tt>.
256 */
257 QXmlName::NamespaceCode moduleNamespace;
258
259 /**
260 * When a direct element constructor is processed, resolvers are
261 * created in order to carry the namespace declarations. In such case,
262 * the old resolver is pushed here.
263 */
264 QStack<NamespaceResolver::Ptr> resolvers;
265
266 /**
267 * This is used for handling the following obscene case:
268 *
269 * - <tt>\<e\>{1}{1}\<\/e\></tt> produce <tt>\<e\>11\</e\></tt>
270 * - <tt>\<e\>{1, 1}\<\/e\></tt> produce <tt>\<e\>1 1\</e\></tt>
271 *
272 * This boolean tracks whether the previous reduction inside element
273 * content was done with an enclosed expression.
274 */
275 bool isPreviousEnclosedExpr;
276
277 int elementConstructorDepth;
278
279 QStack<bool> scanOnlyStack;
280
281 QStack<OrderBy::Stability> orderStability;
282
283 /**
284 * Whether any prolog declaration that must occur after the first
285 * group has been encountered.
286 */
287 bool hasSecondPrologPart;
288
289 bool preserveNamespacesMode;
290 bool inheritNamespacesMode;
291
292 /**
293 * Contains all named templates. Since named templates
294 * can also have rules, each body may also be in templateRules.
295 */
296 QHash<QXmlName, Template::Ptr> namedTemplates;
297
298 /**
299 * All the @c xsl:call-template instructions that we have encountered.
300 */
301 QVector<Expression::Ptr> templateCalls;
302
303 /**
304 * If we're in XSL-T, and a variable reference is encountered
305 * which isn't in-scope, it's added to this hash since a global
306 * variable declaration may appear later on.
307 *
308 * We use a multi hash, since we can encounter several references to
309 * the same variable before it's declared.
310 */
311 QMultiHash<QXmlName, Expression::Ptr> unresolvedVariableReferences;
312
313 /**
314 *
315 * Contains the encountered template rules, as opposed
316 * to named templates.
317 *
318 * The key is the name of the template mode. If it's a default
319 * constructed value, it's the default mode.
320 *
321 * Since templates rules may also be named, each body may also be in
322 * namedTemplates.
323 *
324 * To be specific, the values are not the templates, the values are
325 * modes, and the TemplateMode contains the patterns and bodies.
326 */
327 QHash<QXmlName, TemplateMode::Ptr> templateRules;
328
329 /**
330 * @short Returns the TemplateMode for @p modeName or @c null if the
331 * mode being asked for is @c #current.
332 */
333 TemplateMode::Ptr modeFor(const QXmlName &modeName)
334 {
335 /* #current is not a mode, so it cannot contain templates. #current
336 * specifies how to look up templates wrt. mode. This check helps
337 * code that calls us, asking for the mode it needs to lookup in.
338 */
339 if(modeName == QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current))
340 return TemplateMode::Ptr();
341
342 TemplateMode::Ptr &mode = templateRules[modeName];
343
344 if(!mode)
345 mode = TemplateMode::Ptr(new TemplateMode(modeName));
346
347 Q_ASSERT(templateRules[modeName]);
348 return mode;
349 }
350
351 inline TemplatePattern::ID allocateTemplateID()
352 {
353 ++m_currentTemplateID;
354 return m_currentTemplateID;
355 }
356
357 /**
358 * The @c xsl:param appearing inside template.
359 */
360 VariableDeclaration::List templateParameters;
361
362 /**
363 * The @c xsl:with-param appearing in template calling instruction.
364 */
365 WithParam::Hash templateWithParams;
366
367 inline void templateParametersHandled()
368 {
369 finalizePushedVariable(amount: templateParameters.count());
370 templateParameters.clear();
371 }
372
373 inline void templateWithParametersHandled()
374 {
375 templateWithParams.clear();
376 }
377
378 inline bool isParsingWithParam() const
379 {
380 return m_isParsingWithParam.top();
381 }
382
383 void startParsingWithParam()
384 {
385 m_isParsingWithParam.push(t: true);
386 }
387
388 void endParsingWithParam()
389 {
390 m_isParsingWithParam.pop();
391 }
392
393 /**
394 * This is used to deal with XSL-T's exception to the @c node() type,
395 * which doesn't match document nodes.
396 */
397 bool isParsingPattern;
398
399 ImportPrecedence currentImportPrecedence;
400
401 bool isFirstTemplate() const
402 {
403 return m_currentTemplateID == InitialTemplateID;
404 }
405
406 /**
407 * Whether we're processing XSL-T 1.0 code.
408 */
409 QStack<bool> isBackwardsCompat;
410
411 private:
412 enum
413 {
414 InitialTemplateID = -1
415 };
416
417 VariableSlotID m_evaluationCacheSlot;
418 VariableSlotID m_expressionSlot;
419 VariableSlotID m_positionSlot;
420 PrologDeclarations m_prologDeclarations;
421 VariableSlotID m_globalVariableSlot;
422 TemplatePattern::ID m_currentTemplateID;
423
424 /**
425 * The default is @c false. If we're not parsing @c xsl:with-param,
426 * hence parsing @c xsl:param, the value has changed.
427 */
428 QStack<bool> m_isParsingWithParam;
429 Q_DISABLE_COPY(ParserContext)
430 };
431}
432
433QT_END_NAMESPACE
434
435#endif
436

source code of qtxmlpatterns/src/xmlpatterns/parser/qparsercontext_p.h