|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
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 ** |
|
55 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
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 { |
|
873 parseInfo->staticContext->error(QtXmlPatterns::tr("No variable by name %1 exists") |
|
874 .arg(formatKeyword(parseInfo->staticContext->namePool(), variableName)), |
|
875 ReportContext::XPST0008, fromYYLTYPE(location, parseInfo)); |
|
876 } |
|
877 |
|
878 /** |
|
879 * The Cardinality in a TypeDeclaration for a variable in a quantification has no effect, |
|
880 * and this function ensures this by changing @p type to Cardinality Cardinality::zeroOrMore(). |
|
881 * |
|
882 * @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=3305">Bugzilla Bug 3305 |
|
883 * Cardinality + on range variables</a> |
|
884 * @see ParserContext::finalizePushedVariable() |
|
885 */ |
|
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 |