source: trunk/src/xmlpatterns/parser/querytransformparser.ypp@ 604

Last change on this file since 604 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 189.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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%{
53/****************************************************************************
54**
55** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
56** All rights reserved.
57** Contact: Nokia Corporation ([email protected])
58**
59** This file is part of the QtXmlPatterns module of the Qt Toolkit.
60**
61** $QT_BEGIN_LICENSE:LGPL$
62** Commercial Usage
63** Licensees holding valid Qt Commercial licenses may use this file in
64** accordance with the Qt Commercial License Agreement provided with the
65** Software or, alternatively, in accordance with the terms contained in
66** a written agreement between you and Nokia.
67**
68** GNU Lesser General Public License Usage
69** Alternatively, this file may be used under the terms of the GNU Lesser
70** General Public License version 2.1 as published by the Free Software
71** Foundation and appearing in the file LICENSE.LGPL included in the
72** packaging of this file. Please review the following information to
73** ensure the GNU Lesser General Public License version 2.1 requirements
74** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
75**
76** In addition, as a special exception, Nokia gives you certain additional
77** rights. These rights are described in the Nokia Qt LGPL Exception
78** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
79**
80** GNU General Public License Usage
81** Alternatively, this file may be used under the terms of the GNU
82** General Public License version 3.0 as published by the Free Software
83** Foundation and appearing in the file LICENSE.GPL included in the
84** packaging of this file. Please review the following information to
85** ensure the GNU General Public License version 3.0 requirements will be
86** met: http://www.gnu.org/copyleft/gpl.html.
87**
88** If you have questions regarding the use of this file, please contact
89** Nokia at [email protected].
90** $QT_END_LICENSE$
91**
92****************************************************************************/
93
94//
95// W A R N I N G
96// -------------
97//
98// This file is not part of the Qt API. It exists purely as an
99// implementation detail. This header file may change from version to
100// version without notice, or even be removed.
101//
102// We mean it.
103
104#include <limits>
105
106#include <QUrl>
107
108#include "qabstractfloat_p.h"
109#include "qandexpression_p.h"
110#include "qanyuri_p.h"
111#include "qapplytemplate_p.h"
112#include "qargumentreference_p.h"
113#include "qarithmeticexpression_p.h"
114#include "qatomicstring_p.h"
115#include "qattributeconstructor_p.h"
116#include "qattributenamevalidator_p.h"
117#include "qaxisstep_p.h"
118#include "qbuiltintypes_p.h"
119#include "qcalltemplate_p.h"
120#include "qcastableas_p.h"
121#include "qcastas_p.h"
122#include "qcombinenodes_p.h"
123#include "qcommentconstructor_p.h"
124#include "qcommonnamespaces_p.h"
125#include "qcommonsequencetypes_p.h"
126#include "qcommonvalues_p.h"
127#include "qcomputednamespaceconstructor_p.h"
128#include "qcontextitem_p.h"
129#include "qcopyof_p.h"
130#include "qcurrentitemstore_p.h"
131#include "qdebug_p.h"
132#include "qdelegatingnamespaceresolver_p.h"
133#include "qdocumentconstructor_p.h"
134#include "qelementconstructor_p.h"
135#include "qemptysequence_p.h"
136#include "qemptysequencetype_p.h"
137#include "qevaluationcache_p.h"
138#include "qexpressionfactory_p.h"
139#include "qexpressionsequence_p.h"
140#include "qexpressionvariablereference_p.h"
141#include "qexternalvariablereference_p.h"
142#include "qforclause_p.h"
143#include "qfunctioncall_p.h"
144#include "qfunctionfactory_p.h"
145#include "qfunctionsignature_p.h"
146#include "qgeneralcomparison_p.h"
147#include "qgenericpredicate_p.h"
148#include "qgenericsequencetype_p.h"
149#include "qifthenclause_p.h"
150#include "qinstanceof_p.h"
151#include "qletclause_p.h"
152#include "qliteral_p.h"
153#include "qlocalnametest_p.h"
154#include "qnamespaceconstructor_p.h"
155#include "qnamespacenametest_p.h"
156#include "qncnameconstructor_p.h"
157#include "qnodecomparison_p.h"
158#include "qnodesort_p.h"
159#include "qorderby_p.h"
160#include "qorexpression_p.h"
161#include "qparsercontext_p.h"
162#include "qpath_p.h"
163#include "qpatternistlocale_p.h"
164#include "qpositionalvariablereference_p.h"
165#include "qprocessinginstructionconstructor_p.h"
166#include "qqnameconstructor_p.h"
167#include "qqnametest_p.h"
168#include "qqnamevalue_p.h"
169#include "qquantifiedexpression_p.h"
170#include "qrangeexpression_p.h"
171#include "qrangevariablereference_p.h"
172#include "qreturnorderby_p.h"
173#include "qschemanumeric_p.h"
174#include "qschematypefactory_p.h"
175#include "qsimplecontentconstructor_p.h"
176#include "qstaticbaseuristore_p.h"
177#include "qstaticcompatibilitystore_p.h"
178#include "qtemplateparameterreference_p.h"
179#include "qtemplate_p.h"
180#include "qtextnodeconstructor_p.h"
181#include "qtokenizer_p.h"
182#include "qtreatas_p.h"
183#include "qtypechecker_p.h"
184#include "qunaryexpression_p.h"
185#include "qunresolvedvariablereference_p.h"
186#include "quserfunctioncallsite_p.h"
187#include "qvaluecomparison_p.h"
188#include "qxpathhelper_p.h"
189#include "qxsltsimplecontentconstructor_p.h"
190
191/*
192 * The cpp generated with bison 2.1 wants to
193 * redeclare the C-like prototypes of 'malloc' and 'free', so we avoid that.
194 */
195#define YYMALLOC malloc
196#define YYFREE free
197
198QT_BEGIN_NAMESPACE
199
200/* Due to Qt's QT_BEGIN_NAMESPACE magic, we can't use `using namespace', for some
201 * undocumented reason. */
202namespace QPatternist
203{
204
205/**
206 * "Macro that you define with #define in the Bison declarations
207 * section to request verbose, specific error message strings when
208 * yyerror is called."
209 */
210#define YYERROR_VERBOSE 1
211
212#undef YYLTYPE_IS_TRIVIAL
213#define YYLTYPE_IS_TRIVIAL 0
214
215/* Suppresses `warning: "YYENABLE_NLS" is not defined`
216 * @c YYENABLE_NLS enables Bison internationalization, and we don't
217 * use that, so disable it. See the Bison Manual, section 4.5 Parser Internationalization.
218 */
219#define YYENABLE_NLS 0
220
221static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator,
222 const ParserContext *const parseInfo)
223{
224 return QSourceLocation(parseInfo->tokenizer->queryURI(),
225 sourceLocator.first_line,
226 sourceLocator.first_column);
227}
228
229/**
230 * @internal
231 * @relates QXmlQuery
232 */
233typedef QFlags<QXmlQuery::QueryLanguage> QueryLanguages;
234
235/**
236 * @short Flags invalid expressions and declarations in the currently
237 * parsed language.
238 *
239 * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0, and
240 * XPath 2.0 inside XSL-T, and field and selector patterns in W3C XML Schema's
241 * identity constraints, it is the union of all the constructs in these
242 * languages. However, when dealing with each language individually, we
243 * regularly need to disallow some expressions, such as direct element
244 * constructors when parsing XSL-T, or the typeswitch when parsing XPath.
245 *
246 * This is further complicated by that XSLTTokenizer sometimes generates code
247 * which is allowed in XQuery but not in XPath. For that reason the token
248 * INTERNAL is sometimes generated, which signals that an expression, for
249 * instance the @c let clause, should not be flagged as an error, because it's
250 * used for internal purposes.
251 *
252 * Hence, this function is called from each expression and declaration with @p
253 * allowedLanguages stating what languages it is allowed in.
254 *
255 * If @p isInternal is @c true, no error is raised. Otherwise, if the current
256 * language is not in @p allowedLanguages, an error is raised.
257 */
258static void allowedIn(const QueryLanguages allowedLanguages,
259 const ParserContext *const parseInfo,
260 const YYLTYPE &sourceLocator,
261 const bool isInternal = false)
262{
263 /* We treat XPath 2.0 as a subset of XSL-T 2.0, so if XPath 2.0 is allowed
264 * and XSL-T is the language, it's ok. */
265 if(!isInternal &&
266 (!allowedLanguages.testFlag(parseInfo->languageAccent) && !(allowedLanguages.testFlag(QXmlQuery::XPath20) && parseInfo->languageAccent == QXmlQuery::XSLT20)))
267 {
268
269 QString langName;
270
271 switch(parseInfo->languageAccent)
272 {
273 case QXmlQuery::XPath20:
274 langName = QLatin1String("XPath 2.0");
275 break;
276 case QXmlQuery::XSLT20:
277 langName = QLatin1String("XSL-T 2.0");
278 break;
279 case QXmlQuery::XQuery10:
280 langName = QLatin1String("XQuery 1.0");
281 break;
282 case QXmlQuery::XmlSchema11IdentityConstraintSelector:
283 langName = QtXmlPatterns::tr("W3C XML Schema identity constraint selector");
284 break;
285 case QXmlQuery::XmlSchema11IdentityConstraintField:
286 langName = QtXmlPatterns::tr("W3C XML Schema identity constraint field");
287 break;
288 }
289
290 parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered "
291 "which is disallowed in the current language(%1).").arg(langName),
292 ReportContext::XPST0003,
293 fromYYLTYPE(sourceLocator, parseInfo));
294
295 }
296}
297
298static inline bool isVariableReference(const Expression::ID id)
299{
300 return id == Expression::IDExpressionVariableReference
301 || id == Expression::IDRangeVariableReference
302 || id == Expression::IDArgumentReference;
303}
304
305class ReflectYYLTYPE : public SourceLocationReflection
306{
307public:
308 inline ReflectYYLTYPE(const YYLTYPE &sourceLocator,
309 const ParserContext *const pi) : m_sl(sourceLocator)
310 , m_parseInfo(pi)
311 {
312 }
313
314 virtual const SourceLocationReflection *actualReflection() const
315 {
316 return this;
317 }
318
319 virtual QSourceLocation sourceLocation() const
320 {
321 return fromYYLTYPE(m_sl, m_parseInfo);
322 }
323
324 virtual QString description() const
325 {
326 Q_ASSERT(false);
327 return QString();
328 }
329
330private:
331 const YYLTYPE &m_sl;
332 const ParserContext *const m_parseInfo;
333};
334
335/**
336 * @short Centralizes a translation string for the purpose of increasing consistency.
337 */
338static inline QString unknownType()
339{
340 return QtXmlPatterns::tr("%1 is an unknown schema type.");
341}
342
343static inline Expression::Ptr create(Expression *const expr,
344 const YYLTYPE &sourceLocator,
345 const ParserContext *const parseInfo)
346{
347 parseInfo->staticContext->addLocation(expr, fromYYLTYPE(sourceLocator, parseInfo));
348 return Expression::Ptr(expr);
349}
350
351static inline Template::Ptr create(Template *const expr,
352 const YYLTYPE &sourceLocator,
353 const ParserContext *const parseInfo)
354{
355 parseInfo->staticContext->addLocation(expr, fromYYLTYPE(sourceLocator, parseInfo));
356 return Template::Ptr(expr);
357}
358
359static inline Expression::Ptr create(const Expression::Ptr &expr,
360 const YYLTYPE &sourceLocator,
361 const ParserContext *const parseInfo)
362{
363 parseInfo->staticContext->addLocation(expr.data(), fromYYLTYPE(sourceLocator, parseInfo));
364 return expr;
365}
366
367static Expression::Ptr createSimpleContent(const Expression::Ptr &source,
368 const YYLTYPE &sourceLocator,
369 const ParserContext *const parseInfo)
370{
371 return create(parseInfo->isXSLT() ? new XSLTSimpleContentConstructor(source) : new SimpleContentConstructor(source),
372 sourceLocator,
373 parseInfo);
374}
375
376static void loadPattern(const Expression::Ptr &matchPattern,
377 TemplatePattern::Vector &ourPatterns,
378 const TemplatePattern::ID id,
379 const PatternPriority priority,
380 const Template::Ptr &temp)
381{
382 Q_ASSERT(temp);
383
384 const PatternPriority effectivePriority = qIsNaN(priority) ? matchPattern->patternPriority() : priority;
385
386 ourPatterns.append(TemplatePattern::Ptr(new TemplatePattern(matchPattern, effectivePriority, id, temp)));
387}
388
389static Expression::Ptr typeCheckTemplateBody(const Expression::Ptr &body,
390 const SequenceType::Ptr &reqType,
391 const ParserContext *const parseInfo)
392{
393 return TypeChecker::applyFunctionConversion(body, reqType,
394 parseInfo->staticContext,
395 ReportContext::XTTE0505,
396 TypeChecker::Options(TypeChecker::AutomaticallyConvert | TypeChecker::GeneratePromotion));
397}
398
399static void registerNamedTemplate(const QXmlName &name,
400 const Expression::Ptr &body,
401 ParserContext *const parseInfo,
402 const YYLTYPE &sourceLocator,
403 const Template::Ptr &temp)
404{
405 Template::Ptr &e = parseInfo->namedTemplates[name];
406
407 if(e)
408 {
409 parseInfo->staticContext->error(QtXmlPatterns::tr("A template by name %1 "
410 "has already been declared.")
411 .arg(formatKeyword(parseInfo->staticContext->namePool(),
412 name)),
413 ReportContext::XTSE0660,
414 fromYYLTYPE(sourceLocator, parseInfo));
415 }
416 else
417 {
418 e = temp;
419 e->body = body;
420 }
421}
422
423/**
424 * @short Centralizes code for creating numeric literals.
425 */
426template<typename TNumberClass>
427Expression::Ptr createNumericLiteral(const QString &in,
428 const YYLTYPE &sl,
429 const ParserContext *const parseInfo)
430{
431 const Item num(TNumberClass::fromLexical(in));
432
433 if(num.template as<AtomicValue>()->hasError())
434 {
435 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not a valid numeric literal.")
436 .arg(formatData(in)),
437 ReportContext::XPST0003, fromYYLTYPE(sl, parseInfo));
438 return Expression::Ptr(); /* Avoid compiler warning. */
439 }
440 else
441 return create(new Literal(num), sl, parseInfo);
442}
443
444/**
445 * @short The generated Bison parser calls this function when there is a parse error.
446 *
447 * It is not called, nor should be, for logical errors(which the Bison not know about). For those,
448 * ReportContext::error() is called.
449 */
450static int XPatherror(YYLTYPE *sourceLocator, const ParserContext *const parseInfo, const char *const msg)
451{
452 Q_UNUSED(sourceLocator);
453 Q_ASSERT(parseInfo);
454
455 parseInfo->staticContext->error(escape(QLatin1String(msg)), ReportContext::XPST0003, fromYYLTYPE(*sourceLocator, parseInfo));
456 return 1;
457}
458
459/**
460 * When we want to connect the OrderBy and ReturnOrderBy, it might be that we have other expressions, such
461 * as @c where and @c let inbetween. We need to continue through them. This function does that.
462 */
463static ReturnOrderBy *locateReturnClause(const Expression::Ptr &expr)
464{
465 Q_ASSERT(expr);
466
467 const Expression::ID id = expr->id();
468 if(id == Expression::IDLetClause || id == Expression::IDIfThenClause || id == Expression::IDForClause)
469 return locateReturnClause(expr->operands()[1]);
470 else if(id == Expression::IDReturnOrderBy)
471 return expr->as<ReturnOrderBy>();
472 else
473 return 0;
474}
475
476static inline bool isPredicate(const Expression::ID id)
477{
478 return id == Expression::IDGenericPredicate ||
479 id == Expression::IDFirstItemPredicate;
480}
481
482/**
483 * Assumes expr is an AxisStep wrapped in some kind of predicates or paths. Filters
484 * through the predicates and returns the AxisStep.
485 */
486static Expression::Ptr findAxisStep(const Expression::Ptr &expr,
487 const bool throughStructures = true)
488{
489 Q_ASSERT(expr);
490
491 if(!throughStructures)
492 return expr;
493
494 Expression *candidate = expr.data();
495 Expression::ID id = candidate->id();
496
497 while(isPredicate(id) || id == Expression::IDPath)
498 {
499 const Expression::List &children = candidate->operands();
500 if(children.isEmpty())
501 return Expression::Ptr();
502 else
503 {
504 candidate = children.first().data();
505 id = candidate->id();
506 }
507 }
508
509 if(id == Expression::IDEmptySequence)
510 return Expression::Ptr();
511 else
512 {
513 Q_ASSERT(candidate->is(Expression::IDAxisStep));
514 return Expression::Ptr(candidate);
515 }
516}
517
518static void changeToTopAxis(const Expression::Ptr &op)
519{
520 /* This axis must have been written away by now. */
521 Q_ASSERT(op->as<AxisStep>()->axis() != QXmlNodeModelIndex::AxisChild);
522
523 if(op->as<AxisStep>()->axis() != QXmlNodeModelIndex::AxisSelf)
524 op->as<AxisStep>()->setAxis(QXmlNodeModelIndex::AxisAttributeOrTop);
525}
526
527/**
528 * @short Writes @p operand1 and @p operand2, two operands in an XSL-T pattern,
529 * into an equivalent XPath expression.
530 *
531 * Essentially, the following rewrite is done:
532 *
533 * <tt>
534 * axis1::test1(a)/axis2::test2(b)
535 * =>
536 * child-or-top::test2(b)[parent::test1(a)]
537 * </tt>
538 *
539 * Section 5.5.3 The Meaning of a Pattern talks about rewrites that are applied to
540 * only the first step in a pattern, but since we're doing rewrites more radically,
541 * its line of reasoning cannot be followed.
542 *
543 * Keep in mind the rewrites that non-terminal PatternStep do.
544 *
545 * @see createIdPatternPath()
546 */
547static inline Expression::Ptr createPatternPath(const Expression::Ptr &operand1,
548 const Expression::Ptr &operand2,
549 const QXmlNodeModelIndex::Axis axis,
550 const YYLTYPE &sl,
551 const ParserContext *const parseInfo)
552{
553 const Expression::Ptr operandL(findAxisStep(operand1, false));
554
555 if(operandL->is(Expression::IDAxisStep))
556 operandL->as<AxisStep>()->setAxis(axis);
557 else
558 findAxisStep(operand1)->as<AxisStep>()->setAxis(axis);
559
560 return create(GenericPredicate::create(operand2, operandL,
561 parseInfo->staticContext, fromYYLTYPE(sl, parseInfo)), sl, parseInfo);
562}
563
564/**
565 * @short Performs the same role as createPatternPath(), but is tailored
566 * for @c fn:key() and @c fn:id().
567 *
568 * @c fn:key() and @c fn:id() can be part of path patterns(only as the first step,
569 * to be precise) and that poses a challenge to rewriting because what
570 * createPatternPath() is not possible to express, since the functions cannot be
571 * node tests. E.g, this rewrite is not possible:
572 *
573 * <tt>
574 * id-or-key/abc
575 * =>
576 * child-or-top::abc[parent::id-or-key]
577 * </tt>
578 *
579 * Our approach is to rewrite like this:
580 *
581 * <tt>
582 * id-or-key/abc
583 * =>
584 * child-or-top::abc[parent::node is id-or-key]
585 * </tt>
586 *
587 * @p operand1 is the call to @c fn:key() or @c fn:id(), @p operand2
588 * the right operand, and @p axis the target axis to rewrite to.
589 *
590 * @see createPatternPath()
591 */
592static inline Expression::Ptr createIdPatternPath(const Expression::Ptr &operand1,
593 const Expression::Ptr &operand2,
594 const QXmlNodeModelIndex::Axis axis,
595 const YYLTYPE &sl,
596 const ParserContext *const parseInfo)
597{
598 const Expression::Ptr operandR(findAxisStep(operand2));
599 Q_ASSERT(operandR);
600 changeToTopAxis(operandR);
601
602 const Expression::Ptr parentStep(create(new AxisStep(axis, BuiltinTypes::node),
603 sl,
604 parseInfo));
605 const Expression::Ptr isComp(create(new NodeComparison(parentStep,
606 QXmlNodeModelIndex::Is,
607 operand1),
608 sl,
609 parseInfo));
610
611 return create(GenericPredicate::create(operandR, isComp,
612 parseInfo->staticContext, fromYYLTYPE(sl, parseInfo)), sl, parseInfo);
613}
614
615/**
616 * @short Centralizes a translation message, for the
617 * purpose of consistency and modularization.
618 */
619static inline QString prologMessage(const char *const msg)
620{
621 Q_ASSERT(msg);
622 return QtXmlPatterns::tr("Only one %1 declaration can occur in the query prolog.").arg(formatKeyword(msg));
623}
624
625/**
626 * @short Resolves against the static base URI and checks that @p collation
627 * is a supported Unicode Collation.
628 *
629 * "If a default collation declaration specifies a collation by a
630 * relative URI, that relative URI is resolved to an absolute
631 * URI using the base URI in the static context."
632 *
633 * @returns the Unicode Collation properly resolved, if @p collation is a valid collation
634 */
635template<const ReportContext::ErrorCode errorCode>
636static QUrl resolveAndCheckCollation(const QString &collation,
637 const ParserContext *const parseInfo,
638 const YYLTYPE &sl)
639{
640 Q_ASSERT(parseInfo);
641 const ReflectYYLTYPE ryy(sl, parseInfo);
642
643 QUrl uri(AnyURI::toQUrl<ReportContext::XQST0046>(collation, parseInfo->staticContext, &ryy));
644
645 if(uri.isRelative())
646 uri = parseInfo->staticContext->baseURI().resolved(uri);
647
648 XPathHelper::checkCollationSupport<errorCode>(uri.toString(), parseInfo->staticContext, &ryy);
649
650 return uri;
651}
652
653/* The Bison generated parser declares macros that aren't used
654 * so suppress the warnings by fake usage of them.
655 *
656 * We do the same for some more defines in the first action. */
657#if defined(YYLSP_NEEDED) \
658 || defined(YYBISON) \
659 || defined(YYBISON_VERSION) \
660 || defined(YYPURE) \
661 || defined(yydebug) \
662 || defined(YYSKELETON_NAME)
663#endif
664
665/**
666 * Wraps @p operand with a CopyOf in case it makes any difference.
667 *
668 * There is no need to wrap the return value in a call to create(), it's
669 * already done.
670 */
671static Expression::Ptr createCopyOf(const Expression::Ptr &operand,
672 const ParserContext *const parseInfo,
673 const YYLTYPE &sl)
674{
675 return create(new CopyOf(operand, parseInfo->inheritNamespacesMode,
676 parseInfo->preserveNamespacesMode), sl, parseInfo);
677}
678
679static Expression::Ptr createCompatStore(const Expression::Ptr &expr,
680 const YYLTYPE &sourceLocator,
681 const ParserContext *const parseInfo)
682{
683 return create(new StaticCompatibilityStore(expr), sourceLocator, parseInfo);
684}
685
686/**
687 * @short Creates an Expression that corresponds to <tt>/</tt>. This is literally
688 * <tt>fn:root(self::node()) treat as document-node()</tt>.
689 */
690static Expression::Ptr createRootExpression(const ParserContext *const parseInfo,
691 const YYLTYPE &sl)
692{
693 Q_ASSERT(parseInfo);
694 const QXmlName name(StandardNamespaces::fn, StandardLocalNames::root);
695
696 Expression::List args;
697 args.append(create(new ContextItem(), sl, parseInfo));
698
699 const ReflectYYLTYPE ryy(sl, parseInfo);
700
701 const Expression::Ptr fnRoot(parseInfo->staticContext->functionSignatures()
702 ->createFunctionCall(name, args, parseInfo->staticContext, &ryy));
703 Q_ASSERT(fnRoot);
704
705 return create(new TreatAs(create(fnRoot, sl, parseInfo), CommonSequenceTypes::ExactlyOneDocumentNode), sl, parseInfo);
706}
707
708static int XPathlex(YYSTYPE *lexVal, YYLTYPE *sourceLocator, const ParserContext *const parseInfo)
709{
710#ifdef Patternist_DEBUG_PARSER
711 /**
712 * "External integer variable set to zero by default. If yydebug
713 * is given a nonzero value, the parser will output information on
714 * input symbols and parser action. See section Debugging Your Parser."
715 */
716# define YYDEBUG 1
717
718 extern int XPathdebug;
719 XPathdebug = 1;
720#endif
721
722 Q_ASSERT(parseInfo);
723
724 const Tokenizer::Token tok(parseInfo->tokenizer->nextToken(sourceLocator));
725
726 (*lexVal).sval = tok.value;
727
728 return static_cast<int>(tok.type);
729}
730
731/**
732 * @short Creates a path expression which contains the step <tt>//</tt> between
733 * @p begin and and @p end.
734 *
735 * <tt>begin//end</tt> is a short form for: <tt>begin/descendant-or-self::node()/end</tt>
736 *
737 * This will be compiled as two-path expression: <tt>(/)/(//.)/step/</tt>
738 */
739static Expression::Ptr createSlashSlashPath(const Expression::Ptr &begin,
740 const Expression::Ptr &end,
741 const YYLTYPE &sourceLocator,
742 const ParserContext *const parseInfo)
743{
744 const Expression::Ptr twoSlash(create(new AxisStep(QXmlNodeModelIndex::AxisDescendantOrSelf, BuiltinTypes::node), sourceLocator, parseInfo));
745 const Expression::Ptr p1(create(new Path(begin, twoSlash), sourceLocator, parseInfo));
746
747 return create(new Path(p1, end), sourceLocator, parseInfo);
748}
749
750/**
751 * @short Creates a call to <tt>fn:concat()</tt> with @p args as the arguments.
752 */
753static inline Expression::Ptr createConcatFN(const ParserContext *const parseInfo,
754 const Expression::List &args,
755 const YYLTYPE &sourceLocator)
756{
757 Q_ASSERT(parseInfo);
758 const QXmlName name(StandardNamespaces::fn, StandardLocalNames::concat);
759 const ReflectYYLTYPE ryy(sourceLocator, parseInfo);
760
761 return create(parseInfo->staticContext->functionSignatures()->createFunctionCall(name, args, parseInfo->staticContext, &ryy),
762 sourceLocator, parseInfo);
763}
764
765static inline Expression::Ptr createDirAttributeValue(const Expression::List &content,
766 const ParserContext *const parseInfo,
767 const YYLTYPE &sourceLocator)
768{
769 if(content.isEmpty())
770 return create(new EmptySequence(), sourceLocator, parseInfo);
771 else if(content.size() == 1)
772 return content.first();
773 else
774 return createConcatFN(parseInfo, content, sourceLocator);
775}
776
777/**
778 * @short Checks for variable initialization circularity.
779 *
780 * "A recursive function that checks for recursion is full of ironies."
781 *
782 * -- The Salsa Master
783 *
784 * Issues an error via @p parseInfo's StaticContext if the initialization
785 * expression @p checkee for the global variable @p var, contains a variable
786 * reference to @p var. That is, if there's a circularity.
787 *
788 * @see <a href="http://www.w3.org/TR/xquery/#ERRXQST0054">XQuery 1.0: An XML
789 * Query Language, err:XQST0054</a>
790 */
791static void checkVariableCircularity(const VariableDeclaration::Ptr &var,
792 const Expression::Ptr &checkee,
793 const VariableDeclaration::Type type,
794 FunctionSignature::List &signList,
795 const ParserContext *const parseInfo)
796{
797 Q_ASSERT(var);
798 Q_ASSERT(checkee);
799 Q_ASSERT(parseInfo);
800
801 const Expression::ID id = checkee->id();
802
803 if(id == Expression::IDExpressionVariableReference)
804 {
805 const ExpressionVariableReference *const ref =
806 static_cast<const ExpressionVariableReference *>(checkee.data());
807
808 if(var->slot == ref->slot() && type == ref->variableDeclaration()->type)
809 {
810 parseInfo->staticContext->error(QtXmlPatterns::tr("The initialization of variable %1 "
811 "depends on itself").arg(formatKeyword(var, parseInfo->staticContext->namePool())),
812 parseInfo->isXSLT() ? ReportContext::XTDE0640 : ReportContext::XQST0054, ref);
813 return;
814 }
815 else
816 {
817 /* If the variable we're checking is below another variable, it can be a recursive
818 * dependency through functions, so we need to check variable references too. */
819 checkVariableCircularity(var, ref->sourceExpression(), type, signList, parseInfo);
820 return;
821 }
822 }
823 else if(id == Expression::IDUserFunctionCallsite)
824 {
825 const UserFunctionCallsite::Ptr callsite(checkee);
826 const FunctionSignature::Ptr sign(callsite->callTargetDescription());
827 const FunctionSignature::List::const_iterator end(signList.constEnd());
828 FunctionSignature::List::const_iterator it(signList.constBegin());
829 bool noMatch = true;
830
831 for(; it != end; ++it)
832 {
833 if(*it == sign)
834 {
835 /* The variable we're checking is depending on a function that's recursive. The
836 * user has written a weird query, in other words. Since it's the second time
837 * we've encountered a callsite, we now skip it. */
838 noMatch = false;
839 break;
840 }
841 }
842
843 if(noMatch)
844 {
845 signList.append(sign);
846 /* Check the body of the function being called. */
847 checkVariableCircularity(var, callsite->body(), type, signList, parseInfo);
848 }
849 /* Continue with the operands, such that we also check the arguments of the callsite. */
850 }
851 else if(id == Expression::IDUnresolvedVariableReference)
852 {
853 /* We're called before it has rewritten itself. */
854 checkVariableCircularity(var, checkee->as<UnresolvedVariableReference>()->replacement(), type, signList, parseInfo);
855 }
856
857 /* Check the operands. */
858 const Expression::List ops(checkee->operands());
859 if(ops.isEmpty())
860 return;
861
862 const Expression::List::const_iterator end(ops.constEnd());
863 Expression::List::const_iterator it(ops.constBegin());
864
865 for(; it != end; ++it)
866 checkVariableCircularity(var, *it, type, signList, parseInfo);
867}
868
869static void variableUnavailable(const QXmlName &variableName,
870 const ParserContext *const parseInfo,
871 const YYLTYPE &location)
872{
873 parseInfo->staticContext->error(QtXmlPatterns::tr("No variable with name %1 exists")
874 .arg(formatKeyword(parseInfo->staticContext->namePool(), variableName)),
875 ReportContext::XPST0008, fromYYLTYPE(location, parseInfo));
876}
877
878/**
879 * The Cardinality in a TypeDeclaration for a variable in a quantification has no effect,
880 * and this function ensures this by changing @p type to Cardinality Cardinality::zeroOrMore().
881 *
882 * @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=3305">Bugzilla Bug 3305
883 * Cardinality + on range variables</a>
884 * @see ParserContext::finalizePushedVariable()
885 */
886static inline SequenceType::Ptr quantificationType(const SequenceType::Ptr &type)
887{
888 Q_ASSERT(type);
889 return makeGenericSequenceType(type->itemType(), Cardinality::zeroOrMore());
890}
891
892/**
893 * @p seqType and @p expr may be @c null.
894 */
895static Expression::Ptr pushVariable(const QXmlName name,
896 const SequenceType::Ptr &seqType,
897 const Expression::Ptr &expr,
898 const VariableDeclaration::Type type,
899 const YYLTYPE &sourceLocator,
900 ParserContext *const parseInfo,
901 const bool checkSource = true)
902{
903 Q_ASSERT(!name.isNull());
904 Q_ASSERT(parseInfo);
905
906 /* -2 will cause Q_ASSERTs to trigger if it isn't changed. */
907 VariableSlotID slot = -2;
908
909 switch(type)
910 {
911 case VariableDeclaration::FunctionArgument:
912 /* Fallthrough. */
913 case VariableDeclaration::ExpressionVariable:
914 {
915 slot = parseInfo->allocateExpressionSlot();
916 break;
917 }
918 case VariableDeclaration::GlobalVariable:
919 {
920 slot = parseInfo->allocateGlobalVariableSlot();
921 break;
922 }
923 case VariableDeclaration::RangeVariable:
924 {
925 slot = parseInfo->staticContext->allocateRangeSlot();
926 break;
927 }
928 case VariableDeclaration::PositionalVariable:
929 {
930 slot = parseInfo->allocatePositionalSlot();
931 break;
932 }
933 case VariableDeclaration::TemplateParameter:
934 /* Fallthrough. We do nothing, template parameters
935 * doesn't use context slots at all, they're hashed
936 * on the name. */
937 case VariableDeclaration::ExternalVariable:
938 /* We do nothing, external variables doesn't use
939 *context slots/stack frames at all. */
940 ;
941 }
942
943 const VariableDeclaration::Ptr var(new VariableDeclaration(name, slot, type, seqType));
944
945 Expression::Ptr checked;
946
947 if(checkSource && seqType)
948 {
949 if(expr)
950 {
951 /* We only want to add conversion for function arguments, and variables
952 * if we're XSL-T.
953 *
954 * We unconditionally skip TypeChecker::CheckFocus because the StaticContext we
955 * pass hasn't set up the focus yet, since that's the parent's responsibility. */
956 const TypeChecker::Options options(( type == VariableDeclaration::FunctionArgument
957 || type == VariableDeclaration::TemplateParameter
958 || parseInfo->isXSLT())
959 ? TypeChecker::AutomaticallyConvert : TypeChecker::Options());
960
961 checked = TypeChecker::applyFunctionConversion(expr, seqType, parseInfo->staticContext,
962 parseInfo->isXSLT() ? ReportContext::XTTE0570 : ReportContext::XPTY0004,
963 options);
964 }
965 }
966 else
967 checked = expr;
968
969 /* Add an evaluation cache for all expression variables. No EvaluationCache is needed for
970 * positional variables because in the end they are calls to Iterator::position(). Similarly,
971 * no need to cache range variables either because they are calls to DynamicContext::rangeVariable().
972 *
973 * We don't do it for function arguments because the Expression being cached depends -- it depends
974 * on the callsite. UserFunctionCallsite is responsible for the evaluation caches in that case.
975 *
976 * In some cases the EvaluationCache instance isn't necessary, but in those cases EvaluationCache
977 * optimizes itself away. */
978 if(type == VariableDeclaration::ExpressionVariable)
979 checked = create(new EvaluationCache<false>(checked, var, parseInfo->allocateCacheSlot()), sourceLocator, parseInfo);
980 else if(type == VariableDeclaration::GlobalVariable)
981 checked = create(new EvaluationCache<true>(checked, var, parseInfo->allocateCacheSlot()), sourceLocator, parseInfo);
982
983 var->setExpression(checked);
984
985 parseInfo->variables.push(var);
986 return checked;
987}
988
989static inline VariableDeclaration::Ptr variableByName(const QXmlName name,
990 const ParserContext *const parseInfo)
991{
992 Q_ASSERT(!name.isNull());
993 Q_ASSERT(parseInfo);
994
995 /* We walk the list backwards. */
996 const VariableDeclaration::Stack::const_iterator start(parseInfo->variables.constBegin());
997 VariableDeclaration::Stack::const_iterator it(parseInfo->variables.constEnd());
998
999 while(it != start)
1000 {
1001 --it;
1002 Q_ASSERT(*it);
1003 if((*it)->name == name)
1004 return *it;
1005 }
1006
1007 return VariableDeclaration::Ptr();
1008}
1009
1010static Expression::Ptr resolveVariable(const QXmlName &name,
1011 const YYLTYPE &sourceLocator,
1012 ParserContext *const parseInfo,
1013 const bool raiseErrorOnUnavailability)
1014{
1015 const VariableDeclaration::Ptr var(variableByName(name, parseInfo));
1016 Expression::Ptr retval;
1017
1018 if(var && var->type != VariableDeclaration::ExternalVariable)
1019 {
1020 switch(var->type)
1021 {
1022 case VariableDeclaration::RangeVariable:
1023 {
1024 retval = create(new RangeVariableReference(var->expression(), var->slot), sourceLocator, parseInfo);
1025 break;
1026 }
1027 case VariableDeclaration::GlobalVariable:
1028 /* Fallthrough. From the perspective of an ExpressionVariableReference, it can't tell
1029 * a difference between a global and a local expression variable. However, the cache
1030 * mechanism must. */
1031 case VariableDeclaration::ExpressionVariable:
1032 {
1033 retval = create(new ExpressionVariableReference(var->slot, var), sourceLocator, parseInfo);
1034 break;
1035 }
1036 case VariableDeclaration::FunctionArgument:
1037 {
1038 retval = create(new ArgumentReference(var->sequenceType, var->slot), sourceLocator, parseInfo);
1039 break;
1040 }
1041 case VariableDeclaration::PositionalVariable:
1042 {
1043 retval = create(new PositionalVariableReference(var->slot), sourceLocator, parseInfo);
1044 break;
1045 }
1046 case VariableDeclaration::TemplateParameter:
1047 {
1048 retval = create(new TemplateParameterReference(var), sourceLocator, parseInfo);
1049 break;
1050 }
1051 case VariableDeclaration::ExternalVariable:
1052 /* This code path will never be hit, but the case
1053 * label silences a warning. See above. */
1054 ;
1055 }
1056 Q_ASSERT(retval);
1057 var->references.append(retval);
1058 }
1059 else
1060 {
1061 /* Let's see if your external variable loader can provide us with one. */
1062 const SequenceType::Ptr varType(parseInfo->staticContext->
1063 externalVariableLoader()->announceExternalVariable(name, CommonSequenceTypes::ZeroOrMoreItems));
1064
1065 if(varType)
1066 {
1067 const Expression::Ptr extRef(create(new ExternalVariableReference(name, varType), sourceLocator, parseInfo));
1068 const Expression::Ptr checked(TypeChecker::applyFunctionConversion(extRef, varType, parseInfo->staticContext));
1069 retval = checked;
1070 }
1071 else if(!raiseErrorOnUnavailability && parseInfo->isXSLT())
1072 {
1073 /* In XSL-T, global variables are in scope for the whole
1074 * stylesheet, so we must resolve this first at the end. */
1075 retval = create(new UnresolvedVariableReference(name), sourceLocator, parseInfo);
1076 parseInfo->unresolvedVariableReferences.insert(name, retval);
1077 }
1078 else
1079 variableUnavailable(name, parseInfo, sourceLocator);
1080 }
1081
1082 return retval;
1083}
1084
1085static Expression::Ptr createReturnOrderBy(const OrderSpecTransfer::List &orderSpecTransfer,
1086 const Expression::Ptr &returnExpr,
1087 const OrderBy::Stability stability,
1088 const YYLTYPE &sourceLocator,
1089 const ParserContext *const parseInfo)
1090{
1091 // TODO do resize(orderSpec.size() + 1)
1092 Expression::List exprs;
1093 OrderBy::OrderSpec::Vector orderSpecs;
1094
1095 exprs.append(returnExpr);
1096
1097 const int len = orderSpecTransfer.size();
1098
1099 for(int i = 0; i < len; ++i)
1100 {
1101 exprs.append(orderSpecTransfer.at(i).expression);
1102 orderSpecs.append(orderSpecTransfer.at(i).orderSpec);
1103 }
1104
1105 return create(new ReturnOrderBy(stability, orderSpecs, exprs), sourceLocator, parseInfo);
1106}
1107
1108%}
1109
1110/* This grammar shouldn't be compiled with anything older than the Bison version
1111 * specified below. This '%require' directive was introduced in Bison 2.2. */
1112%require "2.3a"
1113
1114%name-prefix="XPath"
1115
1116/* Specifies the name of the generated parser. */
1117%output="qquerytransformparser.cpp"
1118
1119/* Output the .output file. */
1120%verbose
1121
1122/* Yes, we want descriptive error messages. */
1123%error-verbose
1124
1125/* We'd like to be reentrant/thread-safe */
1126%pure-parser
1127
1128/* We want code for line/columns to be generated. */
1129%locations
1130
1131/* Create a header file and put declarations there. */
1132%defines
1133
1134%parse-param {ParserContext *const parseInfo}
1135%lex-param {ParserContext *const parseInfo}
1136
1137%expect 4
1138/* Silences the following:
1139
1140state 327
1141
1142 293 SequenceType: ItemType . OccurrenceIndicator
1143
1144 "+" shift, and go to state 379
1145 "*" shift, and go to state 380
1146 "?" shift, and go to state 381
1147
1148 "+" [reduce using rule 295 (OccurrenceIndicator)]
1149 "*" [reduce using rule 295 (OccurrenceIndicator)]
1150 $default reduce using rule 295 (OccurrenceIndicator)
1151
1152 OccurrenceIndicator go to state 382
1153
1154state 45
1155
1156 200 PathExpr: "/" . RelativePathExpr
1157 203 | "/" .
1158
1159 [...]
1160
1161 "<" [reduce using rule 203 (PathExpr)]
1162 "*" [reduce using rule 203 (PathExpr)]
1163 $default reduce using rule 203 (PathExpr)
1164*/
1165
1166%token <sval> STRING_LITERAL "<string literal>"
1167
1168/**
1169 * This token is only used in element content and signals content that
1170 * is not Boundary whitespace. Nevertheless, the token value can be all whitespace,
1171 * but it was specified using character references or CDATA sections by the user. */
1172%token <sval> NON_BOUNDARY_WS "<non-boundary text node>"
1173
1174/* XPath 2.0 allows quotes and apostrophes to be escaped with "" and ''; this token is
1175 is used for XPath 2.0 literals such that we can flag syntax errors if running in
1176 1.0 mode. */
1177%token <sval> XPATH2_STRING_LITERAL "<string literal(XPath 2.0)>"
1178%token <sval> QNAME "QName"
1179%token <sval> NCNAME "NCName"
1180
1181/* A QName as a clark name. See QXmlName::toClarkName(). */
1182%token <sval> CLARK_NAME "ClarkName"
1183
1184/**
1185 * Is "ncname:*". The token value does not include the colon and the star.
1186 */
1187%token <sval> ANY_LOCAL_NAME
1188
1189/**
1190 * Is "*:ncname". The token value does not include the colon and the star.
1191 */
1192%token <sval> ANY_PREFIX
1193
1194/**
1195 * An XPath 1.0 number literal. It is a string value because
1196 * Numeric::fromLexical() does the tokenization.
1197 */
1198%token <sval> NUMBER "<number literal>"
1199
1200/**
1201 * XPath 2.0 number literal. It includes the use of 'e'/'E'
1202 */
1203%token <sval> XPATH2_NUMBER "<number literal(XPath 2.0)>"
1204
1205%token ANCESTOR "ancestor"
1206%token ANCESTOR_OR_SELF "ancestor-or-self"
1207%token AND "and"
1208%token APOS "'"
1209%token APPLY_TEMPLATE "apply-template"
1210%token AS "as"
1211%token ASCENDING "ascending"
1212%token ASSIGN ":="
1213%token AT "at"
1214%token AT_SIGN "@"
1215%token ATTRIBUTE "attribute"
1216%token AVT /* Synthetic token. Signals an attribute value template. */
1217%token BAR "|"
1218%token BASEURI "base-uri"
1219%token BEGIN_END_TAG "</"
1220%token BOUNDARY_SPACE "boundary-space"
1221%token BY "by"
1222%token CALL_TEMPLATE "call-template"
1223%token CASE "case"
1224%token CASTABLE "castable"
1225%token CAST "cast"
1226%token CHILD "child"
1227%token COLLATION "collation"
1228%token COLONCOLON "::"
1229%token COMMA ","
1230%token COMMENT "comment"
1231%token COMMENT_START "<!--"
1232%token CONSTRUCTION "construction"
1233%token COPY_NAMESPACES "copy-namespaces"
1234%token CURLY_LBRACE "{"
1235%token CURLY_RBRACE "}"
1236%token DECLARE "declare"
1237%token DEFAULT "default"
1238%token DESCENDANT "descendant"
1239%token DESCENDANT_OR_SELF "descendant-or-self"
1240%token DESCENDING "descending"
1241%token DIV "div"
1242%token DOCUMENT "document"
1243%token DOCUMENT_NODE "document-node"
1244%token DOLLAR "$"
1245%token DOT "."
1246%token DOTDOT ".."
1247%token ELEMENT "element"
1248%token ELSE "else"
1249%token EMPTY "empty"
1250%token EMPTY_SEQUENCE "empty-sequence"
1251%token ENCODING "encoding"
1252%token END_OF_FILE 0 "end of file"
1253%token END_SORT "end_sort"
1254%token EQ "eq"
1255%token ERROR "unknown keyword" /* Used by the Tokenizer. We use the phrase "keyword" instead of "token" to be less pointy. */
1256%token EVERY "every"
1257%token EXCEPT "except"
1258%token EXTERNAL "external"
1259%token FOLLOWING "following"
1260%token FOLLOWING_SIBLING "following-sibling"
1261%token FOLLOWS ">>"
1262%token FOR_APPLY_TEMPLATE "for-apply-template" /* Synthetic token, used in XSL-T. */
1263%token FOR "for"
1264%token FUNCTION "function"
1265%token GE "ge"
1266%token G_EQ "="
1267%token G_GE ">="
1268%token G_GT ">"
1269%token G_LE "<="
1270%token G_LT "<"
1271%token G_NE "!="
1272%token GREATEST "greatest"
1273%token GT "gt"
1274%token IDIV "idiv"
1275%token IF "if"
1276%token IMPORT "import"
1277%token INHERIT "inherit"
1278%token IN "in"
1279%token INSTANCE "instance"
1280%token INTERSECT "intersect"
1281%token IS "is"
1282%token ITEM "item"
1283%token LAX "lax"
1284%token LBRACKET "["
1285%token LEAST "least"
1286%token LE "le"
1287%token LET "let"
1288%token LPAREN "("
1289%token LT "lt"
1290%token MAP "map" /* Synthetic token, used in XSL-T. */
1291%token MATCHES "matches"
1292%token MINUS "-"
1293%token MODE "mode" /* Synthetic token, used in XSL-T. */
1294%token MOD "mod"
1295%token MODULE "module"
1296%token NAME "name"
1297%token NAMESPACE "namespace"
1298%token NE "ne"
1299%token NODE "node"
1300%token NO_INHERIT "no-inherit"
1301%token NO_PRESERVE "no-preserve"
1302%token OF "of"
1303%token OPTION "option"
1304%token ORDERED "ordered"
1305%token ORDERING "ordering"
1306%token ORDER "order"
1307%token OR "or"
1308%token PARENT "parent"
1309%token PI_START "<?"
1310%token PLUS "+"
1311%token POSITION_SET /* Synthetic token. */
1312%token PRAGMA_END "#)"
1313%token PRAGMA_START "(#"
1314%token PRECEDES "<<"
1315%token PRECEDING "preceding"
1316%token PRECEDING_SIBLING "preceding-sibling"
1317%token PRESERVE "preserve"
1318%token PRIORITY "priority"
1319%token PROCESSING_INSTRUCTION "processing-instruction"
1320%token QUESTION "?"
1321%token QUICK_TAG_END "/>"
1322%token QUOTE "\""
1323%token RBRACKET "]"
1324%token RETURN "return"
1325%token RPAREN ")"
1326%token SATISFIES "satisfies"
1327%token SCHEMA_ATTRIBUTE "schema-attribute"
1328%token SCHEMA_ELEMENT "schema-element"
1329%token SCHEMA "schema"
1330%token SELF "self"
1331%token SEMI_COLON ";"
1332%token SLASH "/"
1333%token SLASHSLASH "//"
1334%token SOME "some"
1335%token SORT "sort" /* Synthetic token, used in XSL-T. */
1336%token STABLE "stable"
1337%token STAR "*"
1338%token STRICT "strict"
1339%token STRIP "strip"
1340%token SUCCESS /* Synthetic token, used by the Tokenizer. */
1341%token <sval> COMMENT_CONTENT
1342%token <sval> PI_CONTENT
1343%token <sval> PI_TARGET
1344%token <sval> XSLT_VERSION /* Synthetic token, used in XSL-T. */
1345%token TEMPLATE "template"
1346%token TEXT "text"
1347%token THEN "then"
1348%token TO "to"
1349%token TREAT "treat"
1350%token TUNNEL "tunnel" /* Synthetic token, used in XSL-T. */
1351%token TYPESWITCH "typeswitch"
1352%token UNION "union"
1353%token UNORDERED "unordered"
1354%token VALIDATE "validate"
1355%token VARIABLE "variable"
1356%token VERSION "version"
1357%token WHERE "where"
1358%token XQUERY "xquery"
1359%token INTERNAL "internal" /* Synthetic token, used in XSL-T. */
1360%token INTERNAL_NAME "internal-name" /* Synthetic token, used in XSL-T. */
1361%token CURRENT "current" /* Synthetic token, used in XSL-T. */
1362
1363/* Alphabetically. */
1364%type <attributeHolder> Attribute
1365%type <attributeHolders> DirAttributeList
1366%type <cardinality> OccurrenceIndicator
1367%type <enums.axis> Axis AxisToken
1368%type <enums.boundarySpacePolicy> BoundarySpacePolicy
1369%type <enums.combinedNodeOp> IntersectOperator
1370%type <enums.constructionMode> ConstructionMode
1371%type <enums.mathOperator> MultiplyOperator AdditiveOperator UnaryOperator
1372%type <enums.nodeOperator> NodeOperator
1373%type <enums.orderingEmptySequence> OrderingEmptySequence EmptynessModifier
1374%type <enums.sortDirection> DirectionModifier
1375
1376%type <enums.orderingMode> OrderingMode
1377%type <enums.slot> PositionalVar
1378%type <enums.validationMode> ValidationMode
1379%type <enums.valueOperator> ValueComparisonOperator GeneralComparisonOperator
1380%type <expr> OrExpr AndExpr ComparisonExpr UnionExpr Literal
1381 AdditiveExpr MultiplicativeExpr PrimaryExpr FilterExpr
1382 StepExpr PathExpr RelativePathExpr Expr ExprSingle
1383 VarRef ContextItemExpr IfExpr CastExpr CastableExpr
1384 TreatExpr InstanceOfExpr ValueExpr UnaryExpr NodeComp
1385 IntersectExceptExpr RangeExpr ParenthesizedExpr
1386 ValueComp FunctionCallExpr GeneralComp ForClause
1387 WhereClause FLWORExpr ForTail QuantifiedExpr QueryBody
1388 SomeQuantificationExpr SomeQuantificationTail
1389 EveryQuantificationExpr EveryQuantificationTail
1390 ExtensionExpr EnclosedOptionalExpr VariableValue
1391 EnclosedExpr FunctionBody ValidateExpr NumericLiteral
1392 OrderingExpr TypeswitchExpr LetClause LetTail
1393 Constructor DirectConstructor DirElemConstructor
1394 ComputedConstructor CompDocConstructor CompElemConstructor
1395 CompTextConstructor CompCommentConstructor CompPIConstructor
1396 DirPIConstructor CompAttrConstructor DirElemConstructorTail
1397 AxisStep ForwardStep ReverseStep AbbrevForwardStep
1398 CaseDefault CaseClause CaseTail CompAttributeName
1399 FilteredAxisStep DirCommentConstructor CompPIName
1400 DirAttributeValue AbbrevReverseStep CompNamespaceConstructor
1401 CompElementName CompNameExpr SatisfiesClause Pattern PathPattern
1402 PatternStep RelativePathPattern IdKeyPattern OptionalAssign
1403 OptionalDefaultValue
1404
1405%type <orderSpec> OrderSpec
1406%type <expressionList> ExpressionSequence FunctionArguments
1407 DirElemContent AttrValueContent
1408%type <orderSpecs> OrderSpecList OrderByClause MandatoryOrderByClause
1409%type <functionArgument> Param
1410%type <functionArguments> ParamList
1411%type <itemType> KindTest ItemType AtomicType NodeTest NameTest WildCard NodeTestInAxisStep
1412 ElementTest AttributeTest SchemaElementTest SchemaAttributeTest
1413 TextTest CommentTest PITest DocumentTest AnyKindTest AnyAttributeTest
1414%type <qName> ElementName QName VarName FunctionName PragmaName TypeName NCName
1415 CaseVariable AttributeName OptionalTemplateName
1416 TemplateName Mode OptionalMode
1417%type <qNameVector> Modes OptionalModes
1418%type <sequenceType> SequenceType SingleType TypeDeclaration
1419%type <sval> URILiteral StringLiteral LexicalName
1420%type <enums.Bool> IsInternal IsTunnel
1421%type <enums.Double> OptionalPriority
1422%type <enums.pathKind> MapOrSlash
1423
1424/* Operator Precendence
1425 * See: http://www.w3.org/TR/xpath20/#parse-note-occurrence-indicators */
1426%left STAR DIV
1427%left PLUS MINUS
1428
1429%%
1430
1431/* Here, the grammar starts. In the brackets on the right you
1432 * find the number of corresponding EBNF rule in the XQuery 1.0 specification. If it
1433 * contains an X, it means the non-terminal has no counter part in the grammar, but
1434 * exists for implementation purposes. */
1435Module: VersionDecl LibraryModule /* [1] */
1436| VersionDecl MainModule
1437
1438VersionDecl: /* empty */ /* [2] */
1439| XQUERY VERSION StringLiteral Encoding Separator
1440 {
1441
1442/* Suppress more compiler warnings about unused defines. */
1443#if defined(YYNNTS) \
1444 || defined(yyerrok) \
1445 || defined(YYNSTATES) \
1446 || defined(YYRHSLOC) \
1447 || defined(YYRECOVERING) \
1448 || defined(YYFAIL) \
1449 || defined(YYERROR) \
1450 || defined(YYNRULES) \
1451 || defined(YYBACKUP) \
1452 || defined(YYMAXDEPTH) \
1453 || defined(yyclearin) \
1454 || defined(YYERRCODE) \
1455 || defined(YY_LOCATION_PRINT) \
1456 || defined(YYLLOC_DEFAULT)
1457#endif
1458
1459 if($3 != QLatin1String("1.0"))
1460 {
1461 const ReflectYYLTYPE ryy(@$, parseInfo);
1462
1463 parseInfo->staticContext->error(QtXmlPatterns::tr("Version %1 is not supported. The supported "
1464 "XQuery version is 1.0.")
1465 .arg(formatData($3)),
1466 ReportContext::XQST0031, &ryy);
1467 }
1468 }
1469
1470Encoding: /* empty */ /* [X] */
1471| ENCODING StringLiteral
1472 {
1473 const QRegExp encNameRegExp(QLatin1String("[A-Za-z][A-Za-z0-9._\\-]*"));
1474
1475 if(!encNameRegExp.exactMatch($2))
1476 {
1477 parseInfo->staticContext->error(QtXmlPatterns::tr("The encoding %1 is invalid. "
1478 "It must contain Latin characters only, "
1479 "must not contain whitespace, and must match "
1480 "the regular expression %2.")
1481 .arg(formatKeyword((yyvsp[(2) - (2)].sval)),
1482 formatExpression(encNameRegExp.pattern())),
1483 ReportContext::XQST0087, fromYYLTYPE(@$, parseInfo));
1484 }
1485 }
1486
1487MainModule: Prolog QueryBody /* [3] */
1488 {
1489 /* In XSL-T, we can have dangling variable references, so resolve them
1490 * before we proceed with other steps, such as checking circularity. */
1491 if(parseInfo->isXSLT())
1492 {
1493 typedef QHash<QXmlName, Expression::Ptr> Hash;
1494 const Hash::const_iterator end(parseInfo->unresolvedVariableReferences.constEnd());
1495
1496 for(Hash::const_iterator it(parseInfo->unresolvedVariableReferences.constBegin()); it != end; ++it)
1497 {
1498 const Expression::Ptr body(resolveVariable(it.key(), @$, parseInfo, true)); // TODO source locations vaise
1499 Q_ASSERT(body);
1500 it.value()->as<UnresolvedVariableReference>()->bindTo(body);
1501 }
1502 }
1503
1504 /* The UserFunction callsites aren't bound yet, so bind them(if possible!). */
1505 {
1506 const UserFunctionCallsite::List::const_iterator cend(parseInfo->userFunctionCallsites.constEnd());
1507 UserFunctionCallsite::List::const_iterator cit(parseInfo->userFunctionCallsites.constBegin());
1508 for(; cit != cend; ++cit) /* For each callsite. */
1509 {
1510 const UserFunctionCallsite::Ptr callsite(*cit);
1511 Q_ASSERT(callsite);
1512 const UserFunction::List::const_iterator end(parseInfo->userFunctions.constEnd());
1513 UserFunction::List::const_iterator it(parseInfo->userFunctions.constBegin());
1514
1515 for(; it != end; ++it) /* For each UserFunction. */
1516 {
1517 const FunctionSignature::Ptr sign((*it)->signature());
1518 Q_ASSERT(sign);
1519
1520 if(callsite->isSignatureValid(sign))
1521 {
1522 callsite->setSource((*it),
1523 parseInfo->allocateCacheSlots((*it)->argumentDeclarations().count()));
1524 break;
1525 }
1526 }
1527 if(it == end)
1528 {
1529 parseInfo->staticContext->error(QtXmlPatterns::tr("No function with signature %1 is available")
1530 .arg(formatFunction(callsite)),
1531 ReportContext::XPST0017, fromYYLTYPE(@$, parseInfo));
1532 }
1533 }
1534 }
1535
1536 /* Mark callsites in UserFunction bodies as recursive, if they are. */
1537 {
1538 const UserFunction::List::const_iterator fend(parseInfo->userFunctions.constEnd());
1539 UserFunction::List::const_iterator fit(parseInfo->userFunctions.constBegin());
1540 for(; fit != fend; ++fit)
1541 {
1542 CallTargetDescription::List signList;
1543 signList.append((*fit)->signature());
1544 CallTargetDescription::checkCallsiteCircularity(signList, (*fit)->body());
1545 }
1546 }
1547
1548 /* Now, check all global variables for circularity. This is done
1549 * backwards because global variables are only in scope below them,
1550 * in XQuery. */
1551 {
1552 const VariableDeclaration::List::const_iterator start(parseInfo->declaredVariables.constBegin());
1553 VariableDeclaration::List::const_iterator it(parseInfo->declaredVariables.constEnd());
1554
1555 while(it != start)
1556 {
1557 --it;
1558 if((*it)->type != VariableDeclaration::ExpressionVariable && (*it)->type != VariableDeclaration::GlobalVariable)
1559 continue; /* We want to ignore 'external' variables. */
1560
1561 FunctionSignature::List signList;
1562 checkVariableCircularity(*it, (*it)->expression(), (*it)->type, signList, parseInfo);
1563 ExpressionFactory::registerLastPath((*it)->expression());
1564 parseInfo->finalizePushedVariable(1, false); /* Warn if it's unused. */
1565 }
1566 }
1567
1568 /* Generate code for doing initial template name calling. One problem
1569 * is that we compilation in the initial template name, since we throw away the
1570 * code if we don't have the requested template. */
1571 if(parseInfo->languageAccent == QXmlQuery::XSLT20
1572 && !parseInfo->initialTemplateName.isNull()
1573 && parseInfo->namedTemplates.contains(parseInfo->initialTemplateName))
1574 {
1575 parseInfo->queryBody = create(new CallTemplate(parseInfo->initialTemplateName,
1576 WithParam::Hash()),
1577 @$, parseInfo);
1578 parseInfo->templateCalls.append(parseInfo->queryBody);
1579 /* We just discard the template body that XSLTTokenizer generated. */
1580 }
1581 else
1582 parseInfo->queryBody = $2;
1583 }
1584
1585LibraryModule: ModuleDecl Prolog /* [4] */
1586
1587ModuleDecl: MODULE NAMESPACE NCNAME G_EQ URILiteral Separator /* [5] */
1588 {
1589 // TODO add to namespace context
1590 parseInfo->moduleNamespace = parseInfo->staticContext->namePool()->allocateNamespace($3);
1591 }
1592
1593Prolog: /* Empty. */ /* [6] */
1594/* First part. */
1595| Prolog DefaultNamespaceDecl
1596 {
1597 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1598 if(parseInfo->hasSecondPrologPart)
1599 parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, "
1600 "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
1601 }
1602| Prolog Setter
1603 {
1604 if(parseInfo->hasSecondPrologPart)
1605 parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, "
1606 "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
1607 }
1608| Prolog NamespaceDecl
1609 {
1610 if(parseInfo->hasSecondPrologPart)
1611 parseInfo->staticContext->error(QtXmlPatterns::tr("Namespace declarations must occur before function, "
1612 "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
1613 }
1614| Prolog Import
1615 {
1616 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1617 if(parseInfo->hasSecondPrologPart)
1618 parseInfo->staticContext->error(QtXmlPatterns::tr("Module imports must occur before function, "
1619 "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
1620 }
1621| Prolog TemplateDecl
1622
1623/* Second part. */
1624| Prolog VarDecl
1625 {
1626 parseInfo->hasSecondPrologPart = true;
1627 }
1628| Prolog FunctionDecl
1629 {
1630 parseInfo->hasSecondPrologPart = true;
1631 }
1632| Prolog OptionDecl
1633 {
1634 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1635 parseInfo->hasSecondPrologPart = true;
1636 }
1637
1638/*
1639 * declare template name theName
1640 * {
1641 * "expression"
1642 * };
1643 *
1644 * or
1645 *
1646 * declare template name theName matches (pattern) mode modeName priority 123
1647 * {
1648 * "expression"
1649 * };
1650 *
1651 */
1652TemplateDecl: DECLARE TEMPLATE TemplateName
1653 OptionalTemplateParameters
1654 TypeDeclaration
1655 EnclosedOptionalExpr Separator /* [X] */
1656 {
1657 Template::Ptr temp(create(new Template(parseInfo->currentImportPrecedence, $5), @$, parseInfo));
1658
1659 registerNamedTemplate($3, typeCheckTemplateBody($6, $5, parseInfo),
1660 parseInfo, @1, temp);
1661 temp->templateParameters = parseInfo->templateParameters;
1662 parseInfo->templateParametersHandled();
1663 }
1664| DECLARE TEMPLATE OptionalTemplateName
1665 MATCHES LPAREN
1666 {
1667 parseInfo->isParsingPattern = true;
1668 }
1669 Pattern
1670 {
1671 parseInfo->isParsingPattern = false;
1672 }
1673 RPAREN
1674 OptionalModes
1675 OptionalPriority
1676 OptionalTemplateParameters
1677 TypeDeclaration
1678 EnclosedOptionalExpr Separator /* [X] */
1679 {
1680 /* In this grammar branch, we're guaranteed to be a template rule, but
1681 * may also be a named template. */
1682
1683 const ImportPrecedence ip = parseInfo->isFirstTemplate() ? 0 : parseInfo->currentImportPrecedence;
1684 Expression::Ptr pattern($7);
1685 const TemplatePattern::ID templateID = parseInfo->allocateTemplateID();
1686
1687 Template::Ptr templ(create(new Template(ip, $13), @$, parseInfo));
1688 templ->body = typeCheckTemplateBody($14, $13, parseInfo);
1689 templ->templateParameters = parseInfo->templateParameters;
1690 parseInfo->templateParametersHandled();
1691
1692 TemplatePattern::Vector ourPatterns;
1693 /* We do it as per 6.4 Conflict Resolution for Template Rules:
1694 *
1695 * "If the pattern contains multiple alternatives separated by |, then
1696 * the template rule is treated equivalently to a set of template
1697 * rules, one for each alternative. However, it is not an error if a
1698 * node matches more than one of the alternatives." */
1699 while(pattern->is(Expression::IDCombineNodes))
1700 {
1701 const Expression::List operands(pattern->operands());
1702 pattern = operands.first();
1703
1704 loadPattern(operands.at(1), ourPatterns, templateID, $11, templ);
1705 }
1706
1707 loadPattern(pattern, ourPatterns, templateID, $11, templ);
1708
1709 if(!$3.isNull())
1710 registerNamedTemplate($3, $14, parseInfo, @1, templ);
1711
1712 /* Now, let's add it to all the relevant templates. */
1713 for(int i = 0; i < $10.count(); ++i) /* For each mode. */
1714 {
1715 const QXmlName &modeName = $10.at(i);
1716
1717 if(modeName == QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::all) && $10.count() > 1)
1718 {
1719 parseInfo->staticContext->error(QtXmlPatterns::tr("The keyword %1 cannot occur with any other mode name.")
1720 .arg(formatKeyword(QLatin1String("#all"))),
1721 ReportContext::XTSE0530,
1722 fromYYLTYPE(@$, parseInfo));
1723 }
1724
1725 /* For each pattern the template use. */
1726 const TemplateMode::Ptr mode(parseInfo->modeFor(modeName));
1727 for(int t = 0; t < ourPatterns.count(); ++t)
1728 mode->templatePatterns.append(ourPatterns.at(t));
1729 }
1730 }
1731
1732OptionalPriority: /* Empty. */ /* [X] */
1733 {
1734 $$ = std::numeric_limits<xsDouble>::quiet_NaN();
1735 }
1736
1737| PRIORITY StringLiteral
1738 {
1739 const AtomicValue::Ptr val(Decimal::fromLexical($2));
1740 if(val->hasError())
1741 {
1742 parseInfo->staticContext->error(QtXmlPatterns::tr("The value of attribute %1 must be of type %2, which %3 isn't.")
1743 .arg(formatKeyword(QLatin1String("priority")),
1744 formatType(parseInfo->staticContext->namePool(), BuiltinTypes::xsDecimal),
1745 formatData($2)),
1746 ReportContext::XTSE0530,
1747 fromYYLTYPE(@$, parseInfo));
1748 }
1749 else
1750 $$ = val->as<Numeric>()->toDouble();
1751 }
1752
1753OptionalTemplateName: /* Empty. */ /* [X] */
1754 {
1755 $$ = QXmlName();
1756 }
1757| TemplateName
1758
1759TemplateName: NAME ElementName
1760 {
1761 $$ = $2;
1762 }
1763
1764Setter: BoundarySpaceDecl /* [7] */
1765| DefaultCollationDecl
1766 {
1767 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1768 }
1769| BaseURIDecl
1770| ConstructionDecl
1771 {
1772 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1773 }
1774| OrderingModeDecl
1775 {
1776 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1777 }
1778| EmptyOrderDecl
1779 {
1780 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1781 }
1782| CopyNamespacesDecl
1783
1784Import: SchemaImport /* [8] */
1785| ModuleImport
1786
1787Separator: SEMI_COLON /* [9] */
1788
1789NamespaceDecl: DECLARE NAMESPACE NCNAME G_EQ URILiteral IsInternal Separator /* [10] */
1790 {
1791 if(!$6)
1792 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1793
1794 if($3 == QLatin1String("xmlns"))
1795 {
1796 parseInfo->staticContext->error(QtXmlPatterns::tr("It is not possible to redeclare prefix %1.")
1797 .arg(formatKeyword(QLatin1String("xmlns"))),
1798 ReportContext::XQST0070, fromYYLTYPE(@$, parseInfo));
1799 }
1800 else if ($5 == CommonNamespaces::XML || $3 == QLatin1String("xml"))
1801 {
1802 parseInfo->staticContext->error(QtXmlPatterns::tr(
1803 "The prefix %1 can not be bound. By default, it is already bound "
1804 "to the namespace %2.")
1805 .arg(formatKeyword("xml"))
1806 .arg(formatURI(CommonNamespaces::XML)),
1807 ReportContext::XQST0070,
1808 fromYYLTYPE(@$, parseInfo));
1809 }
1810 else if(parseInfo->declaredPrefixes.contains($3))
1811 {
1812 /* This includes the case where the user has bound a default prefix(such
1813 * as 'local') and now tries to do it again. */
1814 parseInfo->staticContext->error(QtXmlPatterns::tr("Prefix %1 is already declared in the prolog.")
1815 .arg(formatKeyword($3)),
1816 ReportContext::XQST0033, fromYYLTYPE(@$, parseInfo));
1817 }
1818 else
1819 {
1820 parseInfo->declaredPrefixes.append($3);
1821
1822 if($5.isEmpty())
1823 {
1824 parseInfo->staticContext->namespaceBindings()->addBinding(QXmlName(StandardNamespaces::UndeclarePrefix,
1825 StandardLocalNames::empty,
1826 parseInfo->staticContext->namePool()->allocatePrefix($3)));
1827 }
1828 else
1829 {
1830 parseInfo->staticContext->namespaceBindings()->addBinding(parseInfo->staticContext->namePool()->allocateBinding($3, $5));
1831 }
1832 }
1833 }
1834
1835BoundarySpaceDecl: DECLARE BOUNDARY_SPACE BoundarySpacePolicy Separator /* [11] */
1836 {
1837 if(parseInfo->hasDeclaration(ParserContext::BoundarySpaceDecl))
1838 {
1839 parseInfo->staticContext->error(prologMessage("declare boundary-space"),
1840 ReportContext::XQST0068, fromYYLTYPE(@$, parseInfo));
1841 }
1842 else
1843 {
1844 parseInfo->staticContext->setBoundarySpacePolicy($3);
1845 parseInfo->registerDeclaration(ParserContext::BoundarySpaceDecl);
1846 }
1847 }
1848
1849BoundarySpacePolicy: STRIP /* [X] */
1850 {
1851 $$ = StaticContext::BSPStrip;
1852 }
1853
1854| PRESERVE
1855 {
1856 $$ = StaticContext::BSPPreserve;
1857 }
1858
1859DefaultNamespaceDecl: DeclareDefaultElementNamespace /* [12] */
1860| DeclareDefaultFunctionNamespace
1861
1862DeclareDefaultElementNamespace: DECLARE DEFAULT ELEMENT NAMESPACE
1863 URILiteral Separator /* [X] */
1864 {
1865 if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultElementNamespace))
1866 {
1867 parseInfo->staticContext->error(prologMessage("declare default element namespace"),
1868 ReportContext::XQST0066, fromYYLTYPE(@$, parseInfo));
1869 }
1870 else
1871 {
1872 parseInfo->staticContext->namespaceBindings()->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace($5), StandardLocalNames::empty));
1873 parseInfo->registerDeclaration(ParserContext::DeclareDefaultElementNamespace);
1874 }
1875 }
1876
1877DeclareDefaultFunctionNamespace: DECLARE DEFAULT FUNCTION NAMESPACE
1878 URILiteral Separator /* [X] */
1879 {
1880 if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultFunctionNamespace))
1881 {
1882 parseInfo->staticContext->error(prologMessage("declare default function namespace"),
1883 ReportContext::XQST0066, fromYYLTYPE(@$, parseInfo));
1884 }
1885 else
1886 {
1887 parseInfo->staticContext->setDefaultFunctionNamespace($5);
1888 parseInfo->registerDeclaration(ParserContext::DeclareDefaultFunctionNamespace);
1889 }
1890 }
1891
1892OptionDecl: DECLARE OPTION ElementName StringLiteral Separator /* [13] */
1893 {
1894 if($3.prefix() == StandardPrefixes::empty)
1895 {
1896 parseInfo->staticContext->error(QtXmlPatterns::tr("The name of an option must have a prefix. "
1897 "There is no default namespace for options."),
1898 ReportContext::XPST0081, fromYYLTYPE(@$, parseInfo));
1899 }
1900 }
1901
1902OrderingModeDecl: DECLARE ORDERING OrderingMode Separator /* [14] */
1903 {
1904 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
1905 if(parseInfo->hasDeclaration(ParserContext::OrderingModeDecl))
1906 {
1907 parseInfo->staticContext->error(prologMessage("declare ordering"),
1908 ReportContext::XQST0065, fromYYLTYPE(@$, parseInfo));
1909 }
1910 else
1911 {
1912 parseInfo->registerDeclaration(ParserContext::OrderingModeDecl);
1913 parseInfo->staticContext->setOrderingMode($3);
1914 }
1915 }
1916
1917OrderingMode: ORDERED
1918 {
1919 $$ = StaticContext::Ordered;
1920 }
1921| UNORDERED
1922 {
1923 $$ = StaticContext::Unordered;
1924 }
1925
1926EmptyOrderDecl: DECLARE DEFAULT ORDER OrderingEmptySequence Separator /* [15] */
1927 {
1928 if(parseInfo->hasDeclaration(ParserContext::EmptyOrderDecl))
1929 {
1930 parseInfo->staticContext->error(prologMessage("declare default order"),
1931 ReportContext::XQST0069, fromYYLTYPE(@$, parseInfo));
1932 }
1933 else
1934 {
1935 parseInfo->registerDeclaration(ParserContext::EmptyOrderDecl);
1936 parseInfo->staticContext->setOrderingEmptySequence($4);
1937 }
1938 }
1939
1940OrderingEmptySequence: EMPTY LEAST /* [X] */
1941 {
1942 $$ = StaticContext::Least;
1943 }
1944| EMPTY GREATEST
1945 {
1946 $$ = StaticContext::Greatest;
1947 }
1948
1949CopyNamespacesDecl: DECLARE COPY_NAMESPACES PreserveMode COMMA
1950 InheritMode Separator /* [16] */
1951 {
1952 if(parseInfo->hasDeclaration(ParserContext::CopyNamespacesDecl))
1953 {
1954 parseInfo->staticContext->error(prologMessage("declare copy-namespaces"),
1955 ReportContext::XQST0055, fromYYLTYPE(@$, parseInfo));
1956 }
1957 else
1958 {
1959 parseInfo->registerDeclaration(ParserContext::CopyNamespacesDecl);
1960 }
1961 }
1962
1963PreserveMode: PRESERVE /* [17] */
1964 {
1965 parseInfo->preserveNamespacesMode = true;
1966 }
1967
1968| NO_PRESERVE
1969 {
1970 parseInfo->preserveNamespacesMode = false;
1971 }
1972
1973InheritMode: INHERIT /* [18] */
1974 {
1975 parseInfo->inheritNamespacesMode = true;
1976 }
1977
1978| NO_INHERIT
1979 {
1980 parseInfo->inheritNamespacesMode = false;
1981 }
1982
1983DefaultCollationDecl: DECLARE DEFAULT COLLATION StringLiteral Separator /* [19] */
1984 {
1985 if(parseInfo->hasDeclaration(ParserContext::DefaultCollationDecl))
1986 {
1987 parseInfo->staticContext->error(prologMessage("declare default collation"),
1988 ReportContext::XQST0038, fromYYLTYPE(@$, parseInfo));
1989 }
1990 else
1991 {
1992 const QUrl coll(resolveAndCheckCollation<ReportContext::XQST0038>($4, parseInfo, @$));
1993
1994 parseInfo->registerDeclaration(ParserContext::DefaultCollationDecl);
1995 parseInfo->staticContext->setDefaultCollation(coll);
1996 }
1997 }
1998
1999BaseURIDecl: DECLARE BASEURI IsInternal URILiteral Separator /* [20] */
2000 {
2001 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$, $3);
2002 if(parseInfo->hasDeclaration(ParserContext::BaseURIDecl))
2003 {
2004 parseInfo->staticContext->error(prologMessage("declare base-uri"),
2005 ReportContext::XQST0032, fromYYLTYPE(@$, parseInfo));
2006 }
2007 else
2008 {
2009 parseInfo->registerDeclaration(ParserContext::BaseURIDecl);
2010 const ReflectYYLTYPE ryy(@$, parseInfo);
2011
2012 QUrl toBeBase(AnyURI::toQUrl<ReportContext::XQST0046>($4, parseInfo->staticContext, &ryy));
2013 /* Now we're guaranteed that base is a valid lexical representation, but it can still be relative. */
2014
2015 if(toBeBase.isRelative())
2016 toBeBase = parseInfo->staticContext->baseURI().resolved(toBeBase);
2017
2018 parseInfo->staticContext->setBaseURI(toBeBase);
2019 }
2020 }
2021
2022SchemaImport: IMPORT SCHEMA SchemaPrefix URILiteral FileLocations Separator /* [21] */
2023 {
2024 parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Import feature is not supported, "
2025 "and therefore %1 declarations cannot occur.")
2026 .arg(formatKeyword("import schema")),
2027 ReportContext::XQST0009, fromYYLTYPE(@$, parseInfo));
2028 }
2029
2030SchemaPrefix: /* empty */ /* [22] */
2031| DEFAULT ELEMENT NAMESPACE
2032| NAMESPACE NCNAME G_EQ
2033
2034ModuleImport: IMPORT MODULE ModuleNamespaceDecl URILiteral FileLocations Separator /* [23] */
2035 {
2036 if($4.isEmpty())
2037 {
2038 parseInfo->staticContext->error(QtXmlPatterns::tr("The target namespace of a %1 cannot be empty.")
2039 .arg(formatKeyword("module import")),
2040 ReportContext::XQST0088, fromYYLTYPE(@$, parseInfo));
2041
2042 }
2043 else
2044 {
2045 /* This is temporary until we have implemented it. */
2046 parseInfo->staticContext->error(QtXmlPatterns::tr("The module import feature is not supported"),
2047 ReportContext::XQST0016, fromYYLTYPE(@$, parseInfo));
2048 }
2049 }
2050
2051ModuleNamespaceDecl: /* empty */ /* [X] */
2052| NAMESPACE NCNAME G_EQ
2053
2054FileLocations: /* empty */ /* [X] */
2055| AT FileLocation
2056
2057FileLocation: URILiteral /* [X] */
2058| FileLocation COMMA URILiteral
2059
2060VarDecl: DECLARE VARIABLE IsInternal DOLLAR VarName TypeDeclaration
2061 VariableValue OptionalDefaultValue Separator /* [24] */
2062 {
2063 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3);
2064 if(variableByName($5, parseInfo))
2065 {
2066 parseInfo->staticContext->error(QtXmlPatterns::tr("A variable by name %1 has already "
2067 "been declared.")
2068 .arg(formatKeyword(parseInfo->staticContext->namePool()->toLexical($5))),
2069 parseInfo->isXSLT() ? ReportContext::XTSE0630 : ReportContext::XQST0049,
2070 fromYYLTYPE(@$, parseInfo));
2071 }
2072 else
2073 {
2074 if($7) /* We got a value assigned. */
2075 {
2076 const Expression::Ptr checked
2077 (TypeChecker::applyFunctionConversion($7, $6, parseInfo->staticContext,
2078 $3 ? ReportContext::XTTE0570 : ReportContext::XPTY0004,
2079 $3 ? TypeChecker::Options(TypeChecker::CheckFocus | TypeChecker::AutomaticallyConvert) : TypeChecker::CheckFocus));
2080
2081 pushVariable($5, $6, checked, VariableDeclaration::GlobalVariable, @$, parseInfo);
2082 parseInfo->declaredVariables.append(parseInfo->variables.last());
2083 }
2084 else /* We got an 'external' declaration. */
2085 {
2086 const SequenceType::Ptr varType(parseInfo->staticContext->
2087 externalVariableLoader()->announceExternalVariable($5, $6));
2088
2089 if(varType)
2090 {
2091 /* We push the declaration such that we can see name clashes and so on, but we don't use it for tying
2092 * any references to it. */
2093 pushVariable($5, varType, Expression::Ptr(), VariableDeclaration::ExternalVariable, @$, parseInfo);
2094 }
2095 else if($8)
2096 {
2097 /* Ok, the xsl:param got a default value, we make it
2098 * available as a regular variable declaration. */
2099 // TODO turn into checked
2100 pushVariable($5, $6, $8, VariableDeclaration::GlobalVariable, @$, parseInfo);
2101 // TODO ensure that duplicates are trapped.
2102 }
2103 else
2104 {
2105 parseInfo->staticContext->error(QtXmlPatterns::tr("No value is available for the external "
2106 "variable by name %1.")
2107 .arg(formatKeyword(parseInfo->staticContext->namePool(), $5)),
2108 parseInfo->isXSLT() ? ReportContext::XTDE0050 : ReportContext::XPDY0002,
2109 fromYYLTYPE(@$, parseInfo));
2110 }
2111 }
2112 }
2113 }
2114
2115VariableValue: EXTERNAL /* [X] */
2116 {
2117 $$.reset();
2118 }
2119| ASSIGN ExprSingle
2120 {
2121 $$ = $2;
2122 }
2123
2124OptionalDefaultValue: /* Empty. */ /* [X] */
2125 {
2126 $$.reset();
2127 }
2128| ASSIGN ExprSingle
2129 {
2130 $$ = $2;
2131 }
2132
2133ConstructionDecl: DECLARE CONSTRUCTION ConstructionMode Separator /* [25] */
2134 {
2135 if(parseInfo->hasDeclaration(ParserContext::ConstructionDecl))
2136 {
2137 parseInfo->staticContext->error(prologMessage("declare ordering"),
2138 ReportContext::XQST0067, fromYYLTYPE(@$, parseInfo));
2139 }
2140 else
2141 {
2142 parseInfo->registerDeclaration(ParserContext::ConstructionDecl);
2143 parseInfo->staticContext->setConstructionMode($3);
2144 }
2145 }
2146
2147ConstructionMode: STRIP /* [X] */
2148 {
2149 $$ = StaticContext::CMStrip;
2150 }
2151| PRESERVE
2152 {
2153 $$ = StaticContext::CMPreserve;
2154 }
2155
2156FunctionDecl: DECLARE FUNCTION IsInternal FunctionName LPAREN ParamList RPAREN
2157 {
2158 $<enums.slot>$ = parseInfo->currentExpressionSlot() - $6.count();
2159 }
2160 TypeDeclaration FunctionBody Separator /* [26] */
2161 {
2162 if(!$3)
2163 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3);
2164
2165 /* If FunctionBody is null, it is 'external', otherwise the value is the body. */
2166 const QXmlName::NamespaceCode ns($4.namespaceURI());
2167
2168 if(parseInfo->isXSLT() && !$4.hasPrefix())
2169 {
2170 parseInfo->staticContext->error(QtXmlPatterns::tr("A stylesheet function must have a prefixed name."),
2171 ReportContext::XTSE0740,
2172 fromYYLTYPE(@$, parseInfo));
2173 }
2174
2175 if($10) /* We got a function body. */
2176 {
2177 if(ns == StandardNamespaces::empty)
2178 {
2179 parseInfo->staticContext->error(QtXmlPatterns::tr("The namespace for a user defined function "
2180 "cannot be empty (try the predefined "
2181 "prefix %1 which exists for cases "
2182 "like this)")
2183 .arg(formatKeyword("local")),
2184 ReportContext::XQST0060, fromYYLTYPE(@$, parseInfo));
2185 }
2186 else if(XPathHelper::isReservedNamespace(ns))
2187 {
2188 parseInfo->staticContext->error(QtXmlPatterns::tr(
2189 "The namespace %1 is reserved; therefore "
2190 "user defined functions may not use it. "
2191 "Try the predefined prefix %2, which "
2192 "exists for these cases.")
2193 .arg(formatURI(parseInfo->staticContext->namePool(), ns), formatKeyword("local")),
2194 parseInfo->isXSLT() ? ReportContext::XTSE0080 : ReportContext::XQST0045,
2195 fromYYLTYPE(@$, parseInfo));
2196 }
2197 else if(parseInfo->moduleNamespace != StandardNamespaces::empty &&
2198 ns != parseInfo->moduleNamespace)
2199 {
2200 parseInfo->staticContext->error(QtXmlPatterns::tr(
2201 "The namespace of a user defined "
2202 "function in a library module must be "
2203 "equivalent to the module namespace. "
2204 "In other words, it should be %1 instead "
2205 "of %2")
2206 .arg(formatURI(parseInfo->staticContext->namePool(), parseInfo->moduleNamespace),
2207 formatURI(parseInfo->staticContext->namePool(), ns)),
2208 ReportContext::XQST0048, fromYYLTYPE(@$, parseInfo));
2209 }
2210 else
2211 {
2212 /* Apply function conversion such that the body matches the declared
2213 * return type. */
2214 const Expression::Ptr checked(TypeChecker::applyFunctionConversion($10, $9,
2215 parseInfo->staticContext,
2216 ReportContext::XPTY0004,
2217 TypeChecker::Options(TypeChecker::AutomaticallyConvert |
2218 TypeChecker::CheckFocus |
2219 TypeChecker::GeneratePromotion)));
2220
2221 const int argCount = $6.count();
2222 const FunctionSignature::Ptr sign(new FunctionSignature($4 /* name */,
2223 argCount /* minArgs */,
2224 argCount /* maxArgs */,
2225 $9 /* returnType */));
2226 sign->setArguments($6);
2227 const UserFunction::List::const_iterator end(parseInfo->userFunctions.constEnd());
2228 UserFunction::List::const_iterator it(parseInfo->userFunctions.constBegin());
2229
2230 for(; it != end; ++it)
2231 {
2232 if(*(*it)->signature() == *sign)
2233 {
2234 parseInfo->staticContext->error(QtXmlPatterns::tr("A function already exists with "
2235 "the signature %1.")
2236 .arg(formatFunction(parseInfo->staticContext->namePool(), sign)),
2237 parseInfo->isXSLT() ? ReportContext::XTSE0770 : ReportContext::XQST0034, fromYYLTYPE(@$, parseInfo));
2238 }
2239 }
2240
2241 VariableDeclaration::List argDecls;
2242
2243 for(int i = 0; i < argCount; ++i)
2244 argDecls.append(parseInfo->variables.at(i));
2245
2246 if($<enums.slot>8 > -1)
2247 {
2248 /* We have allocated slots, so now push them out of scope. */
2249 parseInfo->finalizePushedVariable(argCount);
2250 }
2251
2252 parseInfo->userFunctions.append(UserFunction::Ptr(new UserFunction(sign, checked, $<enums.slot>8, argDecls)));
2253 }
2254 }
2255 else /* We got an 'external' declaration. */
2256 {
2257 parseInfo->staticContext->error(QtXmlPatterns::tr("No external functions are supported. "
2258 "All supported functions can be used directly, "
2259 "without first declaring them as external"),
2260 ReportContext::XPST0017, fromYYLTYPE(@$, parseInfo));
2261 }
2262 }
2263
2264ParamList: /* empty */ /* [27] */
2265 {
2266 $$ = FunctionArgument::List();
2267 }
2268| Param
2269 {
2270 FunctionArgument::List l;
2271 l.append($1);
2272 $$ = l;
2273 }
2274| ParamList COMMA Param
2275 {
2276 FunctionArgument::List::const_iterator it($1.constBegin());
2277 const FunctionArgument::List::const_iterator end($1.constEnd());
2278
2279 for(; it != end; ++it)
2280 {
2281 if((*it)->name() == $3->name())
2282 {
2283 parseInfo->staticContext->error(QtXmlPatterns::tr("An argument by name %1 has already "
2284 "been declared. Every argument name "
2285 "must be unique.")
2286 .arg(formatKeyword(parseInfo->staticContext->namePool(), $3->name())),
2287 ReportContext::XQST0039, fromYYLTYPE(@$, parseInfo));
2288 }
2289 }
2290
2291 $1.append($3);
2292 $$ = $1;
2293 }
2294
2295Param: DOLLAR VarName TypeDeclaration /* [28] */
2296 {
2297 pushVariable($2, $3, Expression::Ptr(), VariableDeclaration::FunctionArgument, @$, parseInfo);
2298 $$ = FunctionArgument::Ptr(new FunctionArgument($2, $3));
2299 }
2300
2301FunctionBody: EXTERNAL /* [X] */
2302 {
2303 $$.reset();
2304 }
2305| EnclosedExpr
2306
2307EnclosedExpr: CURLY_LBRACE Expr CURLY_RBRACE /* [29] */
2308 {
2309 $$ = $2;
2310 }
2311
2312QueryBody: Expr /* [30] */
2313
2314/**
2315 * A pattern as found in for instance xsl:template/@match.
2316 *
2317 * @note When using this pattern, remember to set ParserContext::isParsingPattern.
2318 *
2319 * @see <a href="http://www.w3.org/TR/xslt20/#dt-pattern">XSL Transformations
2320 * (XSLT) Version 2.0, 5.5.2 Syntax of Patterns</a>
2321 */
2322Pattern: PathPattern /* [XSLT20-1] */
2323| Pattern BAR PathPattern
2324 {
2325 $$ = create(new CombineNodes($1, CombineNodes::Union, $3), @$, parseInfo);
2326 }
2327
2328PathPattern: RelativePathPattern /* [XSLT20-2] */
2329| SLASH
2330 {
2331 /* We write this into a node test. The spec says, 5.5.3 The Meaning of a Pattern:
2332 * "Similarly, / matches a document node, and only a document node,
2333 * because the result of the expression root(.)//(/) returns the root
2334 * node of the tree containing the context node if and only if it is a
2335 * document node." */
2336 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisSelf, BuiltinTypes::document), @$, parseInfo);
2337 }
2338| SLASH RelativePathPattern
2339 {
2340 /* /axis::node-test
2341 * =>
2342 * axis::node-test[parent::document-node()]
2343 *
2344 * In practice it looks like this. $2 is:
2345 *
2346 * TruthPredicate
2347 * AxisStep self::element(c)
2348 * TruthPredicate
2349 * AxisStep parent::element(b)
2350 * AxisStep parent::element(a)
2351 *
2352 * and we want this:
2353 *
2354 * TruthPredicate
2355 * AxisStep self::element(c)
2356 * TruthPredicate
2357 * AxisStep self::element(b)
2358 * TruthPredicate
2359 * AxisStep parent::element(a)
2360 * AxisStep parent::document()
2361 *
2362 * So we want to rewrite the predicate deepest down into a
2363 * another TruthPredicate containing the AxisStep.
2364 *
2365 * The simplest case where $2 is only an axis step is special. When $2 is:
2366 *
2367 * AxisStep self::element(a)
2368 *
2369 * we want:
2370 *
2371 * TruthPredicate
2372 * AxisStep self::element(a)
2373 * AxisStep parent::document()
2374 */
2375
2376 /* First, find the target. */
2377 Expression::Ptr target($2);
2378
2379 while(isPredicate(target->id()))
2380 {
2381 const Expression::Ptr candidate(target->operands().at(1));
2382
2383 if(isPredicate(candidate->id()))
2384 target = candidate;
2385 else
2386 break; /* target is now the last predicate. */
2387 }
2388
2389 if(target->is(Expression::IDAxisStep))
2390 {
2391 $$ = create(GenericPredicate::create($2, create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::document), @$, parseInfo),
2392 parseInfo->staticContext, fromYYLTYPE(@1, parseInfo)), @1, parseInfo);
2393 }
2394 else
2395 {
2396 const Expression::List targetOperands(target->operands());
2397 Expression::List newOps;
2398 newOps.append(targetOperands.at(0));
2399
2400 newOps.append(create(GenericPredicate::create(targetOperands.at(1),
2401 create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::document), @$, parseInfo),
2402 parseInfo->staticContext, fromYYLTYPE(@1, parseInfo)), @1, parseInfo));
2403
2404 target->setOperands(newOps);
2405 $$ = $2;
2406 }
2407 }
2408| SLASHSLASH RelativePathPattern
2409 {
2410 /* //axis::node-test
2411 * =>
2412 * axis::node-test[parent::node()]
2413 *
2414 * Spec says: "//para matches any para element that has a parent node."
2415 */
2416 $$ = create(GenericPredicate::create($2, create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::node), @$, parseInfo),
2417 parseInfo->staticContext, fromYYLTYPE(@1, parseInfo)), @1, parseInfo);
2418 }
2419| IdKeyPattern
2420| IdKeyPattern SLASH RelativePathPattern
2421 {
2422 createIdPatternPath($1, $3, QXmlNodeModelIndex::AxisParent, @2, parseInfo);
2423 }
2424| IdKeyPattern SLASHSLASH RelativePathPattern
2425 {
2426 createIdPatternPath($1, $3, QXmlNodeModelIndex::AxisAncestor, @2, parseInfo);
2427 }
2428
2429IdKeyPattern: FunctionCallExpr
2430 {
2431 const Expression::List ands($1->operands());
2432 const FunctionSignature::Ptr signature($1->as<FunctionCall>()->signature());
2433 const QXmlName name(signature->name());
2434 const QXmlName key(StandardNamespaces::fn, StandardLocalNames::key);
2435 const QXmlName id(StandardNamespaces::fn, StandardLocalNames::id);
2436
2437 if(name == id)
2438 {
2439 const Expression::ID id = ands.first()->id();
2440 if(!isVariableReference(id) && id != Expression::IDStringValue)
2441 {
2442 parseInfo->staticContext->error(QtXmlPatterns::tr("When function %1 is used for matching inside a pattern, "
2443 "the argument must be a variable reference or a string literal.")
2444 .arg(formatFunction(parseInfo->staticContext->namePool(), signature)),
2445 ReportContext::XPST0003,
2446 fromYYLTYPE(@$, parseInfo));
2447 }
2448 }
2449 else if(name == key)
2450 {
2451 if(ands.first()->id() != Expression::IDStringValue)
2452 {
2453 parseInfo->staticContext->error(QtXmlPatterns::tr("In an XSL-T pattern, the first argument to function %1 "
2454 "must be a string literal, when used for matching.")
2455 .arg(formatFunction(parseInfo->staticContext->namePool(), signature)),
2456 ReportContext::XPST0003,
2457 fromYYLTYPE(@$, parseInfo));
2458 }
2459
2460 const Expression::ID id2 = ands.at(1)->id();
2461 if(!isVariableReference(id2) &&
2462 id2 != Expression::IDStringValue &&
2463 id2 != Expression::IDIntegerValue &&
2464 id2 != Expression::IDBooleanValue &&
2465 id2 != Expression::IDFloat)
2466 {
2467 parseInfo->staticContext->error(QtXmlPatterns::tr("In an XSL-T pattern, the first argument to function %1 "
2468 "must be a literal or a variable reference, when used for matching.")
2469 .arg(formatFunction(parseInfo->staticContext->namePool(), signature)),
2470 ReportContext::XPST0003,
2471 fromYYLTYPE(@$, parseInfo));
2472 }
2473
2474 if(ands.count() == 3)
2475 {
2476 parseInfo->staticContext->error(QtXmlPatterns::tr("In an XSL-T pattern, function %1 cannot have a third argument.")
2477 .arg(formatFunction(parseInfo->staticContext->namePool(), signature)),
2478 ReportContext::XPST0003,
2479 fromYYLTYPE(@$, parseInfo));
2480 }
2481
2482 }
2483 else
2484 {
2485 const FunctionSignature::Hash signs(parseInfo->staticContext->functionSignatures()->functionSignatures());
2486 parseInfo->staticContext->error(QtXmlPatterns::tr("In an XSL-T pattern, only function %1 "
2487 "and %2, not %3, can be used for matching.")
2488 .arg(formatFunction(parseInfo->staticContext->namePool(), signs.value(id)),
2489 formatFunction(parseInfo->staticContext->namePool(), signs.value(key)),
2490 formatFunction(parseInfo->staticContext->namePool(), signature)),
2491 ReportContext::XPST0003,
2492 fromYYLTYPE(@$, parseInfo));
2493 }
2494
2495 $$ = $1;
2496 }
2497
2498RelativePathPattern: PatternStep /* [XSLT20-3] */
2499| RelativePathPattern SLASH PatternStep
2500 {
2501 $$ = createPatternPath($1, $3, QXmlNodeModelIndex::AxisParent, @2, parseInfo);
2502 }
2503| RelativePathPattern SLASHSLASH PatternStep
2504 {
2505 $$ = createPatternPath($1, $3, QXmlNodeModelIndex::AxisAncestor, @2, parseInfo);
2506 }
2507
2508PatternStep: FilteredAxisStep
2509 {
2510 const Expression::Ptr expr(findAxisStep($1));
2511
2512 const QXmlNodeModelIndex::Axis axis = expr->as<AxisStep>()->axis();
2513 AxisStep *const axisStep = expr->as<AxisStep>();
2514
2515 /* Here we constrain the possible axes, and we rewrite the axes as according
2516 * to 5.5.3 The Meaning of a Pattern.
2517 *
2518 * However, we also rewrite axis child and attribute to axis self. The
2519 * reason for this is that if we don't, we will match the children of
2520 * the context node, instead of the context node itself. The formal
2521 * definition of a pattern, root(.)//EE is insensitive to context,
2522 * while the way we implement pattern, "the other way of seeing it",
2523 * e.g from right to left, are very much. */
2524
2525 if(axisStep->nodeTest() == BuiltinTypes::document
2526 || axis == QXmlNodeModelIndex::AxisChild)
2527 axisStep->setAxis(QXmlNodeModelIndex::AxisSelf);
2528 else if(axis == QXmlNodeModelIndex::AxisAttribute)
2529 {
2530 axisStep->setAxis(QXmlNodeModelIndex::AxisSelf);
2531 /* Consider that the user write attribute::node(). This is
2532 * semantically equivalent to attribute::attribute(), but since we have changed
2533 * the axis to axis self, we also need to change the node test, such that we
2534 * have self::attribute(). */
2535 if(*axisStep->nodeTest() == *BuiltinTypes::node)
2536 axisStep->setNodeTest(BuiltinTypes::attribute);
2537 }
2538 else
2539 {
2540 parseInfo->staticContext->error(QtXmlPatterns::tr("In an XSL-T pattern, axis %1 cannot be used, "
2541 "only axis %2 or %3 can.")
2542 .arg(formatKeyword(AxisStep::axisName(axis)),
2543 formatKeyword(AxisStep::axisName(QXmlNodeModelIndex::AxisChild)),
2544 formatKeyword(AxisStep::axisName(QXmlNodeModelIndex::AxisAttribute))),
2545 ReportContext::XPST0003,
2546 fromYYLTYPE(@$, parseInfo));
2547 }
2548
2549 $$ = $1;
2550 }
2551
2552Expr: ExprSingle /* [31] */
2553| ExpressionSequence
2554 {
2555 $$ = create(new ExpressionSequence($1), @$, parseInfo);
2556 }
2557
2558ExpressionSequence: ExprSingle COMMA ExprSingle /* [X] */
2559 {
2560 Expression::List l;
2561 l.append($1);
2562 l.append($3);
2563 $$ = l;
2564 }
2565| ExpressionSequence COMMA ExprSingle
2566 {
2567 $1.append($3);
2568 $$ = $1;
2569 }
2570
2571ExprSingle: OrExpr /* [32] */
2572| FLWORExpr
2573| QuantifiedExpr
2574| TypeswitchExpr
2575| IfExpr
2576| AVT LPAREN AttrValueContent RPAREN
2577 {
2578 $$ = createDirAttributeValue($3, parseInfo, @$);
2579 }
2580
2581OptionalModes: /* Empty. */ /* [X] */
2582 {
2583 QVector<QXmlName> result;
2584 result.append(QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default));
2585 $$ = result;
2586 }
2587| MODE Modes
2588 {
2589 $$ = $2;
2590 }
2591
2592OptionalMode: /* Empty. */ /* [X] */
2593 {
2594 $$ = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default);
2595 }
2596| MODE Mode
2597 {
2598 $$ = $2;
2599 }
2600
2601Modes: Mode
2602 {
2603 QVector<QXmlName> result;
2604 result.append($1);
2605 $$ = result;
2606 }
2607| Modes COMMA Mode
2608 {
2609 $1.append($3);
2610 $$ = $1;
2611 }
2612
2613Mode: QName /* [X] */
2614 {
2615 $$ = $1;
2616 }
2617| NCNAME
2618 {
2619 if($1 == QLatin1String("#current"))
2620 $$ = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current);
2621 else if($1 == QLatin1String("#default"))
2622 $$ = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default);
2623 else if($1 == QLatin1String("#all"))
2624 $$ = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::all);
2625 else
2626 {
2627 const ReflectYYLTYPE ryy(@$, parseInfo);
2628
2629 if(!QXmlUtils::isNCName($1))
2630 {
2631 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is an invalid template mode name.")
2632 .arg(formatKeyword($1)),
2633 ReportContext::XTSE0550,
2634 fromYYLTYPE(@$, parseInfo));
2635 }
2636
2637 $$ = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::empty, $1);
2638 }
2639 }
2640
2641
2642FLWORExpr: ForClause /* [33] */
2643| LetClause
2644
2645ForClause: FOR DOLLAR VarName TypeDeclaration
2646 PositionalVar IN ExprSingle
2647 {
2648 /* We're pushing the range variable here, not the positional. */
2649 $<expr>$ = pushVariable($3, quantificationType($4), $7, VariableDeclaration::RangeVariable, @$, parseInfo);
2650 }
2651 {
2652 /* It is ok this appears after PositionalVar, because currentRangeSlot()
2653 * uses a different "channel" than currentPositionSlot(), so they can't trash
2654 * each other. */
2655 $<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();
2656 }
2657 ForTail /* [34] */
2658 {
2659 Q_ASSERT($7);
2660 Q_ASSERT($10);
2661
2662 /* We want the next last pushed variable, since we push the range variable after the
2663 * positional variable. */
2664 if($5 != -1 && parseInfo->variables.at(parseInfo->variables.count() -2)->name == $3)
2665 {
2666 /* Ok, a positional variable is used since its slot is not -1, and its name is equal
2667 * to our range variable. This is an error. */
2668 parseInfo->staticContext->error(QtXmlPatterns::tr("The name of a variable bound in a for-expression must be different "
2669 "from the positional variable. Hence, the two variables named %1 collide.")
2670 .arg(formatKeyword(parseInfo->staticContext->namePool(), $3)),
2671 ReportContext::XQST0089,
2672 fromYYLTYPE(@$, parseInfo));
2673
2674 }
2675
2676 const Expression::Ptr retBody(create(new ForClause($<enums.slot>9, $<expr>8, $10, $5), @$, parseInfo));
2677 ReturnOrderBy *const rob = locateReturnClause($10);
2678
2679 if(rob)
2680 $$ = create(new OrderBy(rob->stability(), rob->orderSpecs(), retBody, rob), @$, parseInfo);
2681 else
2682 $$ = retBody;
2683
2684 parseInfo->finalizePushedVariable();
2685
2686 if($5 != -1) /* We also have a positional variable to remove from the scope. */
2687 parseInfo->finalizePushedVariable();
2688 }
2689
2690ForTail: COMMA DOLLAR VarName TypeDeclaration
2691 PositionalVar IN ExprSingle
2692 {
2693 pushVariable($3, quantificationType($4), $7, VariableDeclaration::RangeVariable, @$, parseInfo);
2694 }
2695 {
2696 /* It is ok this appears after PositionalVar, because currentRangeSlot()
2697 * uses a different "channel" than currentPositionSlot(), so they can't trash
2698 * each other. */
2699 $<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();
2700 }
2701 ForTail /* [X] */
2702 {
2703 $$ = create(new ForClause($<enums.slot>9, $<expr>7, $10, $5), @$, parseInfo);
2704
2705 parseInfo->finalizePushedVariable();
2706
2707 if($5 != -1) /* We also have a positional variable to remove from the scope. */
2708 parseInfo->finalizePushedVariable();
2709 }
2710
2711| WhereClause
2712| ForClause
2713| LetClause
2714
2715PositionalVar: /* empty */ /* [35] */
2716 {
2717 $$ = -1;
2718 }
2719
2720| AT DOLLAR VarName
2721 {
2722 pushVariable($3, CommonSequenceTypes::ExactlyOneInteger, Expression::Ptr(),
2723 VariableDeclaration::PositionalVariable, @$, parseInfo);
2724 $$ = parseInfo->currentPositionSlot();
2725 }
2726
2727LetClause: LET IsInternal DOLLAR VarName TypeDeclaration ASSIGN ExprSingle
2728 {
2729 $<expr>$ = pushVariable($4, quantificationType($5), $7, VariableDeclaration::ExpressionVariable, @$, parseInfo);
2730 }
2731 LetTail /* [36] */
2732 {
2733 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
2734
2735 Q_ASSERT(parseInfo->variables.top()->name == $4);
2736 $$ = create(new LetClause($<expr>8, $9, parseInfo->variables.top()), @$, parseInfo);
2737 parseInfo->finalizePushedVariable();
2738 }
2739
2740LetTail: COMMA DOLLAR VarName TypeDeclaration ASSIGN ExprSingle
2741 { $<expr>$ = pushVariable($3, quantificationType($4), $6, VariableDeclaration::ExpressionVariable, @$, parseInfo);}
2742 LetTail /* [X] */
2743 {
2744 Q_ASSERT(parseInfo->variables.top()->name == $3);
2745 $$ = create(new LetClause($<expr>7, $8, parseInfo->variables.top()), @$, parseInfo);
2746 parseInfo->finalizePushedVariable();
2747 }
2748
2749| WhereClause
2750| ForClause
2751| LetClause
2752
2753WhereClause: OrderByClause RETURN ExprSingle /* [37] */
2754 {
2755 if($1.isEmpty())
2756 $$ = $3;
2757 else
2758 $$ = createReturnOrderBy($1, $3, parseInfo->orderStability.pop(), @$, parseInfo);
2759 }
2760
2761| WHERE ExprSingle OrderByClause RETURN ExprSingle
2762 {
2763 if($3.isEmpty())
2764 $$ = create(new IfThenClause($2, $5, create(new EmptySequence, @$, parseInfo)), @$, parseInfo);
2765 else
2766 $$ = create(new IfThenClause($2, createReturnOrderBy($3, $5, parseInfo->orderStability.pop(), @$, parseInfo),
2767 create(new EmptySequence, @$, parseInfo)),
2768 @$, parseInfo);
2769 }
2770
2771OrderByClause: /* Empty. */ /* [38] */
2772 {
2773 $$ = OrderSpecTransfer::List();
2774 }
2775| MandatoryOrderByClause
2776
2777MandatoryOrderByClause: OrderByInputOrder OrderSpecList
2778 {
2779 $$ = $2;
2780 }
2781
2782OrderSpecList: OrderSpecList COMMA OrderSpec /* [39] */
2783 {
2784 OrderSpecTransfer::List list;
2785 list += $1;
2786 list.append($3);
2787 $$ = list;
2788 }
2789| OrderSpec
2790 {
2791 OrderSpecTransfer::List list;
2792 list.append($1);
2793 $$ = list;
2794 }
2795
2796OrderSpec: ExprSingle DirectionModifier EmptynessModifier CollationModifier /* [40] */
2797 {
2798 $$ = OrderSpecTransfer($1, OrderBy::OrderSpec($2, $3));
2799 }
2800
2801DirectionModifier: /* Empty. */ /* [X] */
2802 {
2803 /* Where does the specification state the default value is ascending?
2804 *
2805 * It is implicit, in the first enumerated list in 3.8.3 Order By and Return Clauses:
2806 *
2807 * "If T1 and T2 are two tuples in the tuple stream, and V1 and V2 are the first pair
2808 * of values encountered when evaluating their orderspecs from left to right for
2809 * which one value is greater-than the other (as defined above), then:
2810 *
2811 * 1. If V1 is greater-than V2: If the orderspec specifies descending,
2812 * then T1 precedes T2 in the tuple stream; otherwise, T2 precedes T1 in the tuple stream.
2813 * 2. If V2 is greater-than V1: If the orderspec specifies descending,
2814 * then T2 precedes T1 in the tuple stream; otherwise, T1 precedes T2 in the tuple stream."
2815 *
2816 * which means that if you don't specify anything, or you
2817 * specify ascending, you get the same result.
2818 */
2819 $$ = OrderBy::OrderSpec::Ascending;
2820 }
2821
2822| ASCENDING
2823 {
2824 $$ = OrderBy::OrderSpec::Ascending;
2825 }
2826
2827| DESCENDING
2828 {
2829 $$ = OrderBy::OrderSpec::Descending;
2830 }
2831
2832EmptynessModifier: /* Empty. */ /* [X] */
2833 {
2834 $$ = parseInfo->staticContext->orderingEmptySequence();
2835 }
2836| OrderingEmptySequence
2837
2838CollationModifier: /* Empty. */ /* [X] */
2839| COLLATION URILiteral
2840 {
2841 if(parseInfo->isXSLT())
2842 resolveAndCheckCollation<ReportContext::XTDE1035>($2, parseInfo, @$);
2843 else
2844 resolveAndCheckCollation<ReportContext::XQST0076>($2, parseInfo, @$);
2845 }
2846| INTERNAL COLLATION ExprSingle
2847 {
2848 /* We do nothing. We don't use collations, and we have this non-terminal
2849 * in order to accept expressions. */
2850 }
2851
2852OrderByInputOrder: STABLE ORDER BY /* [X] */
2853 {
2854 parseInfo->orderStability.push(OrderBy::StableOrder);
2855 }
2856| ORDER BY
2857 {
2858 parseInfo->orderStability.push(OrderBy::UnstableOrder);
2859 }
2860
2861QuantifiedExpr: SomeQuantificationExpr /* [42] */
2862| EveryQuantificationExpr
2863
2864SomeQuantificationExpr: SOME DOLLAR VarName TypeDeclaration IN ExprSingle
2865 {
2866 pushVariable($3, quantificationType($4), $6,
2867 VariableDeclaration::RangeVariable, @$, parseInfo);
2868 }
2869 {$<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();}
2870 SomeQuantificationTail /* [X] */
2871 {
2872 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
2873 $$ = create(new QuantifiedExpression($<enums.slot>8,
2874 QuantifiedExpression::Some, $<expr>6, $9), @$, parseInfo);
2875 parseInfo->finalizePushedVariable();
2876 }
2877
2878SomeQuantificationTail: COMMA DOLLAR VarName TypeDeclaration IN ExprSingle
2879 {
2880 $<expr>$ = pushVariable($3, quantificationType($4), $6,
2881 VariableDeclaration::RangeVariable, @$, parseInfo);
2882 }
2883 {$<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();}
2884 SomeQuantificationTail /* [X] */
2885 {
2886 $$ = create(new QuantifiedExpression($<enums.slot>8,
2887 QuantifiedExpression::Some, $<expr>7, $9), @$, parseInfo);
2888 parseInfo->finalizePushedVariable();
2889 }
2890
2891| SatisfiesClause
2892
2893EveryQuantificationExpr: EVERY DOLLAR VarName TypeDeclaration IN ExprSingle
2894 {
2895 pushVariable($3, quantificationType($4), $6,
2896 VariableDeclaration::RangeVariable, @$, parseInfo);
2897 }
2898 {$<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();}
2899 EveryQuantificationTail /* [X] */
2900 {
2901 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
2902 $$ = create(new QuantifiedExpression($<enums.slot>8,
2903 QuantifiedExpression::Every, $<expr>6, $9), @$, parseInfo);
2904 parseInfo->finalizePushedVariable();
2905 }
2906
2907EveryQuantificationTail: COMMA DOLLAR VarName TypeDeclaration IN ExprSingle
2908 {
2909 $<expr>$ = pushVariable($3, quantificationType($4), $6,
2910 VariableDeclaration::RangeVariable, @$, parseInfo);
2911 }
2912 {$<enums.slot>$ = parseInfo->staticContext->currentRangeSlot();}
2913 EveryQuantificationTail /* [X] */
2914 {
2915 $$ = create(new QuantifiedExpression($<enums.slot>8,
2916 QuantifiedExpression::Every, $<expr>7, $9), @$, parseInfo);
2917 parseInfo->finalizePushedVariable();
2918 }
2919
2920| SatisfiesClause
2921
2922SatisfiesClause: SATISFIES ExprSingle /* [X] */
2923 {
2924 $$ = $2;
2925 }
2926
2927/*
2928 * Typeswitches are re-written to a combination between @c if clauses, <tt>instance of</tt>, and
2929 * @c let bindings. For example, the query:
2930 *
2931 * @code
2932 * typeswitch(input)
2933 * case element() return <!-- a comment -->
2934 * case $i as attribute(name) return name($i)
2935 * default return "Didn't match"
2936 * @endcode
2937 *
2938 * becomes:
2939 *
2940 * @code
2941 * if(input instance of element())
2942 * then <!-- a comment -->
2943 * else if(input instance of attribute(name))
2944 * then let $i as attribute(name) := input return name($i)
2945 * else "Didn't match"
2946 * @endcode
2947 */
2948
2949TypeswitchExpr: TYPESWITCH LPAREN Expr RPAREN
2950 {
2951 parseInfo->typeswitchSource.push($3);
2952 }
2953 CaseClause /* [43] */
2954 {
2955 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
2956 parseInfo->typeswitchSource.pop();
2957 $$ = $6;
2958 }
2959
2960CaseClause: CASE CaseVariable SequenceType /* [44] */
2961 {
2962 if(!$2.isNull())
2963 {
2964 pushVariable($2, $3, parseInfo->typeswitchSource.top(),
2965 VariableDeclaration::ExpressionVariable, @$, parseInfo, false);
2966 }
2967 }
2968 RETURN ExprSingle
2969 {
2970 /* The variable shouldn't be in-scope for other case branches. */
2971 if(!$2.isNull())
2972 parseInfo->finalizePushedVariable();
2973 }
2974 CaseTail
2975 {
2976 const Expression::Ptr instanceOf(create(new InstanceOf(parseInfo->typeswitchSource.top(), $3), @$, parseInfo));
2977 $$ = create(new IfThenClause(instanceOf, $6, $8), @$, parseInfo);
2978 }
2979
2980CaseTail: CaseClause /* [X] */
2981| CaseDefault
2982
2983CaseVariable: /* Empty. */ /* [X] */
2984 {
2985 $$ = QXmlName();
2986 }
2987
2988| DOLLAR ElementName AS
2989 {
2990 $$ = $2;
2991 }
2992
2993CaseDefault: DEFAULT RETURN ExprSingle /* [X] */
2994 {
2995 $$ = $3;
2996 }
2997| DEFAULT DOLLAR ElementName
2998 {
2999 if(!$3.isNull())
3000 {
3001 pushVariable($3, parseInfo->typeswitchSource.top()->staticType(),
3002 parseInfo->typeswitchSource.top(),
3003 VariableDeclaration::ExpressionVariable, @$, parseInfo, false);
3004 }
3005 }
3006 RETURN ExprSingle
3007 {
3008 if(!$3.isNull())
3009 parseInfo->finalizePushedVariable();
3010 $$ = $6;
3011 }
3012
3013IfExpr: IF LPAREN Expr RPAREN THEN ExprSingle ELSE ExprSingle /* [45] */
3014 {
3015 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3016 $$ = create(new IfThenClause($3, $6, $8), @$, parseInfo);
3017 }
3018
3019OrExpr: AndExpr /* [46] */
3020| OrExpr OR AndExpr
3021 {
3022 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3023 $$ = create(new OrExpression($1, $3), @$, parseInfo);
3024 }
3025
3026AndExpr: ComparisonExpr /* [47] */
3027| AndExpr AND ComparisonExpr
3028 {
3029 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3030 $$ = create(new AndExpression($1, $3), @$, parseInfo);
3031 }
3032
3033ComparisonExpr: RangeExpr /* [48] */
3034| ValueComp
3035| GeneralComp
3036| NodeComp
3037
3038RangeExpr: AdditiveExpr /* [49] */
3039| AdditiveExpr TO AdditiveExpr
3040 {
3041 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3042 $$ = create(new RangeExpression($1, $3), @$, parseInfo);
3043 }
3044
3045AdditiveExpr: MultiplicativeExpr /* [50] */
3046| AdditiveExpr AdditiveOperator MultiplicativeExpr
3047 {
3048 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3049 $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo);
3050 }
3051
3052AdditiveOperator: PLUS {$$ = AtomicMathematician::Add;} /* [X] */
3053| MINUS {$$ = AtomicMathematician::Substract;}
3054
3055MultiplicativeExpr: UnionExpr /* [51] */
3056| MultiplicativeExpr MultiplyOperator UnionExpr
3057 {
3058 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3059 $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo);
3060 }
3061
3062MultiplyOperator: STAR {$$ = AtomicMathematician::Multiply;} /* [X] */
3063| DIV {$$ = AtomicMathematician::Div;}
3064| IDIV {$$ = AtomicMathematician::IDiv;}
3065| MOD {$$ = AtomicMathematician::Mod;}
3066
3067UnionExpr: IntersectExceptExpr /* [52] */
3068| UnionExpr UnionOperator IntersectExceptExpr
3069 {
3070 allowedIn(QueryLanguages(QXmlQuery::XQuery10
3071 | QXmlQuery::XPath20
3072 | QXmlQuery::XmlSchema11IdentityConstraintField
3073 | QXmlQuery::XmlSchema11IdentityConstraintSelector),
3074 parseInfo, @$);
3075 $$ = create(new CombineNodes($1, CombineNodes::Union, $3), @$, parseInfo);
3076 }
3077
3078IntersectExceptExpr: InstanceOfExpr /* [53] */
3079| IntersectExceptExpr IntersectOperator InstanceOfExpr
3080 {
3081 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3082 $$ = create(new CombineNodes($1, $2, $3), @$, parseInfo);
3083 }
3084
3085UnionOperator: UNION /* [X] */
3086| BAR
3087
3088IntersectOperator: INTERSECT /* [X] */
3089 {
3090 $$ = CombineNodes::Intersect;
3091 }
3092| EXCEPT
3093 {
3094 $$ = CombineNodes::Except;
3095 }
3096
3097InstanceOfExpr: TreatExpr /* [54] */
3098| TreatExpr INSTANCE OF SequenceType
3099 {
3100 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3101 $$ = create(new InstanceOf($1,
3102 SequenceType::Ptr($4)), @$, parseInfo);
3103 }
3104
3105TreatExpr: CastableExpr /* [55] */
3106| CastableExpr TREAT AS SequenceType
3107 {
3108 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3109 $$ = create(new TreatAs($1, $4), @$, parseInfo);
3110 }
3111
3112CastableExpr: CastExpr /* [56] */
3113| CastExpr CASTABLE AS SingleType
3114 {
3115 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3116 $$ = create(new CastableAs($1, $4), @$, parseInfo);
3117 }
3118
3119CastExpr: UnaryExpr /* [57] */
3120| UnaryExpr CAST AS SingleType
3121 {
3122 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3123 $$ = create(new CastAs($1, $4), @$, parseInfo);
3124 }
3125
3126UnaryExpr: ValueExpr /* [58] */
3127| UnaryOperator UnaryExpr
3128 {
3129 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3130 $$ = create(new UnaryExpression($1, $2, parseInfo->staticContext), @$, parseInfo);
3131 }
3132
3133UnaryOperator: PLUS /* [X] */
3134 {
3135 $$ = AtomicMathematician::Add;
3136 }
3137| MINUS
3138 {
3139 $$ = AtomicMathematician::Substract;
3140 }
3141
3142ValueExpr: ValidateExpr /* [59] */
3143| PathExpr
3144| ExtensionExpr
3145
3146GeneralComp: RangeExpr GeneralComparisonOperator RangeExpr /* [60] */
3147 {
3148 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3149 $$ = create(new GeneralComparison($1, $2, $3, parseInfo->isBackwardsCompat.top()), @$, parseInfo);
3150 }
3151
3152GeneralComparisonOperator: G_EQ {$$ = AtomicComparator::OperatorEqual;} /* [X] */
3153| G_NE {$$ = AtomicComparator::OperatorNotEqual;}
3154| G_GE {$$ = AtomicComparator::OperatorGreaterOrEqual;}
3155| G_GT {$$ = AtomicComparator::OperatorGreaterThan;}
3156| G_LE {$$ = AtomicComparator::OperatorLessOrEqual;}
3157| G_LT {$$ = AtomicComparator::OperatorLessThan;}
3158
3159ValueComp: RangeExpr ValueComparisonOperator RangeExpr /* [61] */
3160 {
3161 $$ = create(new ValueComparison($1, $2, $3), @$, parseInfo);
3162 }
3163
3164ValueComparisonOperator: EQ {$$ = AtomicComparator::OperatorEqual;}
3165| NE {$$ = AtomicComparator::OperatorNotEqual;}
3166| GE {$$ = AtomicComparator::OperatorGreaterOrEqual;}
3167| GT {$$ = AtomicComparator::OperatorGreaterThan;}
3168| LE {$$ = AtomicComparator::OperatorLessOrEqual;}
3169| LT {$$ = AtomicComparator::OperatorLessThan;}
3170
3171NodeComp: RangeExpr NodeOperator RangeExpr /* [62] */
3172 {
3173 $$ = create(new NodeComparison($1, $2, $3), @$, parseInfo);
3174 }
3175
3176NodeOperator: IS {$$ = QXmlNodeModelIndex::Is;} /* [X] */
3177| PRECEDES {$$ = QXmlNodeModelIndex::Precedes;}
3178| FOLLOWS {$$ = QXmlNodeModelIndex::Follows;}
3179
3180ValidateExpr: ValidationMode EnclosedExpr /* [63] */
3181 {
3182 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
3183 parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Validation Feature is not supported. "
3184 "Hence, %1-expressions may not be used.")
3185 .arg(formatKeyword("validate")),
3186 ReportContext::XQST0075, fromYYLTYPE(@$, parseInfo));
3187 /*
3188 $$ = Validate::create($2, $1, parseInfo->staticContext);
3189 */
3190 }
3191
3192/* "A validate expression may optionally specify a validation mode. The
3193 default validation mode is strict." */
3194ValidationMode: VALIDATE {$$ = Validate::Strict;} /* [64] */
3195| VALIDATE STRICT {$$ = Validate::Strict;}
3196| VALIDATE LAX {$$ = Validate::Lax;}
3197
3198ExtensionExpr: Pragmas EnclosedOptionalExpr /* [65] */
3199 {
3200 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
3201 /* We don't support any pragmas, so we only do the
3202 * necessary validation and use the fallback expression. */
3203
3204 if($2)
3205 $$ = $2;
3206 else
3207 {
3208 parseInfo->staticContext->error(QtXmlPatterns::tr("None of the pragma expressions are supported. "
3209 "Therefore, a fallback expression "
3210 "must be present"),
3211 ReportContext::XQST0079, fromYYLTYPE(@$, parseInfo));
3212 }
3213 }
3214
3215EnclosedOptionalExpr: CURLY_LBRACE /* empty */ CURLY_RBRACE /* [X] */
3216 {
3217 $$.reset();
3218 }
3219| CURLY_LBRACE Expr CURLY_RBRACE
3220 {
3221 $$ = $2;
3222 }
3223
3224Pragmas: Pragmas Pragma /* [X] */
3225| Pragma
3226
3227Pragma: PRAGMA_START PragmaName PragmaContents PRAGMA_END /* [66] */
3228 {
3229 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
3230 }
3231
3232PragmaContents: /* empty */ /* [67] */
3233| StringLiteral
3234
3235PathExpr: SLASH RelativePathExpr /* [68] */
3236 {
3237 /* This is "/step". That is, fn:root(self::node()) treat as document-node()/RelativePathExpr. */
3238 $$ = create(new Path(createRootExpression(parseInfo, @$), $2), @$, parseInfo);
3239 }
3240
3241| SLASHSLASH RelativePathExpr
3242 {
3243 $$ = createSlashSlashPath(createRootExpression(parseInfo, @$), $2, @$, parseInfo);
3244 }
3245| SLASH
3246 {
3247 /* This is "/". That is, fn:root(self::node()) treat as document-node(). */
3248 $$ = createRootExpression(parseInfo, @$);
3249 }
3250
3251| RelativePathExpr
3252 /* This is "step", simply. We let bison generate "$$ = $1". */
3253
3254RelativePathExpr: StepExpr /* [69] */
3255| RelativePathExpr MapOrSlash StepExpr
3256 {
3257 $$ = create(new Path($1, $3, $2), @$, parseInfo);
3258 }
3259| RelativePathExpr MapOrSlash SORT MandatoryOrderByClause RETURN StepExpr END_SORT
3260 {
3261 const Expression::Ptr orderBy(createReturnOrderBy($4, $6, parseInfo->orderStability.pop(), @$, parseInfo));
3262
3263 ReturnOrderBy *const rob = orderBy->as<ReturnOrderBy>();
3264 const Expression::Ptr path(create(new Path($1, orderBy, $2), @$, parseInfo));
3265
3266 $$ = create(new OrderBy(rob->stability(), rob->orderSpecs(), path, rob), @$, parseInfo);
3267 }
3268| RelativePathExpr SLASHSLASH StepExpr
3269 {
3270 $$ = createSlashSlashPath($1, $3, @$, parseInfo);
3271 }
3272
3273StepExpr: FilteredAxisStep /* [70] */
3274 {
3275 $$ = NodeSortExpression::wrapAround($1, parseInfo->staticContext);
3276 }
3277| FilterExpr
3278| CURRENT EnclosedExpr
3279 {
3280 $$ = create(new CurrentItemStore($2), @$, parseInfo);
3281 }
3282| XSLT_VERSION
3283 {
3284 const xsDouble version = $1.toDouble();
3285
3286 parseInfo->isBackwardsCompat.push(version != 2);
3287
3288 $<enums.Double>$ = version;
3289 }
3290 EnclosedExpr
3291 {
3292 if($<enums.Double>2 < 2)
3293 $$ = createCompatStore($3, @$, parseInfo);
3294 else
3295 $$ = $3;
3296 }
3297| BASEURI StringLiteral CURLY_LBRACE Expr CURLY_RBRACE /* [X] */
3298{
3299 allowedIn(QXmlQuery::XSLT20, parseInfo, @$);
3300 Q_ASSERT(!$2.isEmpty());
3301 $$ = create(new StaticBaseURIStore($2, $4), @$, parseInfo);
3302}
3303
3304| DECLARE NAMESPACE NCNAME G_EQ STRING_LITERAL CURLY_LBRACE /* [X] */
3305 {
3306 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$);
3307 parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings());
3308 const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings()));
3309 resolver->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace($5),
3310 StandardLocalNames::empty,
3311 parseInfo->staticContext->namePool()->allocatePrefix($3)));
3312 parseInfo->staticContext->setNamespaceBindings(resolver);
3313 }
3314 Expr
3315 CURLY_RBRACE
3316 {
3317 parseInfo->staticContext->setNamespaceBindings(parseInfo->resolvers.pop());
3318 $$ = $8;
3319 }
3320| CALL_TEMPLATE ElementName LPAREN TemplateWithParameters RPAREN
3321 {
3322 $$ = create(new CallTemplate($2, parseInfo->templateWithParams), @$, parseInfo);
3323 parseInfo->templateWithParametersHandled();
3324 parseInfo->templateCalls.append($$);
3325 }
3326
3327TemplateWithParameters:
3328 {
3329 parseInfo->startParsingWithParam();
3330 }
3331 TemplateParameters
3332 {
3333 parseInfo->endParsingWithParam();
3334 }
3335
3336TemplateParameters: /* Empty. */ /* [X] */
3337 {
3338 }
3339| TemplateParameter
3340 {
3341 }
3342| TemplateParameters COMMA TemplateParameter
3343 {
3344 }
3345
3346OptionalTemplateParameters: /* Empty. */ /* [X] */
3347 {
3348 }
3349| LPAREN TemplateParameters RPAREN
3350 {
3351 }
3352
3353TemplateParameter: IsTunnel DOLLAR VarName TypeDeclaration OptionalAssign
3354 {
3355 /* Note, this grammar rule is invoked for @c xsl:param @em and @c
3356 * xsl:with-param. */
3357 const bool isParsingWithParam = parseInfo->isParsingWithParam();
3358
3359 /**
3360 * @c xsl:param doesn't make life easy:
3361 *
3362 * If it only has @c name, it's default value is an empty
3363 * string(hence has type @c xs:string), but the value that
3364 * (maybe) is supplied can be anything, typically a node.
3365 *
3366 * Therefore, for that very common case we can't rely on
3367 * the Expression's type, but have to force it to item()*.
3368 *
3369 * So if we're supplied the type item()*, we pass a null
3370 * SequenceType. TemplateParameterReference recognizes this
3371 * and has item()* as its static type, regardless of if the
3372 * expression has a more specific type.
3373 */
3374 SequenceType::Ptr type;
3375
3376 if(!$4->is(CommonSequenceTypes::ZeroOrMoreItems))
3377 type = $4;
3378
3379 Expression::Ptr expr;
3380
3381 /* The default value is an empty sequence. */
3382 if(!$5 && ((type && $4->cardinality().allowsEmpty())
3383 || isParsingWithParam))
3384 expr = create(new EmptySequence, @$, parseInfo);
3385 else
3386 expr = $5;
3387
3388 /* We ensure we have some type, so CallTemplate, Template and friends
3389 * are happy. */
3390 if(!isParsingWithParam && !type)
3391 type = CommonSequenceTypes::ZeroOrMoreItems;
3392
3393 if($1)
3394 /* TODO, handle tunnel parameters. */;
3395 else
3396 {
3397 if((!isParsingWithParam && VariableDeclaration::contains(parseInfo->templateParameters, $3)) ||
3398 (isParsingWithParam && parseInfo->templateWithParams.contains($3)))
3399 {
3400 parseInfo->staticContext->error(QtXmlPatterns::tr("Each name of a template parameter must be unique; %1 is duplicated.")
3401 .arg(formatKeyword(parseInfo->staticContext->namePool(), $3)),
3402 isParsingWithParam ? ReportContext::XTSE0670 : ReportContext::XTSE0580, fromYYLTYPE(@$, parseInfo));
3403 }
3404 else
3405 {
3406 if(isParsingWithParam)
3407 parseInfo->templateWithParams[$3] = WithParam::Ptr(new WithParam($3, $4, expr));
3408 else
3409 {
3410 Q_ASSERT(type);
3411 pushVariable($3, type, expr, VariableDeclaration::TemplateParameter, @$, parseInfo);
3412 parseInfo->templateParameters.append(parseInfo->variables.top());
3413 }
3414 }
3415 }
3416 }
3417
3418IsTunnel: /* Empty. */
3419 {
3420 $$ = false;
3421 }
3422| TUNNEL
3423 {
3424 $$ = true;
3425 }
3426
3427OptionalAssign: /* Empty. */ /* [X] */
3428 {
3429 $$ = Expression::Ptr();
3430 }
3431| ASSIGN ExprSingle
3432 {
3433 $$ = $2;
3434 }
3435
3436/**
3437 * Controls whethers a path expression should sort its result. Used for
3438 * implementing XSL-T's for-each.
3439 */
3440MapOrSlash: SLASH /* [X] */
3441 {
3442 $$ = Path::RegularPath;
3443 }
3444| MAP
3445 {
3446 $$ = Path::XSLTForEach;
3447 }
3448| FOR_APPLY_TEMPLATE
3449 {
3450 $$ = Path::ForApplyTemplate;
3451 }
3452
3453FilteredAxisStep: AxisStep /* [X] */
3454| FilteredAxisStep LBRACKET Expr RBRACKET
3455 {
3456 $$ = create(GenericPredicate::create($1, $3, parseInfo->staticContext, fromYYLTYPE(@$, parseInfo)), @$, parseInfo);
3457 }
3458
3459AxisStep: ForwardStep /* [71] */
3460| ReverseStep
3461
3462ForwardStep: Axis
3463 {
3464 if($1 == QXmlNodeModelIndex::AxisAttribute)
3465 parseInfo->nodeTestSource = BuiltinTypes::attribute;
3466 }
3467 NodeTestInAxisStep /* [72] */
3468 {
3469 if($3)
3470 {
3471 /* A node test was explicitly specified. The un-abbreviated syntax was used. */
3472 $$ = create(new AxisStep($1, $3), @$, parseInfo);
3473 }
3474 else
3475 {
3476 /* Quote from 3.2.1.1 Axes
3477 *
3478 * [Definition: Every axis has a principal node kind. If an axis
3479 * can contain elements, then the principal node kind is element;
3480 * otherwise, it is the kind of nodes that the axis can contain.] Thus:
3481 * - For the attribute axis, the principal node kind is attribute.
3482 * - For all other axes, the principal node kind is element. */
3483
3484 if($1 == QXmlNodeModelIndex::AxisAttribute)
3485 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, BuiltinTypes::attribute), @$, parseInfo);
3486 else
3487 $$ = create(new AxisStep($1, BuiltinTypes::element), @$, parseInfo);
3488 }
3489
3490 parseInfo->restoreNodeTestSource();
3491 }
3492| AbbrevForwardStep
3493
3494NodeTestInAxisStep: NodeTest
3495| AnyAttributeTest
3496
3497Axis: AxisToken COLONCOLON /* [73] */
3498 {
3499 if($1 == QXmlNodeModelIndex::AxisNamespace)
3500 {
3501 /* We don't raise XPST0010 here because the namespace axis isn't an optional
3502 * axis. It simply is not part of the XQuery grammar. */
3503 parseInfo->staticContext->error(QtXmlPatterns::tr("The %1-axis is unsupported in XQuery")
3504 .arg(formatKeyword("namespace")),
3505 ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
3506 }
3507 else
3508 $$ = $1;
3509
3510 switch($1)
3511 {
3512 case QXmlNodeModelIndex::AxisAttribute:
3513 {
3514 allowedIn(QueryLanguages( QXmlQuery::XPath20
3515 | QXmlQuery::XQuery10
3516 | QXmlQuery::XmlSchema11IdentityConstraintField
3517 | QXmlQuery::XSLT20),
3518 parseInfo, @$);
3519 break;
3520 }
3521 case QXmlNodeModelIndex::AxisChild:
3522 {
3523 allowedIn(QueryLanguages( QXmlQuery::XPath20
3524 | QXmlQuery::XQuery10
3525 | QXmlQuery::XmlSchema11IdentityConstraintField
3526 | QXmlQuery::XmlSchema11IdentityConstraintSelector
3527 | QXmlQuery::XSLT20),
3528 parseInfo, @$);
3529 break;
3530 }
3531 default:
3532 {
3533 allowedIn(QueryLanguages( QXmlQuery::XPath20
3534 | QXmlQuery::XQuery10
3535 | QXmlQuery::XSLT20),
3536 parseInfo, @$);
3537 }
3538 }
3539 }
3540
3541AxisToken: ANCESTOR_OR_SELF {$$ = QXmlNodeModelIndex::AxisAncestorOrSelf ;}
3542| ANCESTOR {$$ = QXmlNodeModelIndex::AxisAncestor ;}
3543| ATTRIBUTE {$$ = QXmlNodeModelIndex::AxisAttribute ;}
3544| CHILD {$$ = QXmlNodeModelIndex::AxisChild ;}
3545| DESCENDANT_OR_SELF {$$ = QXmlNodeModelIndex::AxisDescendantOrSelf;}
3546| DESCENDANT {$$ = QXmlNodeModelIndex::AxisDescendant ;}
3547| FOLLOWING {$$ = QXmlNodeModelIndex::AxisFollowing ;}
3548| PRECEDING {$$ = QXmlNodeModelIndex::AxisPreceding ;}
3549| FOLLOWING_SIBLING {$$ = QXmlNodeModelIndex::AxisFollowingSibling;}
3550| PRECEDING_SIBLING {$$ = QXmlNodeModelIndex::AxisPrecedingSibling;}
3551| PARENT {$$ = QXmlNodeModelIndex::AxisParent ;}
3552| SELF {$$ = QXmlNodeModelIndex::AxisSelf ;}
3553
3554AbbrevForwardStep: AT_SIGN
3555 {
3556 parseInfo->nodeTestSource = BuiltinTypes::attribute;
3557 }
3558 NodeTest /* [72] */
3559 {
3560 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20 | QXmlQuery::XmlSchema11IdentityConstraintField), parseInfo, @$);
3561 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, $3), @$, parseInfo);
3562
3563 parseInfo->restoreNodeTestSource();
3564 }
3565| NodeTest
3566 {
3567 ItemType::Ptr nodeTest;
3568
3569 if(parseInfo->isParsingPattern && *$1 == *BuiltinTypes::node)
3570 nodeTest = BuiltinTypes::xsltNodeTest;
3571 else
3572 nodeTest = $1;
3573
3574 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisChild, nodeTest), @$, parseInfo);
3575 }
3576| AnyAttributeTest
3577 {
3578 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, $1), @$, parseInfo);
3579 }
3580
3581ReverseStep: AbbrevReverseStep /* [75] */
3582
3583AbbrevReverseStep: DOTDOT /* [77] */
3584 {
3585 $$ = create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::node), @$, parseInfo);
3586 }
3587
3588NodeTest: NameTest /* [78] */
3589| KindTest
3590 {
3591 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3592 }
3593
3594NameTest: ElementName /* [79] */
3595 {
3596 $$ = QNameTest::create(parseInfo->nodeTestSource, $1);
3597 }
3598| WildCard
3599
3600WildCard: STAR /* [80] */
3601 {
3602 $$ = parseInfo->nodeTestSource;
3603 }
3604| ANY_LOCAL_NAME
3605 {
3606 const NamePool::Ptr np(parseInfo->staticContext->namePool());
3607 const ReflectYYLTYPE ryy(@$, parseInfo);
3608
3609 const QXmlName::NamespaceCode ns(QNameConstructor::namespaceForPrefix(np->allocatePrefix($1), parseInfo->staticContext, &ryy));
3610
3611 $$ = NamespaceNameTest::create(parseInfo->nodeTestSource, ns);
3612 }
3613| ANY_PREFIX
3614 {
3615 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3616 const QXmlName::LocalNameCode c = parseInfo->staticContext->namePool()->allocateLocalName($1);
3617 $$ = LocalNameTest::create(parseInfo->nodeTestSource, c);
3618 }
3619
3620FilterExpr: PrimaryExpr /* [81] */
3621| FilterExpr LBRACKET Expr RBRACKET
3622 {
3623 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3624 $$ = create(GenericPredicate::create($1, $3, parseInfo->staticContext, fromYYLTYPE(@4, parseInfo)), @$, parseInfo);
3625 }
3626
3627PrimaryExpr: Literal /* [84] */
3628| VarRef
3629| ParenthesizedExpr
3630| ContextItemExpr
3631| FunctionCallExpr
3632| OrderingExpr
3633| Constructor
3634| APPLY_TEMPLATE OptionalMode LPAREN TemplateWithParameters RPAREN
3635 {
3636 $$ = create(new ApplyTemplate(parseInfo->modeFor($2),
3637 parseInfo->templateWithParams,
3638 parseInfo->modeFor(QXmlName(StandardNamespaces::InternalXSLT,
3639 StandardLocalNames::Default))),
3640 @1, parseInfo);
3641 parseInfo->templateWithParametersHandled();
3642 }
3643
3644Literal: NumericLiteral /* [85] */
3645| StringLiteral
3646 {
3647 $$ = create(new Literal(AtomicString::fromValue($1)), @$, parseInfo);
3648 }
3649
3650NumericLiteral: XPATH2_NUMBER /* [86] */
3651 {
3652 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3653 $$ = createNumericLiteral<Double>($1, @$, parseInfo);
3654 }
3655| NUMBER
3656 {
3657 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3658 $$ = createNumericLiteral<Numeric>($1, @$, parseInfo);
3659 }
3660
3661VarRef: DOLLAR VarName /* [87] */
3662 {
3663 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3664 $$ = resolveVariable($2, @$, parseInfo, false);
3665 }
3666
3667VarName: NCNAME /* [88] */
3668 {
3669 /* See: http://www.w3.org/TR/xpath20/#id-variables */
3670 $$ = parseInfo->staticContext->namePool()->allocateQName(QString(), $1);
3671 }
3672| QName
3673 {
3674 $$ = $1;
3675 }
3676
3677ParenthesizedExpr: LPAREN Expr RPAREN /* [89] */
3678 {
3679 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3680 $$ = $2;
3681 }
3682| LPAREN RPAREN
3683 {
3684 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3685 $$ = create(new EmptySequence, @$, parseInfo);
3686 }
3687
3688ContextItemExpr: DOT /* [90] */
3689 {
3690 $$ = create(new ContextItem(), @$, parseInfo);
3691 }
3692
3693OrderingExpr: OrderingMode EnclosedExpr /* [X] */
3694 {
3695 $$ = $2;
3696 }
3697
3698FunctionCallExpr: FunctionName LPAREN FunctionArguments RPAREN /* [93] */
3699 {
3700 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
3701 if(XPathHelper::isReservedNamespace($1.namespaceURI()) || $1.namespaceURI() == StandardNamespaces::InternalXSLT)
3702 { /* We got a call to a builtin function. */
3703 const ReflectYYLTYPE ryy(@$, parseInfo);
3704
3705 const Expression::Ptr
3706 func(parseInfo->staticContext->
3707 functionSignatures()->createFunctionCall($1, $3, parseInfo->staticContext, &ryy));
3708
3709 if(func)
3710 $$ = create(func, @$, parseInfo);
3711 else
3712 {
3713 parseInfo->staticContext->error(QtXmlPatterns::tr("No function by name %1 is available.")
3714 .arg(formatKeyword(parseInfo->staticContext->namePool(), $1)),
3715 ReportContext::XPST0017, fromYYLTYPE(@$, parseInfo));
3716 }
3717 }
3718 else /* It's a call to a function created with 'declare function'.*/
3719 {
3720 $$ = create(new UserFunctionCallsite($1, $3.count()), @$, parseInfo);
3721
3722 $$->setOperands($3);
3723 parseInfo->userFunctionCallsites.append($$);
3724 }
3725 }
3726
3727FunctionArguments: /* empty */ /* [X] */
3728 {
3729 $$ = Expression::List();
3730 }
3731
3732| ExprSingle
3733 {
3734 Expression::List list;
3735 list.append($1);
3736 $$ = list;
3737 }
3738
3739| ExpressionSequence
3740
3741Constructor: DirectConstructor /* [94] */
3742 {
3743 allowedIn(QXmlQuery::XQuery10, parseInfo, @$);
3744 }
3745| ComputedConstructor
3746/* The reason we cannot call alloweIn() as the action for ComputedConstructor,
3747 * is that we use the computed constructors for XSL-T, and therefore generate
3748 * INTERNAL tokens. */
3749
3750DirectConstructor: DirElemConstructor /* [95] */
3751| DirCommentConstructor
3752| DirPIConstructor
3753
3754/*
3755 * Direct attribute constructors can contain embedded expressions, and for those namespace bindings
3756 * on the same element needs to be in scope. For example:
3757 *
3758 * @code
3759 * <element attribute="{prefix:nameTest}" xmlns:prefix="http://example.com/"/>
3760 * @endcode
3761 *
3762 * Patternist is designed to do all name resolution at parse time so the subsequent code only has to
3763 * deal with expanded QNames(which the QName class represents), and this presents a problem since
3764 * the parser haven't even encountered the @c xmlns:prefix when resolving @c prefix in the name test.
3765 *
3766 * This is solved as follows:
3767 *
3768 * <ol>
3769 * <li>Just before starting parsing the attributes, we call Tokenizer::commenceScanOnly().
3770 * This switches the tokenizer to not tokenize embedded expressions in attributes,
3771 * but to return them as strings, token type STRING_LITERAL.</li>
3772 * <li>We parse all the attributes, and iterates over them, only caring about
3773 * namespace bindings, and validates and adds them to the context.</li>
3774 * <li>We call Tokenizer::resumeTokenizationFrom() from the previous position
3775 * returned from Tokenizer::commenceScanOnly() and parses the attributes once more,
3776 * but this time with tokenization of embedded expressions. Since we this time
3777 * have the namespace bindings in place, everything resolves.</li>
3778 * </ol>
3779 *
3780 * Saxon does this in a similar way. Study net.sf.saxon.expr.QueryParser::parseDirectElementConstructor().
3781 *
3782 * @see XQueryTokenizer::attributeAsRaw()
3783 */
3784DirElemConstructor: G_LT
3785 LexicalName
3786 {
3787 $<enums.tokenizerPosition>$ = parseInfo->tokenizer->commenceScanOnly();
3788 parseInfo->scanOnlyStack.push(true);
3789 }
3790
3791 /* This list contains name/string pairs. No embedded
3792 * expressions has been parsed. */
3793 DirAttributeList
3794
3795 {
3796 ++parseInfo->elementConstructorDepth;
3797 Expression::List constructors;
3798
3799 parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings());
3800
3801 /* Fix up attributes and namespace declarations. */
3802 const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings()));
3803 const NamePool::Ptr namePool(parseInfo->staticContext->namePool());
3804 const int len = $4.size();
3805 QSet<QXmlName::PrefixCode> usedDeclarations;
3806
3807 /* Whether xmlns="" has been encountered. */
3808 bool hasDefaultDeclaration = false;
3809
3810 /* For each attribute & namespace declaration, do: */
3811 for(int i = 0; i < len; ++i)
3812 {
3813 QString strLocalName;
3814 QString strPrefix;
3815
3816 XPathHelper::splitQName($4.at(i).first, strPrefix, strLocalName);
3817 const QXmlName::PrefixCode prefix = namePool->allocatePrefix(strPrefix);
3818
3819 /* This can seem a bit weird. However, this name is ending up in a QXmlName
3820 * which consider its prefix a... prefix. So, a namespace binding name can in some cases
3821 * be a local name, but that's just as the initial syntactical construct. */
3822 const QXmlName::LocalNameCode localName = namePool->allocatePrefix(strLocalName);
3823
3824 /* Not that localName is "foo" in "xmlns:foo" and that prefix is "xmlns". */
3825
3826 if(prefix == StandardPrefixes::xmlns ||
3827 (prefix == StandardPrefixes::empty && localName == StandardPrefixes::xmlns))
3828 {
3829 if(localName == StandardPrefixes::xmlns)
3830 hasDefaultDeclaration = true;
3831
3832 /* We have a namespace declaration. */
3833
3834 const Expression::Ptr nsExpr($4.at(i).second);
3835
3836 const QString strNamespace(nsExpr->is(Expression::IDEmptySequence) ? QString() : nsExpr->as<Literal>()->item().stringValue());
3837
3838 const QXmlName::NamespaceCode ns = namePool->allocateNamespace(strNamespace);
3839
3840 if(ns == StandardNamespaces::empty)
3841 {
3842 if(localName != StandardPrefixes::xmlns)
3843 {
3844 parseInfo->staticContext->error(QtXmlPatterns::tr("The namespace URI cannot be the empty string when binding to a prefix, %1.")
3845 .arg(formatURI(strPrefix)),
3846 ReportContext::XQST0085, fromYYLTYPE(@$, parseInfo));
3847 }
3848 }
3849 else if(!AnyURI::isValid(strNamespace))
3850 {
3851 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is an invalid namespace URI.").arg(formatURI(strNamespace)),
3852 ReportContext::XQST0022, fromYYLTYPE(@$, parseInfo));
3853 }
3854
3855 if(prefix == StandardPrefixes::xmlns && localName == StandardPrefixes::xmlns)
3856 {
3857 parseInfo->staticContext->error(QtXmlPatterns::tr("It is not possible to bind to the prefix %1")
3858 .arg(formatKeyword("xmlns")),
3859 ReportContext::XQST0070, fromYYLTYPE(@$, parseInfo));
3860 }
3861
3862 if(ns == StandardNamespaces::xml && localName != StandardPrefixes::xml)
3863 {
3864 parseInfo->staticContext->error(QtXmlPatterns::tr("Namespace %1 can only be bound to %2 (and it is, in either case, pre-declared).")
3865 .arg(formatURI(namePool->stringForNamespace(StandardNamespaces::xml)))
3866 .arg(formatKeyword("xml")),
3867 ReportContext::XQST0070, fromYYLTYPE(@$, parseInfo));
3868 }
3869
3870 if(localName == StandardPrefixes::xml && ns != StandardNamespaces::xml)
3871 {
3872 parseInfo->staticContext->error(QtXmlPatterns::tr("Prefix %1 can only be bound to %2 (and it is, in either case, pre-declared).")
3873 .arg(formatKeyword("xml"))
3874 .arg(formatURI(namePool->stringForNamespace(StandardNamespaces::xml))),
3875 ReportContext::XQST0070, fromYYLTYPE(@$, parseInfo));
3876 }
3877
3878 QXmlName nb;
3879
3880 if(localName == StandardPrefixes::xmlns)
3881 nb = QXmlName(ns, StandardLocalNames::empty);
3882 else
3883 nb = QXmlName(ns, StandardLocalNames::empty, localName);
3884
3885 if(usedDeclarations.contains(nb.prefix()))
3886 {
3887 parseInfo->staticContext->error(QtXmlPatterns::tr("Two namespace declaration attributes have the same name: %1.")
3888 .arg(formatKeyword(namePool->stringForPrefix(nb.prefix()))),
3889 ReportContext::XQST0071, fromYYLTYPE(@$, parseInfo));
3890
3891 }
3892 else
3893 usedDeclarations.insert(nb.prefix());
3894
3895 /* If the user has bound the XML namespace correctly, we in either
3896 * case don't want to output it.
3897 *
3898 * We only have to check the namespace parts since the above checks has ensured
3899 * consistency in the prefix parts. */
3900 if(ns != StandardNamespaces::xml)
3901 {
3902 /* We don't want default namespace declarations when the
3903 * default namespace already is empty. */
3904 if(!(ns == StandardNamespaces::empty &&
3905 localName == StandardNamespaces::xmlns &&
3906 resolver->lookupNamespaceURI(StandardPrefixes::empty) == StandardNamespaces::empty))
3907 {
3908 constructors.append(create(new NamespaceConstructor(nb), @$, parseInfo));
3909 resolver->addBinding(nb);
3910 }
3911 }
3912 }
3913 }
3914
3915 if(parseInfo->elementConstructorDepth == 1 && !hasDefaultDeclaration)
3916 {
3917 /* TODO But mostly this isn't needed, since the default element
3918 * namespace is empty? How does this at all work? */
3919 const QXmlName def(resolver->lookupNamespaceURI(StandardPrefixes::empty), StandardLocalNames::empty);
3920 constructors.append(create(new NamespaceConstructor(def), @$, parseInfo));
3921 }
3922
3923 parseInfo->staticContext->setNamespaceBindings(resolver);
3924 $<expressionList>$ = constructors;
3925
3926 /* Resolve the name of the element, now that the namespace attributes are read. */
3927 {
3928 const ReflectYYLTYPE ryy(@$, parseInfo);
3929
3930 const QXmlName ele = QNameConstructor::expandQName<StaticContext::Ptr,
3931 ReportContext::XPST0081,
3932 ReportContext::XPST0081>($2, parseInfo->staticContext, resolver, &ryy);
3933 parseInfo->tagStack.push(ele);
3934 }
3935
3936 parseInfo->tokenizer->resumeTokenizationFrom($<enums.tokenizerPosition>3);
3937 }
3938 POSITION_SET
3939 DirAttributeList
3940 DirElemConstructorTail /* [96] */
3941 {
3942 /* We add the content constructor after the attribute constructors. This might result
3943 * in nested ExpressionSequences, but it will be optimized away later on. */
3944
3945 Expression::List attributes($<expressionList>5);
3946 const NamePool::Ptr namePool(parseInfo->staticContext->namePool());
3947 const int len = $7.size();
3948 QSet<QXmlName> declaredAttributes;
3949 declaredAttributes.reserve(len);
3950
3951 /* For each namespace, resolve its name(now that we have resolved the namespace declarations) and
3952 * turn it into an attribute constructor. */
3953 for(int i = 0; i < len; ++i)
3954 {
3955 QString strLocalName;
3956 QString strPrefix;
3957
3958 XPathHelper::splitQName($7.at(i).first, strPrefix, strLocalName);
3959 const QXmlName::PrefixCode prefix = namePool->allocatePrefix(strPrefix);
3960 const QXmlName::LocalNameCode localName = namePool->allocateLocalName(strLocalName);
3961
3962 if(prefix == StandardPrefixes::xmlns ||
3963 (prefix == StandardPrefixes::empty && localName == StandardLocalNames::xmlns))
3964 {
3965 const Expression::ID id = $7.at(i).second->id();
3966
3967 if(id == Expression::IDStringValue || id == Expression::IDEmptySequence)
3968 {
3969 /* It's a namespace declaration, and we've already handled those above. */
3970 continue;
3971 }
3972 else
3973 {
3974 parseInfo->staticContext->error(QtXmlPatterns::tr("The namespace URI must be a constant and cannot "
3975 "use enclosed expressions."),
3976 ReportContext::XQST0022, fromYYLTYPE(@$, parseInfo));
3977 }
3978
3979 }
3980 else
3981 {
3982 const ReflectYYLTYPE ryy(@$, parseInfo);
3983 const QXmlName att = QNameConstructor::expandQName<StaticContext::Ptr,
3984 ReportContext::XPST0081,
3985 ReportContext::XPST0081>($7.at(i).first, parseInfo->staticContext,
3986 parseInfo->staticContext->namespaceBindings(),
3987 &ryy, true);
3988 if(declaredAttributes.contains(att))
3989 {
3990 parseInfo->staticContext->error(QtXmlPatterns::tr("An attribute by name %1 has already appeared on this element.")
3991 .arg(formatKeyword(parseInfo->staticContext->namePool(), att)),
3992 ReportContext::XQST0040, fromYYLTYPE(@$, parseInfo));
3993
3994 }
3995 else
3996 declaredAttributes.insert(att);
3997
3998 /* wrapLiteral() needs the SourceLocationReflection of the AttributeConstructor, but
3999 * it's unknown inside the arguments to its constructor. Hence we have to do this workaround of setting
4000 * it twice.
4001 *
4002 * The AttributeConstructor's arguments are just dummies. */
4003 const Expression::Ptr ctor(create(new AttributeConstructor($7.at(i).second, $7.at(i).second), @$, parseInfo));
4004
4005 Expression::List ops;
4006 ops.append(wrapLiteral(toItem(QNameValue::fromValue(namePool, att)), parseInfo->staticContext, ctor.data()));
4007 ops.append($7.at(i).second);
4008 ctor->setOperands(ops);
4009
4010 attributes.append(ctor);
4011 }
4012 }
4013
4014 Expression::Ptr contentOp;
4015
4016 if(attributes.isEmpty())
4017 contentOp = $8;
4018 else
4019 {
4020 attributes.append($8);
4021 contentOp = create(new ExpressionSequence(attributes), @$, parseInfo);
4022 }
4023
4024 const Expression::Ptr name(create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), parseInfo->tagStack.top()))), @$, parseInfo));
4025 $$ = create(new ElementConstructor(name, contentOp, parseInfo->isXSLT()), @$, parseInfo);
4026
4027 /* Restore the old context. We don't want the namespaces
4028 * to be in-scope for expressions appearing after the
4029 * element they appeared on. */
4030 parseInfo->staticContext->setNamespaceBindings(parseInfo->resolvers.pop());
4031 parseInfo->tagStack.pop();
4032
4033 --parseInfo->elementConstructorDepth;
4034 }
4035
4036DirElemConstructorTail: QUICK_TAG_END
4037 {
4038 $$ = create(new EmptySequence(), @$, parseInfo);
4039 }
4040| G_GT DirElemContent BEGIN_END_TAG ElementName G_GT
4041 {
4042 if(!$4.isLexicallyEqual(parseInfo->tagStack.top()))
4043 {
4044 parseInfo->staticContext->error(QtXmlPatterns::tr("A direct element constructor is not "
4045 "well-formed. %1 is ended with %2.")
4046 .arg(formatKeyword(parseInfo->staticContext->namePool()->toLexical(parseInfo->tagStack.top())),
4047 formatKeyword(parseInfo->staticContext->namePool()->toLexical($4))),
4048 ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo));
4049 }
4050
4051 if($2.isEmpty())
4052 $$ = create(new EmptySequence(), @$, parseInfo);
4053 else if($2.size() == 1)
4054 $$ = $2.first();
4055 else
4056 $$ = create(new ExpressionSequence($2), @$, parseInfo);
4057 }
4058
4059DirAttributeList: /* empty */ /* [97] */
4060 {
4061 $$ = AttributeHolderVector();
4062 }
4063| DirAttributeList Attribute
4064 {
4065 $1.append($2);
4066 $$ = $1;
4067 }
4068
4069Attribute: LexicalName G_EQ DirAttributeValue /* [X] */
4070 {
4071 $$ = qMakePair($1, $3);
4072 }
4073
4074DirAttributeValue: QUOTE AttrValueContent QUOTE /* [98] */
4075 {
4076 $$ = createDirAttributeValue($2, parseInfo, @$);
4077 }
4078
4079| APOS AttrValueContent APOS
4080 {
4081 $$ = createDirAttributeValue($2, parseInfo, @$);
4082 }
4083
4084AttrValueContent: /* Empty. */ /* [X] */
4085 {
4086 $$ = Expression::List();
4087 }
4088| EnclosedExpr AttrValueContent
4089 {
4090 Expression::Ptr content($1);
4091
4092 if(parseInfo->isBackwardsCompat.top())
4093 content = create(GenericPredicate::createFirstItem(content), @$, parseInfo);
4094
4095 $2.prepend(createSimpleContent(content, @$, parseInfo));
4096 $$ = $2;
4097 }
4098| StringLiteral AttrValueContent
4099 {
4100 $2.prepend(create(new Literal(AtomicString::fromValue($1)), @$, parseInfo));
4101 $$ = $2;
4102 }
4103
4104DirElemContent: /* empty */ /* [101] */
4105 {
4106 $$ = Expression::List();
4107 parseInfo->isPreviousEnclosedExpr = false;
4108 }
4109| DirElemContent DirectConstructor
4110 {
4111 $1.append($2);
4112 $$ = $1;
4113 parseInfo->isPreviousEnclosedExpr = false;
4114 }
4115| DirElemContent StringLiteral
4116 {
4117 if(parseInfo->staticContext->boundarySpacePolicy() == StaticContext::BSPStrip &&
4118 XPathHelper::isWhitespaceOnly($2))
4119 {
4120 $$ = $1;
4121 }
4122 else
4123 {
4124 $1.append(create(new TextNodeConstructor(create(new Literal(AtomicString::fromValue($2)), @$, parseInfo)), @$, parseInfo));
4125 $$ = $1;
4126 parseInfo->isPreviousEnclosedExpr = false;
4127 }
4128 }
4129| DirElemContent NON_BOUNDARY_WS
4130 {
4131 $1.append(create(new TextNodeConstructor(create(new Literal(AtomicString::fromValue($2)), @$, parseInfo)), @$, parseInfo));
4132 $$ = $1;
4133 parseInfo->isPreviousEnclosedExpr = false;
4134 }
4135| DirElemContent EnclosedExpr
4136 {
4137 /* We insert a text node constructor that send an empty text node between
4138 * the two enclosed expressions, in order to ensure that no space is inserted.
4139 *
4140 * However, we only do it when we have no node constructors. */
4141 if(parseInfo->isPreviousEnclosedExpr &&
4142 BuiltinTypes::xsAnyAtomicType->xdtTypeMatches($2->staticType()->itemType()) &&
4143 BuiltinTypes::xsAnyAtomicType->xdtTypeMatches($1.last()->staticType()->itemType()))
4144 $1.append(create(new TextNodeConstructor(create(new Literal(AtomicString::fromValue(QString())), @$, parseInfo)), @$, parseInfo));
4145 else
4146 parseInfo->isPreviousEnclosedExpr = true;
4147
4148 $1.append(createCopyOf($2, parseInfo, @$));
4149 $$ = $1;
4150 }
4151
4152DirCommentConstructor: COMMENT_START COMMENT_CONTENT /* [103] */
4153 {
4154 $$ = create(new CommentConstructor(create(new Literal(AtomicString::fromValue($2)), @$, parseInfo)), @$, parseInfo);
4155 }
4156
4157DirPIConstructor: PI_START PI_TARGET PI_CONTENT /* [105] */
4158 {
4159 const ReflectYYLTYPE ryy(@$, parseInfo);
4160 NCNameConstructor::validateTargetName<StaticContext::Ptr,
4161 ReportContext::XPST0003,
4162 ReportContext::XPST0003>($2,
4163 parseInfo->staticContext, &ryy);
4164
4165 $$ = create(new ProcessingInstructionConstructor(
4166 create(new Literal(AtomicString::fromValue($2)), @$, parseInfo),
4167 create(new Literal(AtomicString::fromValue($3)), @$, parseInfo)), @$, parseInfo);
4168 }
4169
4170ComputedConstructor: CompDocConstructor /* [109] */
4171| CompElemConstructor
4172| CompAttrConstructor
4173| CompTextConstructor
4174| CompCommentConstructor
4175| CompPIConstructor
4176| CompNamespaceConstructor
4177
4178CompDocConstructor: DOCUMENT IsInternal EnclosedExpr /* [110] */
4179 {
4180 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
4181
4182 $$ = create(new DocumentConstructor($3), @$, parseInfo);
4183 }
4184
4185CompElemConstructor: ELEMENT IsInternal CompElementName
4186 {
4187 /* This value is incremented before the action below is executed. */
4188 ++parseInfo->elementConstructorDepth;
4189 }
4190 EnclosedOptionalExpr /* [111] */
4191 {
4192 Q_ASSERT(5);
4193 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
4194
4195 Expression::Ptr effExpr;
4196
4197 if($5)
4198 effExpr = createCopyOf($5, parseInfo, @$);
4199 else
4200 effExpr = create(new EmptySequence(), @$, parseInfo);
4201
4202 const QXmlName::NamespaceCode ns = parseInfo->resolvers.top()->lookupNamespaceURI(StandardPrefixes::empty);
4203
4204 /* Ensure the default namespace gets counted as an in-scope binding, if such a one exists. If we're
4205 * a child of another constructor, it has already been done. */
4206 if(parseInfo->elementConstructorDepth == 1 && ns != StandardNamespaces::empty)
4207 {
4208 Expression::List exprList;
4209
4210 /* We append the namespace constructor before the body, in order to
4211 * comply with QAbstractXmlPushHandler's contract. */
4212 const QXmlName def(parseInfo->resolvers.top()->lookupNamespaceURI(StandardPrefixes::empty), StandardLocalNames::empty);
4213 exprList.append(create(new NamespaceConstructor(def), @$, parseInfo));
4214
4215 exprList.append(effExpr);
4216
4217 effExpr = create(new ExpressionSequence(exprList), @$, parseInfo);
4218 }
4219
4220 --parseInfo->elementConstructorDepth;
4221 $$ = create(new ElementConstructor($3, effExpr, parseInfo->isXSLT()), @$, parseInfo);
4222 }
4223
4224IsInternal: /* Empty. */ /* [X] */
4225 {
4226 $$ = false;
4227 }
4228| INTERNAL
4229 {
4230 $$ = true;
4231 }
4232
4233CompAttrConstructor: ATTRIBUTE
4234 IsInternal
4235 CompAttributeName
4236 EnclosedOptionalExpr /* [113] */
4237 {
4238 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
4239
4240 const Expression::Ptr name(create(new AttributeNameValidator($3), @$, parseInfo));
4241
4242 if($4)
4243 $$ = create(new AttributeConstructor(name, createSimpleContent($4, @$, parseInfo)), @$, parseInfo);
4244 else
4245 $$ = create(new AttributeConstructor(name, create(new EmptySequence(), @$, parseInfo)), @$, parseInfo);
4246 }
4247
4248CompTextConstructor: TEXT IsInternal EnclosedExpr /* [114] */
4249 {
4250 $$ = create(new TextNodeConstructor(createSimpleContent($3, @$, parseInfo)), @$, parseInfo);
4251 }
4252
4253CompCommentConstructor: COMMENT IsInternal EnclosedExpr /* [115] */
4254 {
4255 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
4256
4257 $$ = create(new CommentConstructor(createSimpleContent($3, @$, parseInfo)), @$, parseInfo);
4258 }
4259
4260CompPIConstructor: PROCESSING_INSTRUCTION CompPIName EnclosedOptionalExpr /* [116] */
4261 {
4262 allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2);
4263
4264 if($3)
4265 {
4266 $$ = create(new ProcessingInstructionConstructor($2, createSimpleContent($3, @$, parseInfo)), @$, parseInfo);
4267 }
4268 else
4269 $$ = create(new ProcessingInstructionConstructor($2, create(new EmptySequence(), @$, parseInfo)), @$, parseInfo);
4270 }
4271
4272CompAttributeName: {
4273 parseInfo->nodeTestSource = BuiltinTypes::attribute;
4274 }
4275 ElementName
4276 {
4277 parseInfo->restoreNodeTestSource();
4278 } /* [X] */
4279 {
4280 $$ = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), $2))), @$, parseInfo);
4281 }
4282| CompNameExpr
4283
4284CompElementName: ElementName /* [X] */
4285 {
4286 $$ = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), $1))), @$, parseInfo);
4287 }
4288| CompNameExpr
4289
4290CompNameExpr: EnclosedExpr
4291 {
4292 if(BuiltinTypes::xsQName->xdtTypeMatches($1->staticType()->itemType()))
4293 $$ = $1;
4294 else
4295 {
4296 $$ = create(new QNameConstructor($1,
4297 parseInfo->staticContext->namespaceBindings()),
4298 @$, parseInfo);
4299 }
4300 }
4301
4302/*
4303 * We always create an NCNameConstructor here. If will be rewritten away if not needed.
4304 */
4305CompPIName: NCNAME
4306 {
4307 $$ = create(new NCNameConstructor(create(new Literal(AtomicString::fromValue($1)), @$, parseInfo)), @$, parseInfo);
4308 }
4309| EnclosedExpr
4310 {
4311 $$ = create(new NCNameConstructor($1), @$, parseInfo);
4312 }
4313
4314/*
4315 * This expression is used for implementing XSL-T 2.0's xsl:namespace
4316 * instruction.
4317 */
4318CompNamespaceConstructor: NAMESPACE EnclosedExpr EnclosedExpr /* [X] */
4319{
4320 $$ = create(new ComputedNamespaceConstructor($2, $3), @$, parseInfo);
4321}
4322
4323SingleType: AtomicType /* [117] */
4324 {
4325 $$ = makeGenericSequenceType($1, Cardinality::exactlyOne());
4326 }
4327| AtomicType QUESTION
4328 {
4329 $$ = makeGenericSequenceType($1, Cardinality::zeroOrOne());
4330 }
4331
4332TypeDeclaration: /* empty */ /* [118] */
4333 {
4334 $$ = CommonSequenceTypes::ZeroOrMoreItems;
4335 }
4336| AS SequenceType
4337 {
4338 $$ = $2;
4339 }
4340
4341SequenceType: ItemType OccurrenceIndicator /* [119] */
4342 {
4343 $$ = makeGenericSequenceType($1, $2);
4344 }
4345
4346| EMPTY_SEQUENCE EmptyParanteses
4347 {
4348 $$ = CommonSequenceTypes::Empty;
4349 }
4350
4351OccurrenceIndicator: /* empty */ {$$ = Cardinality::exactlyOne();} /* [120] */
4352| PLUS {$$ = Cardinality::oneOrMore();}
4353| STAR {$$ = Cardinality::zeroOrMore();}
4354| QUESTION {$$ = Cardinality::zeroOrOne();}
4355
4356ItemType: AtomicType /* [121] */
4357| KindTest
4358| AnyAttributeTest
4359| ITEM EmptyParanteses
4360 {
4361 $$ = BuiltinTypes::item;
4362 }
4363
4364AtomicType: ElementName /* [122] */
4365 {
4366 const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType($1));
4367
4368 if(!t)
4369 {
4370 parseInfo->staticContext->error(QtXmlPatterns::tr("The name %1 does not refer to any schema type.")
4371 .arg(formatKeyword(parseInfo->staticContext->namePool(), $1)), ReportContext::XPST0051, fromYYLTYPE(@$, parseInfo));
4372 }
4373 else if(BuiltinTypes::xsAnyAtomicType->wxsTypeMatches(t))
4374 $$ = AtomicType::Ptr(t);
4375 else
4376 {
4377 /* Try to give an intelligent message. */
4378 if(t->isComplexType())
4379 {
4380 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is an complex type. Casting to complex "
4381 "types is not possible. However, casting "
4382 "to atomic types such as %2 works.")
4383 .arg(formatType(parseInfo->staticContext->namePool(), t))
4384 .arg(formatType(parseInfo->staticContext->namePool(), BuiltinTypes::xsInteger)),
4385 ReportContext::XPST0051, fromYYLTYPE(@$, parseInfo));
4386 }
4387 else
4388 {
4389 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not an atomic type. Casting "
4390 "is only possible to atomic types.")
4391 .arg(formatType(parseInfo->staticContext->namePool(), t)),
4392 ReportContext::XPST0051, fromYYLTYPE(@$, parseInfo));
4393 }
4394 }
4395 }
4396
4397/* This non-terminal does not contain SchemaAttributeTest and AttributeTest.
4398 Those are in the AnyAttributeTest non-terminal. This is in order to get the axis
4399 right for attribute tests in the abbreviated syntax. */
4400KindTest: DocumentTest /* [123] */
4401| ElementTest
4402| SchemaElementTest
4403| PITest
4404| CommentTest
4405| TextTest
4406| AnyKindTest
4407
4408AnyKindTest: NODE EmptyParanteses /* [124] */
4409 {
4410 $$ = BuiltinTypes::node;
4411 }
4412
4413DocumentTest: DOCUMENT_NODE EmptyParanteses /* [125] */
4414 {
4415 $$ = BuiltinTypes::document;
4416 }
4417
4418| DOCUMENT_NODE LPAREN AnyElementTest RPAREN
4419 {
4420 // TODO support for document element testing
4421 $$ = BuiltinTypes::document;
4422 }
4423
4424AnyElementTest: ElementTest /* [X] */
4425| SchemaElementTest
4426
4427TextTest: TEXT EmptyParanteses /* [126] */
4428 {
4429 $$ = BuiltinTypes::text;
4430 }
4431
4432CommentTest: COMMENT EmptyParanteses /* [127] */
4433 {
4434 $$ = BuiltinTypes::comment;
4435 }
4436
4437PITest: PROCESSING_INSTRUCTION EmptyParanteses /* [128] */
4438 {
4439 $$ = BuiltinTypes::pi;
4440 }
4441
4442| PROCESSING_INSTRUCTION LPAREN NCNAME RPAREN
4443 {
4444 $$ = LocalNameTest::create(BuiltinTypes::pi, parseInfo->staticContext->namePool()->allocateLocalName($3));
4445 }
4446
4447| PROCESSING_INSTRUCTION LPAREN StringLiteral RPAREN
4448 {
4449 if(QXmlUtils::isNCName($3))
4450 {
4451 $$ = LocalNameTest::create(BuiltinTypes::pi, parseInfo->staticContext->namePool()->allocateLocalName($3));
4452 }
4453 else
4454 {
4455 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not a valid name for a "
4456 "processing-instruction.")
4457 .arg(formatKeyword($3)),
4458 ReportContext::XPTY0004,
4459 fromYYLTYPE(@$, parseInfo));
4460 }
4461 }
4462
4463AnyAttributeTest: AttributeTest
4464| SchemaAttributeTest
4465
4466AttributeTest: ATTRIBUTE EmptyParanteses /* [129] */
4467 {
4468 $$ = BuiltinTypes::attribute;
4469 }
4470
4471| ATTRIBUTE LPAREN STAR RPAREN
4472 {
4473 $$ = BuiltinTypes::attribute;
4474 }
4475
4476| ATTRIBUTE LPAREN AttributeName RPAREN
4477 {
4478 $$ = QNameTest::create(BuiltinTypes::attribute, $3);
4479 }
4480| ATTRIBUTE LPAREN AttributeName COMMA TypeName RPAREN
4481 {
4482 const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType($5));
4483
4484 if(t)
4485 $$ = BuiltinTypes::attribute;
4486 else
4487 {
4488 parseInfo->staticContext->error(unknownType().arg(formatKeyword(parseInfo->staticContext->namePool(), $5)),
4489 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4490 }
4491 }
4492| ATTRIBUTE LPAREN STAR COMMA TypeName RPAREN
4493 {
4494 const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType($5));
4495
4496 if(t)
4497 $$ = BuiltinTypes::attribute;
4498 else
4499 {
4500 parseInfo->staticContext->error(unknownType().arg(formatKeyword(parseInfo->staticContext->namePool(), $5)),
4501 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4502 }
4503 }
4504
4505SchemaAttributeTest: SCHEMA_ATTRIBUTE LPAREN ElementName RPAREN /* [131] */
4506 {
4507 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute "
4508 "declarations. Note that the schema import "
4509 "feature is not supported.")
4510 .arg(formatKeyword(parseInfo->staticContext->namePool(), $3)),
4511 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4512 $$.reset();
4513 }
4514
4515ElementTest: ELEMENT EmptyParanteses /* [133] */
4516 {
4517 $$ = BuiltinTypes::element;
4518 }
4519
4520| ELEMENT LPAREN STAR RPAREN
4521 {
4522 $$ = BuiltinTypes::element;
4523 }
4524
4525| ELEMENT LPAREN ElementName RPAREN
4526 {
4527 $$ = QNameTest::create(BuiltinTypes::element, $3);
4528 }
4529
4530| ELEMENT LPAREN ElementName COMMA TypeName OptionalQuestionMark RPAREN
4531 {
4532 const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType($5));
4533
4534 if(t)
4535 $$ = BuiltinTypes::element;
4536 else
4537 {
4538 parseInfo->staticContext->error(unknownType()
4539 .arg(formatKeyword(parseInfo->staticContext->namePool(), $5)),
4540 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4541 }
4542 }
4543
4544| ELEMENT LPAREN STAR COMMA TypeName OptionalQuestionMark RPAREN
4545 {
4546 const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType($5));
4547
4548 if(t)
4549 $$ = BuiltinTypes::element;
4550 else
4551 {
4552 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is an unknown schema type.")
4553 .arg(formatKeyword(parseInfo->staticContext->namePool(), $5)),
4554 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4555 }
4556 }
4557
4558OptionalQuestionMark: /* Empty. */
4559| QUESTION
4560
4561SchemaElementTest: SCHEMA_ELEMENT LPAREN ElementName RPAREN /* [135] */
4562 {
4563 parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute "
4564 "declarations. Note that the schema import "
4565 "feature is not supported.")
4566 .arg(formatKeyword(parseInfo->staticContext->namePool(), $3)),
4567 ReportContext::XPST0008, fromYYLTYPE(@$, parseInfo));
4568 $$.reset();
4569 }
4570
4571EmptyParanteses: LPAREN RPAREN /* [X] */
4572
4573AttributeName: NCNAME /* [137] */
4574 {
4575 $$ = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::empty, $1);
4576 }
4577
4578| QName
4579
4580/*
4581 * When a QName appear with no prefix, it uses a certain default namespace
4582 * depending on where the QName occurs. These two rules, invoked in the appropriate
4583 * contexts, performs this distinction.
4584 */
4585ElementName: NCNAME /* [138] */
4586 {
4587 if(parseInfo->nodeTestSource == BuiltinTypes::element)
4588 $$ = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->namespaceBindings()->lookupNamespaceURI(StandardPrefixes::empty), $1);
4589 else
4590 $$ = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::empty, $1);
4591 }
4592| QName
4593
4594TypeName: ElementName /* [139] */
4595
4596FunctionName: NCName /* [X] */
4597| QName
4598
4599NCName: NCNAME
4600 {
4601 $$ = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->defaultFunctionNamespace(), $1);
4602 }
4603| INTERNAL_NAME NCNAME
4604 {
4605 $$ = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::InternalXSLT, $2);
4606 }
4607
4608LexicalName: NCNAME
4609| QNAME
4610
4611PragmaName: NCNAME /* [X] */
4612 {
4613 parseInfo->staticContext->error(QtXmlPatterns::tr("The name of an extension expression must be in "
4614 "a namespace."),
4615 ReportContext::XPST0081, fromYYLTYPE(@$, parseInfo));
4616 }
4617| QName
4618
4619URILiteral: StringLiteral /* [140] */
4620
4621StringLiteral: STRING_LITERAL /* [144] */
4622 {
4623 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
4624 }
4625| XPATH2_STRING_LITERAL
4626 {
4627 allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$);
4628 }
4629
4630QName: QNAME /* [154] */
4631 {
4632
4633 const ReflectYYLTYPE ryy(@$, parseInfo);
4634
4635 $$ = QNameConstructor::
4636 expandQName<StaticContext::Ptr,
4637 ReportContext::XPST0081,
4638 ReportContext::XPST0081>($1, parseInfo->staticContext,
4639 parseInfo->staticContext->namespaceBindings(), &ryy);
4640
4641 }
4642| CLARK_NAME
4643 {
4644 $$ = parseInfo->staticContext->namePool()->fromClarkName($1);
4645 }
4646
4647%%
4648
4649QString Tokenizer::tokenToString(const Token &token)
4650{
4651 switch(token.type)
4652 {
4653 case NCNAME:
4654 /* Fallthrough. */
4655 case QNAME:
4656 /* Fallthrough. */
4657 case NUMBER:
4658 /* Fallthrough. */
4659 case XPATH2_NUMBER:
4660 return token.value;
4661 case STRING_LITERAL:
4662 return QLatin1Char('"') + token.value + QLatin1Char('"');
4663 default:
4664 {
4665 const QString raw(QString::fromLatin1(yytname[YYTRANSLATE(token.type)]));
4666
4667 /* Remove the quotes. */
4668 if(raw.at(0) == QLatin1Char('"') && raw.length() > 1)
4669 return raw.mid(1, raw.length() - 2);
4670 else
4671 return raw;
4672 }
4673 }
4674}
4675
4676} /* namespace Patternist */
4677
4678QT_END_NAMESPACE
4679
4680// vim: et:ts=4:sw=4:sts=4:syntax=yacc
Note: See TracBrowser for help on using the repository browser.