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

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

trunk: Merged in qt 4.6.2 sources.

File size: 189.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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) 2010 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()