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

Last change on this file since 439 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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