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

Last change on this file since 615 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 {