1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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_XSLTTokenizer_H
53 #define Patternist_XSLTTokenizer_H
59 #include <private/qmaintainingreader_p.h>
60 #include <private/qreportcontext_p.h>
61 #include <private/qtokenizer_p.h>
62 #include <private/qxslttokenlookup_p.h>
71 * @short A TokenSource which contains one Tokenizer::Token.
73 * One possible way to optimize this is to let SingleTokenContainer
74 * actually contain a list of tokens, such that XSLTTokenizer::queueToken()
75 * could append to that, instead of instansiating a SingleTokenContainer
78 * @author Frans Englich <frans.englich@nokia.com>
80 class SingleTokenContainer : public TokenSource
83 inline SingleTokenContainer(const Tokenizer::Token &token,
84 const YYLTYPE &location);
86 virtual Tokenizer::Token nextToken(YYLTYPE *const sourceLocator);
88 const Tokenizer::Token m_token;
89 const YYLTYPE m_location;
93 SingleTokenContainer::SingleTokenContainer(const Tokenizer::Token &token,
94 const YYLTYPE &location) : m_token(token)
95 , m_location(location)
96 , m_hasDelivered(false)
101 * @short Tokenizes XSL-T 2.0 documents.
103 * XSLTTokenizer takes in its constructor a pointer to a QIODevice which is
104 * supposed to contain an XSL-T document. XSLTTokenizer then rewrites that
105 * document into XQuery tokens delivered via nextToken(), which the regular
106 * XQuery parser then reads. Hence, the XSL-T language is rewritten into
107 * XQuery code, slightly extended to handle the featuress specific to
110 * @author Frans Englich <frans.englich@nokia.com>
112 class XSLTTokenizer : public Tokenizer
113 , private MaintainingReader<XSLTTokenLookup>
117 * XSLTTokenizer do not own @p queryDevice.
119 XSLTTokenizer(QIODevice *const queryDevice,
120 const QUrl &location,
121 const ReportContext::Ptr &context,
122 const NamePool::Ptr &np);
124 virtual Token nextToken(YYLTYPE *const sourceLocator);
127 * For XSLT we don't need this mechanism, so we do nothing.
129 virtual int commenceScanOnly();
132 * For XSLT we don't need this mechanism, so we do nothing.
134 virtual void resumeTokenizationFrom(const int position);
136 virtual void setParserContext(const ParserContext::Ptr &parseInfo);
138 virtual QUrl documentURI() const
144 virtual bool isAnyAttributeAllowed() const;
147 inline void validateElement() const;
149 YYLTYPE currentSourceLocator() const;
153 OutsideDocumentElement,
154 InsideStylesheetModule,
155 InsideSequenceConstructor
168 void queueNamespaceDeclarations(TokenSource::Queue *const ts,
169 QStack<Token> *const target,
170 const bool isDeclaration = false);
172 inline void queueToken(const Token &token,
173 TokenSource::Queue *const ts);
174 void queueEmptySequence(TokenSource::Queue *const to);
175 void queueSequenceType(const QString &expr);
177 * If @p emptynessAllowed is @c true, the @c select attribute may
178 * be empty while there also is no sequence constructor.
180 void queueSimpleContentConstructor(const ReportContext::ErrorCode code,
181 const bool emptynessAllowed,
182 TokenSource::Queue *const to,
183 const bool selectOnlyFirst = false);
185 * Tokenizes and queues @p expr as if it was an attribute value
188 void queueAVT(const QString &expr,
189 TokenSource::Queue *const to);
191 void hasWrittenExpression(bool &beacon);
192 void commencingExpression(bool &hasWrittenExpression,
193 TokenSource::Queue *const to);
195 void outsideDocumentElement();
196 void insideChoose(TokenSource::Queue *const to);
197 void insideFunction();
199 bool attributeYesNo(const QString &localName) const;
202 * Scans/skips @c xsl:fallback elements only. This is the case of the
203 * children of @c xsl:sequence, for instance.
205 void parseFallbacksOnly();
208 * Returns true if the current element is either @c stylesheet
209 * or the synonym @c transform.
211 * This function assumes that m_reader is positioned at an element
212 * and that the namespace is XSL-T.
214 bool isStylesheetElement() const;
217 * Returns true if the current element name is @p name.
219 * It is assumed that the namespace is XSL-T and that the current
220 * state in m_reader is either QXmlStreamReader::StartElement or
221 * QXmlStreamReader::EndElement.
223 bool isElement(const NodeName &name) const;
226 * Queues a text constructor for @p chars, if @p chars is
229 void queueTextConstructor(QString &chars,
230 bool &hasWrittenExpression,
231 TokenSource::Queue *const to);
235 * @see <a href="http://www.w3.org/TR/xslt20/#stylesheet-structure">XSL
236 * Transformations (XSLT) Version 2, 3.6 Stylesheet Element</a>
238 void insideStylesheetModule();
239 void insideTemplate();
242 * Takes @p expr for an XPath expression, and pushes the necessary
243 * things for having it delivered as a stream of token, appropriate
244 * for Effective Boolean Value parsing.
246 void queueExpression(const QString &expr,
247 TokenSource::Queue *const to,
248 const bool wrapWithParantheses = true);
250 void skipBodyOfParam(const ReportContext::ErrorCode code);
252 void queueParams(const NodeName parentName,
253 TokenSource::Queue *const to);
256 * Used for @c xsl:apply-templates and @c xsl:call-templates.
258 void queueWithParams(const NodeName parentName,
259 TokenSource::Queue *const to,
260 const bool initialAdvance = true);
263 * Queues an @c xsl:variable declaration. If @p isInstruction is @c
264 * true, it is assumed to be a an instruction, otherwise a top-level
265 * declaration element.
267 void queueVariableDeclaration(const VariableType variableType,
268 TokenSource::Queue *const to);
271 * Skips the current sub-tree.
273 * If text nodes that aren't strippable whitespace, or elements are
274 * encountered, @c true is returned, otherwise @c false.
276 * If @p exitOnContent is @c true, this function exits immediately
277 * if content is encountered for which it would return @c false.
279 bool skipSubTree(const bool exitOnContent = false);
282 * Queues the necessary tokens for the expression that is either
283 * supplied using a @c select attribute or a sequence constructor,
284 * while doing the necessary error handling for ensuring they are
285 * mutually exclusive.
287 * It is assumed that the current state of m_reader is
288 * QXmlStreamReader::StartElement, or that the attributes for the
289 * element is supplied through @p atts. This function advances m_reader
290 * up until the corresponding QXmlStreamReader::EndElement.
292 * If @p emptynessAllowed is @c false, the element must either have a
293 * sequence constructor or a @c select attribute. If @c true, both may
296 * Returns @c true if the queued expression was supplied through the
297 * @c select attribute otherwise @c false.
299 bool queueSelectOrSequenceConstructor(const ReportContext::ErrorCode code,
300 const bool emptynessAllowed,
301 TokenSource::Queue *const to,
302 const QXmlStreamAttributes *const atts = 0,
303 const bool queueEmptyOnEmpty = true);
306 * If @p initialAdvance is @c true, insideSequenceConstructor() will
307 * advance m_reader, otherwise it won't. Not doing so is useful
308 * when the caller is already inside a sequence constructor.
310 * Returns @c true if a sequence constructor was found and queued.
311 * Returns @c false if none was found, and the empty sequence was
314 bool insideSequenceConstructor(TokenSource::Queue *const to,
315 const bool initialAdvance = true,
316 const bool queueEmptyOnEmpty = true);
318 bool insideSequenceConstructor(TokenSource::Queue *const to,
319 QStack<Token> &queueOnExit,
320 const bool initialAdvance = true,
321 const bool queueEmptyOnEmpty = true);
323 void insideAttributeSet();
324 void pushState(const State nextState);
328 * @short Handles @c xml:space and standard attributes.
330 * If @p isXSLTElement is @c true, the current element is an XSL-T
331 * element, as opposed to a Literal Result Element.
333 * handleStandardAttributes() must be called before validateElement(),
334 * because the former determines the version in use, and
335 * validateElement() depends on that.
337 * The core of this function can't be run many times because it pushes
338 * whitespace handling onto m_stripWhitespace.
339 * m_hasHandledStandardAttributes protects helping against this.
341 * @see validateElement()
342 * @see <a href="http://www.w3.org/TR/xslt20/#standard-attributes">XSL
343 * Transformations (XSLT) Version 2.0, 3.5 Standard Attributes</a>
345 void handleStandardAttributes(const bool isXSLTElement);
348 * @short Sends the tokens in @p source to @p destination.
350 inline void queueOnExit(QStack<Token> &source,
351 TokenSource::Queue *const destination);
354 * Handles the @c type and @c validation attribute on instructions and
355 * literal result elements.
357 * @p isLRE should be true if the current element is not in the XSL-T
358 * namespace, that is if it's a Literal Result Element.
360 * @see <a href="http://www.w3.org/TR/xslt20/#validation">XSL
361 * Transformations (XSLT) Version 2.0, 19.2 Validation</a>
363 void handleValidationAttributes(const bool isLRE) const;
365 void unexpectedContent(const ReportContext::ErrorCode code = ReportContext::XTSE0010) const;
367 void checkForParseError() const;
369 inline void startStorageOfCurrent(TokenSource::Queue *const to);
370 inline void endStorageOfCurrent(TokenSource::Queue *const to);
373 * Checks that @p attribute has a value in accordance with what
374 * is allowed and supported.
376 void handleXSLTVersion(TokenSource::Queue *const to,
377 QStack<Token> *const queueOnExit,
378 const bool isXSLTElement,
379 const QXmlStreamAttributes *atts = 0,
380 const bool generateCode = true,
381 const bool setGlobalVersion = false);
384 * @short Generates code for reflecting @c xml:base attributes.
386 void handleXMLBase(TokenSource::Queue *const to,
387 QStack<Token> *const queueOnExit,
388 const bool isInstruction = true,
389 const QXmlStreamAttributes *atts = 0);
392 * Concatenates text nodes, ignores comments and processing
393 * instructions, and raises errors on everything else.
395 * Hence, similar to QXmlStreamReader::readElementText(), except
396 * for error handling.
398 QString readElementText();
401 * Tokenizes and validate xsl:sort statements, if any, until
402 * other content is encountered. The produced tokens are returned
405 * If @p oneSortRequired, at least one @c sort element must appear,
406 * otherwise an error is raised.
408 * If @p speciallyTreatWhitespace whitespace will be treated as if it
409 * was one of the elements mentioned in step 4 in section 4.2 Stripping
410 * Whitespace from the Stylesheet.
412 void queueSorting(const bool oneSortRequired,
413 TokenSource::Queue *const to,
414 const bool speciallyTreatWhitespace = false);
416 static ElementDescription<XSLTTokenLookup>::Hash createElementDescriptions();
417 static QHash<QString, int> createValidationAlternatives();
418 static QSet<NodeName> createStandardAttributes();
421 * Reads the attribute by name @p attributeName, and returns @c true if
422 * its value is @p isTrue, @c false if it is @p isFalse, and raise an
425 bool readToggleAttribute(const QString &attributeName,
426 const QString &isTrue,
427 const QString &isFalse,
428 const QXmlStreamAttributes *const atts = 0) const;
430 int readAlternativeAttribute(const QHash<QString, int> &alternatives,
431 const QXmlStreamAttribute &attr) const;
434 * Returns @c true if the current text node can be skipped without
435 * it leading to a validation error, with respect to whitespace.
437 inline bool whitespaceToSkip() const;
439 const QUrl m_location;
440 const NamePool::Ptr m_namePool;
441 QStack<State> m_state;
442 TokenSource::Queue m_tokenSource;
452 * Whether we're processing in Forwards-Compatible or
453 * Backwards-Compatible mode.
455 * This is set by handleStandardAttributes().
457 * ParserContext have similar information in
458 * ParserContext::isBackwardsCompat. A big distinction is that both the
459 * tokenizer and the parser buffer tokens and have positions disjoint
460 * to each other. E.g, the state the parser has when reducing into
461 * non-terminals, is different from the tokenizer's.
463 QStack<ProcessMode> m_processingMode;
466 * Returns @c true if the current state in m_reader is in the XSLT
467 * namespace. It is assumed that the current state is an element.
469 inline bool isXSLT() const;
471 const QHash<QString, int> m_validationAlternatives;
473 ParserContext::Ptr m_parseInfo;