Qt 4.8
Public Types | Public Functions | Static Public Functions | Protected Types | Protected Functions | List of all members
QPatternist::ExpressionFactory Class Reference

The central entry point for compiling expressions. More...

#include <qexpressionfactory_p.h>

Inheritance diagram for QPatternist::ExpressionFactory:
QSharedData

Public Types

enum  CompilationStage {
  QueryBodyInitial = 1, QueryBodyTypeCheck = 1 << 1, QueryBodyCompression = 1 << 2, UserFunctionTypeCheck = 1 << 3,
  UserFunctionCompression = 1 << 4, GlobalVariableTypeCheck = 1 << 5
}
 
typedef QExplicitlySharedDataPointer< ExpressionFactoryPtr
 

Public Functions

virtual Expression::Ptr createExpression (const QString &expr, const StaticContext::Ptr &context, const QXmlQuery::QueryLanguage lang, const SequenceType::Ptr &requiredType, const QUrl &queryURI, const QXmlName &initialTemplateName)
 
virtual Expression::Ptr createExpression (QIODevice *const device, const StaticContext::Ptr &context, const QXmlQuery::QueryLanguage lang, const SequenceType::Ptr &requiredType, const QUrl &queryURI, const QXmlName &initialTemplateName)
 
 ExpressionFactory ()
 This constructor cannot be synthesized since we use the Q_DISABLE_COPY macro. More...
 
virtual ~ExpressionFactory ()
 
- Public Functions inherited from QSharedData
 QSharedData ()
 Constructs a QSharedData object with a reference count of 0. More...
 
 QSharedData (const QSharedData &)
 Constructs a QSharedData object with reference count 0. More...
 

Static Public Functions

static void registerLastPath (const Expression::Ptr &operand)
 

Protected Types

enum  TemplateCompilationStage { TemplateInitial = 1, TemplateTypeCheck = 1 << 1, TemplateCompress = 1 << 2 }
 

Protected Functions

Expression::Ptr createExpression (const Tokenizer::Ptr &tokenizer, const StaticContext::Ptr &context, const QXmlQuery::QueryLanguage lang, const SequenceType::Ptr &requiredType, const QUrl &queryURI, const QXmlName &initialTemplateName)
 
virtual void processNamedTemplate (const QXmlName &name, const Expression::Ptr &tree, const TemplateCompilationStage stage)
 
virtual void processTemplateRule (const Expression::Ptr &body, const TemplatePattern::Ptr &pattern, const QXmlName &mode, const TemplateCompilationStage stage)
 
virtual void processTreePass (const Expression::Ptr &tree, const CompilationStage stage)
 

Additional Inherited Members

- Public Variables inherited from QSharedData
QAtomicInt ref
 

Detailed Description

The central entry point for compiling expressions.

Author
Frans Englich frans.nosp@m..eng.nosp@m.lich@.nosp@m.noki.nosp@m.a.com

Definition at line 77 of file qexpressionfactory_p.h.

Typedefs

◆ Ptr

Definition at line 80 of file qexpressionfactory_p.h.

Enumerations

◆ CompilationStage

◆ TemplateCompilationStage

Enumerator
TemplateInitial 
TemplateTypeCheck 
TemplateCompress 

Definition at line 142 of file qexpressionfactory_p.h.

Constructors and Destructors

◆ ExpressionFactory()

QPatternist::ExpressionFactory::ExpressionFactory ( )
inline

This constructor cannot be synthesized since we use the Q_DISABLE_COPY macro.

Definition at line 86 of file qexpressionfactory_p.h.

87  {
88  }

◆ ~ExpressionFactory()

virtual QPatternist::ExpressionFactory::~ExpressionFactory ( )
inlinevirtual

Definition at line 90 of file qexpressionfactory_p.h.

91  {
92  }

Functions

◆ createExpression() [1/3]

Expression::Ptr QPatternist::ExpressionFactory::createExpression ( const QString expr,
const StaticContext::Ptr context,
const QXmlQuery::QueryLanguage  lang,
const SequenceType::Ptr requiredType,
const QUrl queryURI,
const QXmlName initialTemplateName 
)
virtual

Creates a compiled representation of the XPath expression expr, with Static Context information supplied via context. This is for example whether the expression is an XPath 1.0 or XPath 2.0 expression, or what functions that are available.

requiredType specifies what type results of the evaluating the expression must match. Passing CommonValues::ZeroOrMoreItems allows anything as result, while passing CommonSequenceTypes::EBV means anything but an Effective Boolean Value extractable result is a type error, for example.

Note
An empty expr is an invalid XPath expression. It will be reported as such, but it is neverthless the caller's resonsibility to ensure that it's not that(since it is likely invalid already in the medium it was stored).

Definition at line 77 of file qexpressionfactory.cpp.

83 {
84  if(lang == QXmlQuery::XSLT20)
85  {
86  QByteArray query(expr.toUtf8());
87  QBuffer buffer(&query);
88  buffer.open(QIODevice::ReadOnly);
89 
90  return createExpression(&buffer,
91  context,
92  lang,
93  requiredType,
94  queryURI,
95  initialTemplateName);
96  }
97  else
98  {
99  return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)),
100  context,
101  lang,
102  requiredType,
103  queryURI,
104  initialTemplateName);
105  }
106 }
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
QExplicitlySharedDataPointer< Tokenizer > Ptr
Definition: qtokenizer_p.h:163
virtual Expression::Ptr createExpression(const QString &expr, const StaticContext::Ptr &context, const QXmlQuery::QueryLanguage lang, const SequenceType::Ptr &requiredType, const QUrl &queryURI, const QXmlName &initialTemplateName)

◆ createExpression() [2/3]

Expression::Ptr QPatternist::ExpressionFactory::createExpression ( QIODevice *const  device,
const StaticContext::Ptr context,
const QXmlQuery::QueryLanguage  lang,
const SequenceType::Ptr requiredType,
const QUrl queryURI,
const QXmlName initialTemplateName 
)
virtual

Definition at line 108 of file qexpressionfactory.cpp.

Referenced by createExpression().

114 {
115  Q_ASSERT(device);
116  Q_ASSERT(device->isReadable());
117 
118  Tokenizer::Ptr tokenizer;
119 
120  if(lang == QXmlQuery::XSLT20)
121  tokenizer = Tokenizer::Ptr(new XSLTTokenizer(device, queryURI, context, context->namePool()));
122  else
123  tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI));
124 
125  return createExpression(tokenizer, context, lang, requiredType, queryURI, initialTemplateName);
126 }
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
Definition: qiodevice.cpp:544
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
QExplicitlySharedDataPointer< Tokenizer > Ptr
Definition: qtokenizer_p.h:163
virtual Expression::Ptr createExpression(const QString &expr, const StaticContext::Ptr &context, const QXmlQuery::QueryLanguage lang, const SequenceType::Ptr &requiredType, const QUrl &queryURI, const QXmlName &initialTemplateName)

◆ createExpression() [3/3]

Expression::Ptr QPatternist::ExpressionFactory::createExpression ( const Tokenizer::Ptr tokenizer,
const StaticContext::Ptr context,
const QXmlQuery::QueryLanguage  lang,
const SequenceType::Ptr requiredType,
const QUrl queryURI,
const QXmlName initialTemplateName 
)
protected

Definition at line 128 of file qexpressionfactory.cpp.

134 {
135  Q_ASSERT(context);
136  Q_ASSERT(requiredType);
137  Q_ASSERT(queryURI.isValid());
138 
139  Tokenizer::Ptr effectiveTokenizer(tokenizer);
140 #ifdef Patternist_DEBUG
141  effectiveTokenizer = Tokenizer::Ptr(new TokenRevealer(queryURI, tokenizer));
142 #endif
143 
145 
146  const ParserContext::Ptr info(new ParserContext(context, lang, effectiveTokenizer.data()));
147  info->initialTemplateName = initialTemplateName;
148 
149  effectiveTokenizer->setParserContext(info);
150 
151  const int bisonRetval = XPathparse(info.data());
152 
153  Q_ASSERT_X(bisonRetval == 0, Q_FUNC_INFO,
154  "We shouldn't be able to get an error, because we throw exceptions.");
155  Q_UNUSED(bisonRetval); /* Needed when not compiled in debug mode, since bisonRetval won't
156  * be used in the Q_ASSERT_X above. */
157 
158  Expression::Ptr result(info->queryBody);
159 
160  if(!result)
161  {
162  context->error(QtXmlPatterns::tr("A library module cannot be evaluated "
163  "directly. It must be imported from a "
164  "main module."),
166  QSourceLocation(queryURI, 1, 1));
167  }
168 
169  /* Optimization: I think many things are done in the wrong order below. We
170  * probably want everything typechecked before compressing, since we can
171  * have references all over the place(variable references, template
172  * invocations, function callsites). This could even be a source to bugs.
173  */
174 
175  /* Here, we type check user declared functions and global variables. This
176  * means that variables and functions that are not used are type
177  * checked(which they otherwise wouldn't have been), and those which are
178  * used, are type-checked twice, unfortunately. */
179 
180  const bool hasExternalFocus = context->contextItemType();
181 
182  if(lang == QXmlQuery::XSLT20)
183  {
184  /* Bind xsl:call-template instructions to their template bodies.
185  *
186  * We do this before type checking and compressing them, because a
187  * CallTemplate obviously needs its template before being compressed.
188  *
189  * Also, we do this before type checking and compressing user
190  * functions, since they can contain template call sites.
191  */
192  for(int i = 0; i < info->templateCalls.count(); ++i)
193  {
194  CallTemplate *const site = info->templateCalls.at(i)->as<CallTemplate>();
195  const QXmlName targetName(site->name());
196  const Template::Ptr t(info->namedTemplates.value(targetName));
197 
198  if(t)
199  site->setTemplate(t);
200  else
201  {
202  context->error(QtXmlPatterns::tr("No template by name %1 exists.").arg(formatKeyword(context->namePool(), targetName)),
204  site);
205  }
206  }
207  }
208 
209  /* Type check and compress user functions. */
210  {
211  const UserFunction::List::const_iterator end(info->userFunctions.constEnd());
212  UserFunction::List::const_iterator it(info->userFunctions.constBegin());
213 
214  /* If the query has a focus(which is common, in the case of a
215  * stylesheet), we must ensure that the focus isn't visible in the
216  * function body. */
217  StaticContext::Ptr effectiveContext;
218 
219  if(hasExternalFocus)
220  {
221  effectiveContext = StaticContext::Ptr(new StaticFocusContext(ItemType::Ptr(),
222  context));
223  }
224  else
225  effectiveContext = context;
226 
227  for(; it != end; ++it)
228  {
229  pDebug() << "----- User Function Typecheck -----";
230  registerLastPath((*it)->body());
231 
232  /* We will most likely call body()->typeCheck() again, once for
233  * each callsite. That is, it will be called from
234  * UserFunctionCallsite::typeCheck(), which will be called
235  * indirectly when we check the query body. */
236  const Expression::Ptr typeCheck((*it)->body()->typeCheck(effectiveContext,
237  (*it)->signature()->returnType()));
238  /* We don't have to call (*it)->setBody(typeCheck) here since it's
239  * only used directly below. */
241  pDebug() << "------------------------------";
242 
243  pDebug() << "----- User Function Compress -----";
244  const Expression::Ptr comp(typeCheck->compress(effectiveContext));
245  (*it)->setBody(comp);
247  pDebug() << "------------------------------";
248  }
249  }
250 
251  /* Type check and compress global variables. */
252  {
253  const VariableDeclaration::Stack::const_iterator vend(info->variables.constEnd());
254  VariableDeclaration::Stack::const_iterator vit(info->variables.constBegin());
255  for(; vit != vend; ++vit)
256  {
257  Q_ASSERT(*vit);
258  /* This is a bit murky, the global variable will have it
259  * Expression::typeCheck() function called from all its references,
260  * but we also want to check it here globally, so we do
261  * typechecking using a proper focus. */
262  if((*vit)->type == VariableDeclaration::ExternalVariable)
263  continue;
264 
265  pDebug() << "----- Global Variable Typecheck -----";
266  Q_ASSERT((*vit)->expression());
267  /* We supply ZeroOrMoreItems, meaning the variable can evaluate to anything. */
268  // FIXME which is a source to bugs
269  // TODO What about compressing variables?
270  const Expression::Ptr
271  nev((*vit)->expression()->typeCheck(context, CommonSequenceTypes::ZeroOrMoreItems));
273  pDebug() << "------------------------------";
274  }
275  }
276 
277  /* Do all tests specific to XSL-T. */
278  if(lang == QXmlQuery::XSLT20)
279  {
280  /* Type check and compress named templates. */
281  {
282  pDebug() << "Have " << info->namedTemplates.count() << "named templates";
283 
284  QMutableHashIterator<QXmlName, Template::Ptr> it(info->namedTemplates);
285 
286  while(it.hasNext())
287  {
288  it.next();
289  processNamedTemplate(it.key(), it.value()->body, TemplateInitial);
290 
291  it.value()->body = it.value()->body->typeCheck(context, CommonSequenceTypes::ZeroOrMoreItems);
292  processNamedTemplate(it.key(), it.value()->body, TemplateTypeCheck);
293 
294  it.value()->body = it.value()->body->compress(context);
295  processNamedTemplate(it.key(), it.value()->body, TemplateCompress);
296 
297  it.value()->compileParameters(context);
298  }
299  }
300 
301  /* Type check and compress template rules. */
302  {
303  QHashIterator<QXmlName, TemplateMode::Ptr> it(info->templateRules);
304 
305  /* Since a pattern can exist of AxisStep, its typeCheck() stage
306  * requires a focus. In the case that we're invoked with a name but
307  * no focus, this will yield a compile error, unless we declare a
308  * focus manually. This only needs to be done for the pattern
309  * expression, since the static type of the pattern is used as the
310  * static type for the focus of the template body. */
311  StaticContext::Ptr patternContext;
312  if(hasExternalFocus)
313  patternContext = context;
314  else
315  patternContext = StaticContext::Ptr(new StaticFocusContext(BuiltinTypes::node, context));
316 
317  /* For each template pattern. */
318  while(it.hasNext())
319  {
320  it.next();
321  const TemplateMode::Ptr &mode = it.value();
322  const int len = mode->templatePatterns.count();
323  TemplatePattern::ID currentTemplateID = -1;
324  bool hasDoneItOnce = false;
325 
326  /* For each template pattern. */
327  for(int i = 0; i < len; ++i)
328  {
329  /* We can't use references for these two members, since we
330  * assign to them. */
331  const TemplatePattern::Ptr &pattern = mode->templatePatterns.at(i);
332  Expression::Ptr matchPattern(pattern->matchPattern());
333 
334  processTemplateRule(pattern->templateTarget()->body,
335  pattern, mode->name(), TemplateInitial);
336 
337  matchPattern = matchPattern->typeCheck(patternContext, CommonSequenceTypes::ZeroOrMoreItems);
338  matchPattern = matchPattern->compress(patternContext);
339  pattern->setMatchPattern(matchPattern);
340 
341  if(currentTemplateID == -1 && hasDoneItOnce)
342  {
343  currentTemplateID = pattern->id();
344  continue;
345  }
346  else if(currentTemplateID == pattern->id() && hasDoneItOnce)
347  {
348  hasDoneItOnce = false;
349  continue;
350  }
351 
352  hasDoneItOnce = true;
353  currentTemplateID = pattern->id();
354  Expression::Ptr body(pattern->templateTarget()->body);
355 
356  /* Patterns for a new template has started, we must
357  * deal with the body & parameters. */
358  {
359  /* TODO type is wrong, it has to be the union of all
360  * patterns. */
361  const StaticContext::Ptr focusContext(new StaticFocusContext(matchPattern->staticType()->itemType(),
362  context));
363  body = body->typeCheck(focusContext, CommonSequenceTypes::ZeroOrMoreItems);
364 
365  pattern->templateTarget()->compileParameters(focusContext);
366  }
367 
368  processTemplateRule(body, pattern, mode->name(), TemplateTypeCheck);
369 
370  body = body->compress(context);
371 
372  pattern->templateTarget()->body = body;
373  processTemplateRule(body, pattern, mode->name(), TemplateCompress);
374  }
375 
376  mode->finalize();
377  }
378  }
379 
380  /* Add templates in mode #all to all other modes.
381  *
382  * We do this after the templates has been typechecked and compressed,
383  * since otherwise it will be done N times for the built-in templates,
384  * where N is the count of different templates, instead of once. */
385  {
388  const TemplateMode::Ptr &modeAll = info->templateRules[nameModeAll];
389 
390  Q_ASSERT_X(modeAll, Q_FUNC_INFO,
391  "We should at least have the builtin templates.");
392  QHashIterator<QXmlName, TemplateMode::Ptr> it(info->templateRules);
393 
394  while(it.hasNext())
395  {
396  it.next();
397 
398  /* Don't add mode #all to mode #all. */
399  if(it.key() == nameModeAll)
400  continue;
401 
402  it.value()->addMode(modeAll);
403  }
404  }
405  }
406 
407  /* Type check and compress the query body. */
408  {
409  pDebug() << "----- Initial AST build. -----";
411  pDebug() << "------------------------------";
412 
413  pDebug() << "----- Type Check -----";
414  registerLastPath(result);
415  result->rewrite(result, result->typeCheck(context, requiredType), context);
417  pDebug() << "------------------------------";
418 
419  pDebug() << "----- Compress -----";
420  result->rewrite(result, result->compress(context), context);
422  pDebug() << "------------------------------";
423  }
424 
425  return result;
426 }
bool isValid() const
Returns true if the URL is valid; otherwise returns false.
Definition: qurl.cpp:4303
static mach_timebase_info_data_t info
QString formatKeyword(const QString &keyword)
static const SequenceType::Ptr ZeroOrMoreItems
#define it(className, varName)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
friend class const_iterator
Definition: qlist.h:264
QExplicitlySharedDataPointer< Template > Ptr
Definition: qtemplate_p.h:89
QExplicitlySharedDataPointer< TemplatePattern > Ptr
The QSourceLocation class identifies a location in a resource by URI, line, and column.
static const AnyNodeType::Ptr node
QExplicitlySharedDataPointer< Expression > Ptr
A smart pointer wrapping mutable Expression instances.
QExplicitlySharedDataPointer< ItemType > Ptr
Definition: qitemtype_p.h:88
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way...
Definition: qxmlname.h:58
QExplicitlySharedDataPointer< ParserContext > Ptr
QExplicitlySharedDataPointer< TemplateMode > Ptr
virtual void processTreePass(const Expression::Ptr &tree, const CompilationStage stage)
const T * const_iterator
The QVector::const_iterator typedef provides an STL-style const iterator for QVector and QStack...
Definition: qvector.h:245
QExplicitlySharedDataPointer< Tokenizer > Ptr
Definition: qtokenizer_p.h:163
QExplicitlySharedDataPointer< StaticContext > Ptr
int XPathparse(QPatternist::ParserContext *const info)
The entry point to the parser.
static const KeyPair *const end
virtual void processTemplateRule(const Expression::Ptr &body, const TemplatePattern::Ptr &pattern, const QXmlName &mode, const TemplateCompilationStage stage)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static void registerLastPath(const Expression::Ptr &operand)
virtual void processNamedTemplate(const QXmlName &name, const Expression::Ptr &tree, const TemplateCompilationStage stage)
QNoDebug pDebug()
Definition: qdebug_p.h:99
#define Q_FUNC_INFO
Definition: qglobal.h:1871

◆ processNamedTemplate()

void QPatternist::ExpressionFactory::processNamedTemplate ( const QXmlName name,
const Expression::Ptr tree,
const TemplateCompilationStage  stage 
)
protectedvirtual

Definition at line 461 of file qexpressionfactory.cpp.

Referenced by createExpression().

464 {
465  Q_UNUSED(name);
466  Q_UNUSED(tree);
467  Q_UNUSED(stage);
468 }
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729

◆ processTemplateRule()

void QPatternist::ExpressionFactory::processTemplateRule ( const Expression::Ptr body,
const TemplatePattern::Ptr pattern,
const QXmlName mode,
const TemplateCompilationStage  stage 
)
protectedvirtual

Definition at line 450 of file qexpressionfactory.cpp.

Referenced by createExpression().

454 {
455  Q_UNUSED(body);
456  Q_UNUSED(pattern);
457  Q_UNUSED(mode);
458  Q_UNUSED(stage);
459 }
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729

◆ processTreePass()

void QPatternist::ExpressionFactory::processTreePass ( const Expression::Ptr tree,
const CompilationStage  stage 
)
protectedvirtual

This function is called by createExpression() each time after a pass on the AST has been completed. Under a typical compilation this function is thus called three times: after the initial build, after the Expression::typeCheck() stage, and after Expression::compress(). tree is the AST after each pass.

This mechanism is currently used for debugging, since it provides a way of introspecting what the compilation process do to the tree. The current implementation do nothing.

Definition at line 445 of file qexpressionfactory.cpp.

Referenced by createExpression().

447 {
448 }

◆ registerLastPath()

void QPatternist::ExpressionFactory::registerLastPath ( const Expression::Ptr operand)
static

Finds the last paths of a set of paths(if any) and tells the Path so, such that it can generate the code for checking XPTY0018.

Must be called before typeCheck() is called on the operand, since the typeCheck() uses the information for type checking.

Definition at line 428 of file qexpressionfactory.cpp.

Referenced by createExpression(), and QPatternist::yyparse().

429 {
430  OperandsIterator it(operand, OperandsIterator::IncludeParent);
431  Expression::Ptr next(it.next());
432 
433  while(next)
434  {
435  if(next->is(Expression::IDPath))
436  {
437  next->as<Path>()->setLast();
438  next = it.skipOperands();
439  }
440  else
441  next = it.next();
442  }
443 }
#define it(className, varName)
A Path object defines a path for use by PathView .
QExplicitlySharedDataPointer< Expression > Ptr
A smart pointer wrapping mutable Expression instances.

The documentation for this class was generated from the following files: