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