OpenVDB  12.0.0
AST.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file ast/AST.h
5 ///
6 /// @authors Nick Avramoussis, Richard Jones
7 ///
8 /// @brief Provides the definition for every abstract and concrete derived
9 /// class which represent a particular abstract syntax tree (AST) node
10 /// type.
11 ///
12 /// AST nodes represents a particular branch of a complete AST. Concrete
13 /// nodes can be thought of as leaf node types which hold semantic
14 /// information of a partial or complete statement or expression. A
15 /// string of AX can be fully represented by building the correct
16 /// AST structure. The AX grammar defined in axparser.y represents the
17 /// valid mapping of a tokenized string to AST nodes.
18 ///
19 /// AST node classes can either represent a "leaf-level" semantic
20 /// component of a given AX AST, or an abstract base type. The latter are
21 /// used by the parser and leaf-level AST nodes for storage of compatible
22 /// child nodes, and provide grouping of various nodes which share common
23 /// semantics. The main two types of abstract AST nodes are statements
24 /// and expressions.
25 ///
26 
27 #ifndef OPENVDB_AX_AST_HAS_BEEN_INCLUDED
28 #define OPENVDB_AX_AST_HAS_BEEN_INCLUDED
29 
30 #include "Tokens.h"
31 
32 #include <openvdb/version.h>
33 #include <openvdb/util/Assert.h>
34 
35 #include <memory>
36 #include <utility>
37 #include <vector>
38 
39 namespace openvdb {
41 namespace OPENVDB_VERSION_NAME {
42 
43 namespace ax {
44 namespace ast {
45 
46 /// @brief Forward declaration of the base Abstract Syntax Tree type.
47 /// @note Not to be confused with ast::Node types, which are the base abstract
48 /// type for all AST nodes. Tree nodes are the highest possible concrete
49 /// node type (in terms of hierarchy) which represent a full AX file.
50 /// They are always returned from the parser.
51 struct Tree;
52 
53 ////////////////////////////////////////////////////////////////////////
54 ////////////////////////////////////////////////////////////////////////
55 
56 /// @details A reference list of all abstract and concrete AST nodes in
57 /// hierarchical order (non-linear)
58 /// Abstract nodes:
59 /// - Node
60 /// - Statement
61 /// - Expression
62 /// - Variable
63 /// - ValueBase
64 ///
65 /// Concrete nodes:
66 /// - Tree
67 /// - StatementList
68 /// - Block
69 /// - Loop
70 /// - Keyword
71 /// - ConditionalStatement
72 /// - CommaOperator
73 /// - BinaryOperator
74 /// - TernaryOperator
75 /// - AssignExpression
76 /// - Crement
77 /// - UnaryOperator
78 /// - Cast
79 /// - FunctionCall
80 /// - ArrayUnpack
81 /// - ArrayPack
82 /// - Attribute
83 /// - ExternalVariable
84 /// - DeclareLocal
85 /// - Local
86 /// - Value<double/float/int32_t/int16_t/int64_t/bool>
87 /// - Value<std::string>
88 
89 ////////////////////////////////////////////////////////////////////////
90 ////////////////////////////////////////////////////////////////////////
91 
92 /// @brief The base abstract node which determines the interface and required
93 /// methods for all derived concrete nodes which comprise a valid AST.
94 /// @note All AST nodes share a few common characteristics. All constructors
95 /// typically take pointers to the abstract (pure-virtual) node types
96 /// and assume ownership of this data on successful construction. Deep
97 /// copy methods propagate down through all children of a given AST node
98 /// but have the unique behavior of ensuring parent data is updated to
99 /// the newly created parent nodes. Due to this behavior and the fact
100 /// that most nodes store unique pointers to other nodes, we've omitted
101 /// comparison and equality operators.
102 struct Node
103 {
104  using Ptr = std::shared_ptr<Node>;
105  using UniquePtr = std::unique_ptr<Node>;
106 
107  /// @brief An enumerated list of node types for all concrete node types.
108  /// These can be used for faster evaluation of a given concrete node
109  /// using the virtual function table via Node::nodetype() rather
110  /// than performing a dynamic_cast/calling Node::isType.
111  /// @note This is sometimes referred to as "manual RTTI". We use this
112  /// technique combine with single dispatch due to opting for CRTP on
113  /// the main visitor and no templated virtual method support in C++.
114  /// i.e. no way to double dispatch: visit<template T>(Visitor<T>*)
115  /// @note Abstract (pure-virtual) nodes are not listed here. Node::isType
116  /// should be used to determine if a node is of a given abstract
117  /// type.
118  enum NodeType {
145  ValueStrNode
146  };
147 
148  Node() = default;
149  virtual ~Node() = default;
150 
151  /// @brief The deep copy method for a Node
152  /// @return A deep copy of the current node and all its children
153  virtual Node* copy() const = 0;
154 
155  /// @name Name/Type
156  /// @{
157 
158  /// @brief Virtual method for accessing node type information
159  /// @note This method should be used when querying a concrete nodes type.
160  /// @return Returns the enumerated node type from the NodeType list
161  virtual NodeType nodetype() const = 0;
162 
163  /// @brief Virtual method for accessing node name information
164  /// @return Returns the node class name
165  virtual const char* nodename() const = 0;
166 
167  /// @brief Virtual method for accessing node name information
168  /// @return Returns the short node class name
169  virtual const char* subname() const = 0;
170 
171  /// @brief Virtual method for accessing a node's base class. Note that if
172  /// this is called explicitly on an instance of ast::Node (the top
173  /// most base class) a nullptr is returned. This is primarily used
174  /// by the Visitor to support hierarchical visits.
175  /// @return Returns the current node as its base class type.
176  virtual const Node* basetype() const { return nullptr; }
177 
178  /// @brief Query whether or not this node is of a specific (derived) type.
179  /// This method should be used to check if a node is of a particular
180  /// abstract type. When checking concrete types, it's generally
181  /// more efficient to check the return value of Node::nodetype()
182  /// @tparam NodeT The node type to query against.
183  /// @return True if this node is of the given type, false otherwise.
184  template <typename NodeT>
185  inline bool isType() const {
186  return dynamic_cast<const NodeT*>(this);
187  }
188 
189  /// @}
190 
191  /// @name Child Queries
192  /// @{
193 
194  /// @brief Virtual method for accessing child information. Returns the
195  /// number of children a given AST node owns.
196  /// @return The number of children this node owns.
197  virtual size_t children() const = 0;
198 
199  /// @brief Virtual method for accessing child information. Returns a const
200  /// pointer to a child node at the given index. If the index is out
201  /// of range, a nullptr is returned.
202  /// @note This may still return a nullptr even if the given index is valid
203  /// if the child node has not been created.
204  /// @param index The child index to query
205  /// @return A Pointer to the child node, or a nullptr if none exists.
206  virtual const Node* child(const size_t index) const = 0;
207 
208  /// @brief Returns the child index of this node in relation to its parent,
209  /// or -1 if no valid index is found (usually representing the top
210  /// most node (i.e. Tree)
211  /// @return The child index of this node
212  inline int64_t childidx() const
213  {
214  const Node* p = this->parent();
215  if (!p) return -1;
216  size_t i = 0;
217  const size_t count = p->children();
218  for (; i < count; ++i) {
219  if (p->child(i) == this) break;
220  }
221  if (i == count) return -1;
222  return static_cast<int64_t>(i);
223  }
224 
225  /// @}
226 
227  /// @name Replacement
228  /// @{
229 
230  /// @brief In place replacement. Attempts to replace this node at its
231  /// specific location within its Abstract Syntax Tree. On a
232  /// successful replacement, this node is destroyed, the provided
233  /// node is inserted in its place and ownership is transferred to the
234  /// parent node. No further calls to this node can be made on
235  /// successful replacements.
236  /// @note A replacement will fail if this node is the top most node within
237  /// an AST hierarchy or if the provided node type is not a
238  /// compatible type for the required abstract storage. For example,
239  /// if this node is an Attribute being held on a BinaryOperator,
240  /// only concrete nodes derived from an Expression can be used as a
241  /// replacement.
242  /// @note This method will dynamic_cast the provided node to check to see
243  /// if it's a compatible type.
244  /// @param node The node to insert on a successful replacement.
245  /// @return True if the replacement was successful, resulting in destruction
246  /// of this class and ownership transferal of the provided node.
247  /// False otherwise, where this and the provided node are unchanged.
248  inline bool replace(Node* node)
249  {
250  const int64_t idx = this->childidx();
251  if (idx == -1) return false; // avoid second vcall
252  return this->parent()->replacechild(idx, node);
253  }
254 
255  /// @brief Virtual method that attempted to replace a child at a given
256  /// index with a provided node type.
257  /// @note See Node::replace for a more detailed description
258  /// @param index The child index where a replacement should be attempted
259  /// @param node The node to insert on a successful replacement.
260  /// @return True if the replacement was successful, false otherwise
261  inline virtual bool replacechild(const size_t index, Node* node);
262 
263  /// @}
264 
265  /// @name Parent
266  /// @{
267 
268  /// @brief Access a const pointer to this nodes parent
269  /// @note Can be a nullptr if this is the top most node in an AST (usually
270  /// a Tree)
271  /// @return A const pointer to this node's parent node
272  inline const Node* parent() const { return mParent; }
273 
274  /// @brief Set this node's parent. This is used during construction of an
275  /// AST and should not be used. @todo Make this private.
276  /// @param parent The parent to set
277  inline void setParent(Node* parent) {
278 #ifndef NDEBUG
279  [[maybe_unused]] bool hasChild = false;
280  for (size_t i = 0; i < parent->children(); ++i)
281  hasChild |= parent->child(i) == this;
282  OPENVDB_ASSERT(hasChild);
283 #endif
284  mParent = parent;
285  }
286 
287 private:
288  /// @brief Access a non const pointer to this nodes parent. Used by
289  /// replacement methods.
290  /// @note Can be a nullptr if this is the top most node in an AST (usually
291  /// a Tree)
292  /// @return A non-const pointer to this nodes parent node
293  inline Node* parent() { return mParent; }
294 
295  /// @}
296 
297  Node* mParent = nullptr;
298 };
299 
300 inline bool Node::replacechild(const size_t, Node*) { return false; }
301 
302 
303 ////////////////////////////////////////////////////////////////////////
304 ////////////////////////////////////////////////////////////////////////
305 
306 /// Abstract (pure-virtual) AST nodes
307 
308 /// @brief Statements are anything that can make up a line, i.e. everything
309 /// in between semicolons. Likewise to their base ast::Node class,
310 /// currently every concrete AST node is either directly or indirectly
311 /// a derived statement type. They hold no class data.
312 struct Statement : public Node
313 {
314  using UniquePtr = std::unique_ptr<Statement>;
315  ~Statement() override = default;
316  virtual Statement* copy() const override = 0;
317  const Node* basetype() const override { return this; }
318 };
319 
320 /// @brief Expressions are comprised of full or potentially partial parts of a
321 /// full statement that may not necessary make up an entire valid
322 /// statement on their own. For example, while a Binary Operator such as
323 /// "3 + 5;"" is a valid statement on its own, the full statement
324 /// "3 + 5 + 6;" must be broken down into two expressions which together
325 /// form the statement as well as determining precedence.
326 struct Expression : public Statement
327 {
328  using UniquePtr = std::unique_ptr<Expression>;
329  ~Expression() override = default;
330  virtual Expression* copy() const override = 0;
331  const Statement* basetype() const override { return this; }
332 };
333 
334 /// @brief Variables are a base type for Locals, Attributes and
335 /// ExternalVariables. Unlike other abstract types, they also consolidate
336 /// data for the derived types.
337 struct Variable : public Expression
338 {
339  using UniquePtr = std::unique_ptr<Variable>;
340 
341  Variable(const std::string& name)
342  : Expression(), mName(name) {}
343  Variable(const Variable& other)
344  : Expression(), mName(other.mName) {}
345  ~Variable() override = default;
346 
347  virtual Variable* copy() const override = 0;
348  const Expression* basetype() const override { return this; }
349  //
350  size_t children() const override { return 0; }
351  const Node* child(const size_t) const override { return nullptr; }
352  //
353  inline const std::string& name() const { return mName; }
354 
355 private:
356  const std::string mName;
357 };
358 
359 /// @brief ValueBases are a base class for anything that holds a value (literal).
360 /// Derived classes store the actual typed values
361 struct ValueBase : public Expression
362 {
363  using UniquePtr = std::unique_ptr<ValueBase>;
364  ~ValueBase() override = default;
365  virtual Expression* copy() const override = 0;
366  const Expression* basetype() const override { return this; }
367  //
368  size_t children() const override { return 0; }
369  const Node* child(const size_t) const override { return nullptr; }
370 };
371 
372 
373 ////////////////////////////////////////////////////////////////////////
374 ////////////////////////////////////////////////////////////////////////
375 
376 /// Concrete AST nodes
377 
378 /// @brief A StatementList is derived from a Statement and comprises of
379 /// combinations of multiple statements. This could represent either
380 /// a list of statements of different types but in practice will likely
381 /// represent a ',' separated list of the same type i.e.
382 /// 'int i = 1, j = 1;'.
383 /// @note Statements held by the list are guaranteed to be valid (non null).
384 /// nullptrs added to the list are implicitly dropped.
385 /// @todo Consider combination with Block
386 struct StatementList : public Statement
387 {
388  using UniquePtr = std::unique_ptr<StatementList>;
389 
390  /// @brief Construct a new StatementList with an empty list
391  StatementList() : mList() {}
392  /// @brief Construct a new StatementList with a single statement,
393  /// transferring ownership of the statement to the statement list
394  /// and updating parent data on the statement. If the statement is a
395  /// nullptr, it is ignored.
396  /// @param statement The statement to construct from
398  : mList() {
399  this->addStatement(statement);
400  }
401  /// @brief Construct a new StatementList from a vector of statements,
402  /// transferring ownership of all valid statements to the statement
403  /// list and updating parent data on the statement. Only valid (non
404  /// null) statements are added to the statement list.
405  /// @param statements The vector of statements to construct from
406  StatementList(const std::vector<Statement*>& statements)
407  : mList() {
408  for (Statement* statement : statements) {
409  this->addStatement(statement);
410  }
411  }
412  /// @brief Deep copy constructor for a StatementList, performing a deep
413  /// copy on every held statement, ensuring parent information is
414  /// updated.
415  /// @param other A const reference to another statement list to deep copy
416  StatementList(const StatementList& other) : mList() {
417  for (const Statement::UniquePtr& stmnt : other.mList) {
418  this->addStatement(stmnt->copy());
419  }
420  }
421  ~StatementList() override = default;
422 
423  /// @copybrief Node::copy()
424  StatementList* copy() const override { return new StatementList(*this); }
425  /// @copybrief Node::nodetype()
426  NodeType nodetype() const override { return Node::StatementListNode; }
427  /// @copybrief Node::nodename()
428  const char* nodename() const override { return "statement list"; }
429  /// @copybrief Node::subname()
430  const char* subname() const override { return "stml"; }
431  /// @copybrief Node::basetype()
432  const Statement* basetype() const override { return this; }
433 
434  /// @copybrief Node::children()
435  size_t children() const override final { return this->size(); }
436  /// @copybrief Node::child()
437  const Statement* child(const size_t i) const override final {
438  if (i >= mList.size()) return nullptr;
439  return mList[i].get();
440  }
441  /// @copybrief Node::replacechild()
442  inline bool replacechild(const size_t i, Node* node) override final {
443  if (mList.size() <= i) return false;
444  Expression* expr = dynamic_cast<Expression*>(node);
445  if (!expr) return false;
446  mList[i].reset(expr);
447  mList[i]->setParent(this);
448  return true;
449  }
450 
451  /// @brief Alias for StatementList::children
452  inline size_t size() const { return mList.size(); }
453  /// @brief Adds a statement to this statement list, transferring ownership to the
454  /// statement list and updating parent data on the statement. If the
455  /// statement is a nullptr, it is ignored.
456  inline void addStatement(Statement* stmnt) {
457  if (stmnt) {
458  mList.emplace_back(stmnt);
459  stmnt->setParent(this);
460  }
461  }
462 private:
463  std::vector<Statement::UniquePtr> mList;
464 };
465 
466 /// @brief A Block node represents a scoped list of statements. It may comprise
467 /// of 0 or more statements, and specifically indicates that a new scope
468 /// is activated, typically represented by curly braces. Note that a
469 /// block does not alway have to be encapsulated by curly braces, but
470 /// always represents a new scope.
471 /// @note Statements held by the block are guaranteed to be valid (non null).
472 /// nullptrs added to the block are implicitly dropped.
473 /// @note While closely linked, it's important to differentiate between this
474 /// class and an llvm::BasicBlock.
475 /// @todo Consider combination with StatementList
476 struct Block : public Statement
477 {
478  using UniquePtr = std::unique_ptr<Block>;
479 
480  /// @brief Construct a new Block with an empty list
481  Block() : mList() {}
482  /// @brief Construct a new Block with a single statement, transferring
483  /// ownership of the statement to the block and updating parent
484  /// data on the statement. If the statement is a nullptr, it is
485  /// ignored.
486  /// @param statement The statement to construct from
487  Block(Statement* statement)
488  : mList() {
489  this->addStatement(statement);
490  }
491  /// @brief Construct a new Block from a vector of statements, transferring
492  /// ownership of all valid statements to the block and updating
493  /// parent data on the statement. Only valid (non null) statements
494  /// are added to the block.
495  /// @param statements The vector of statements to construct from
496  Block(const std::vector<Statement*>& statements)
497  : mList() {
498  for (Statement* statement : statements) {
499  this->addStatement(statement);
500  }
501  }
502  /// @brief Deep copy constructor for a Block, performing a deep copy on
503  /// every held statement, ensuring parent information is updated.
504  /// @param other A const reference to another block to deep copy
505  Block(const Block& other) : mList() {
506  for (const Statement::UniquePtr& stmnt : other.mList) {
507  this->addStatement(stmnt->copy());
508  }
509  }
510  ~Block() override = default;
511 
512  /// @copybrief Node::copy()
513  Block* copy() const override final { return new Block(*this); }
514  /// @copybrief Node::nodetype()
515  NodeType nodetype() const override { return Node::BlockNode; }
516  /// @copybrief Node::nodename()
517  const char* nodename() const override { return "scoped block"; }
518  /// @copybrief Node::subname()
519  const char* subname() const override { return "blk"; }
520  /// @copybrief Node::basetype()
521  const Statement* basetype() const override { return this; }
522 
523  /// @copybrief Node::children()
524  size_t children() const override final { return this->size(); }
525  /// @copybrief Node::child()
526  const Statement* child(const size_t i) const override final {
527  if (i >= mList.size()) return nullptr;
528  return mList[i].get();
529  }
530  /// @copybrief Node::replacechild()
531  inline bool replacechild(const size_t i, Node* node) override final {
532  if (mList.size() <= i) return false;
533  Expression* expr = dynamic_cast<Expression*>(node);
534  if (!expr) return false;
535  mList[i].reset(expr);
536  mList[i]->setParent(this);
537  return true;
538  }
539 
540  /// @brief Alias for Block::children
541  inline size_t size() const { return mList.size(); }
542  /// @brief Adds a statement to this block, transferring ownership to the
543  /// block and updating parent data on the statement. If the
544  /// statement is a nullptr, it is ignored.
545  inline void addStatement(Statement* stmnt) {
546  if (stmnt) {
547  mList.emplace_back(stmnt);
548  stmnt->setParent(this);
549  }
550  }
551 private:
552  std::vector<Statement::UniquePtr> mList;
553 };
554 
555 /// @brief A Tree is the highest concrete (non-abstract) node in the entire AX
556 /// AST hierarchy. It represents an entire conversion of a valid AX
557 /// string.
558 /// @note A tree is the only node type which has typedefs for use as a shared
559 /// pointer. All other nodes are expected to be handled through unique
560 /// pointers to infer ownership.
561 /// @todo Replace block with StatementList
562 struct Tree : public Node
563 {
564  using Ptr = std::shared_ptr<Tree>;
565  using ConstPtr = std::shared_ptr<const Tree>;
566  using UniquePtr = std::unique_ptr<Tree>;
567 
568  /// @brief Construct a new Tree from a given Block, transferring ownership
569  /// of the Block to the tree and updating parent data on the Block.
570  /// @note The provided Block must be a valid pointer (non-null)
571  /// @param block The Block to construct from
572  Tree(Block* block = new Block())
573  : mBlock(block) {
574  mBlock->setParent(this);
575  }
576  /// @brief Deep copy constructor for a Tree, performing a deep copy on
577  /// the held Block, ensuring parent information is updated.
578  /// @param other A const reference to another Tree to deep copy
579  Tree(const Tree& other)
580  : mBlock(new Block(*other.mBlock)) {
581  mBlock->setParent(this);
582  }
583  ~Tree() override = default;
584 
585  /// @copybrief Node::copy()
586  Tree* copy() const override final { return new Tree(*this); }
587  /// @copybrief Node::nodetype()
588  NodeType nodetype() const override { return Node::TreeNode; }
589  /// @copybrief Node::nodename()
590  const char* nodename() const override { return "tree"; }
591  /// @copybrief Node::subname()
592  const char* subname() const override { return "tree"; }
593  /// @copybrief Node::basetype()
594  const Node* basetype() const override { return this; }
595 
596  /// @copybrief Node::children()
597  size_t children() const override final { return 1; }
598  /// @copybrief Node::child()
599  const Block* child(const size_t i) const override final {
600  if (i == 0) return mBlock.get();
601  return nullptr;
602  }
603 private:
604  Block::UniquePtr mBlock;
605 };
606 
607 struct CommaOperator : public Expression
608 {
609  using UniquePtr = std::unique_ptr<CommaOperator>;
610 
611  /// @brief Construct a new CommaOperator with an expr set
612  CommaOperator() : mExpressions() {}
613  /// @brief Construct a new CommaOperator with a single expression,
614  /// transferring ownership of the expression to the CommaOperator
615  /// and updating parent data on the expression. If the expression is
616  /// a nullptr, it is ignored.
617  /// @param expression The Expression to construct from
619  : mExpressions() {
620  this->append(expression);
621  }
622  /// @brief Construct a new CommaOperator from a vector of expression,
623  /// transferring ownership of all valid expression to the
624  /// CommaOperator and updating parent data on the statement. Only
625  /// valid (non null) expression are added to the block.
626  /// @param expressions The vector of expressions to construct from
627  CommaOperator(const std::vector<Expression*>& expressions)
628  : mExpressions() {
629  mExpressions.reserve(expressions.size());
630  for (Expression* expression : expressions) {
631  this->append(expression);
632  }
633  }
634  /// @brief Deep copy constructor for an CommaOperator, performing a deep
635  /// copy on every held expression, ensuring parent information is
636  /// updated.
637  /// @param other A const reference to another CommaOperator to deep copy
639  : mExpressions() {
640  mExpressions.reserve(other.mExpressions.size());
641  for (const Expression::UniquePtr& expr : other.mExpressions) {
642  this->append(expr->copy());
643  }
644  }
645  ~CommaOperator() override = default;
646 
647  /// @copybrief Node::copy()
648  CommaOperator* copy() const override final {
649  return new CommaOperator(*this);
650  }
651  /// @copybrief Node::nodetype()
652  NodeType nodetype() const override { return Node::CommaOperatorNode; }
653  /// @copybrief Node::nodename()
654  const char* nodename() const override { return "comma"; }
655  /// @copybrief Node::subname()
656  const char* subname() const override { return "comma"; }
657  /// @copybrief Node::basetype()
658  const Expression* basetype() const override { return this; }
659 
660  /// @copybrief Node::children()
661  size_t children() const override final { return this->size(); }
662  /// @copybrief Node::child()
663  const Expression* child(const size_t i) const override final {
664  if (i >= mExpressions.size()) return nullptr;
665  return mExpressions[i].get();
666  }
667  /// @copybrief Node::replacechild()
668  inline bool replacechild(const size_t i, Node* node) override final {
669  if (mExpressions.size() <= i) return false;
670  Expression* expr = dynamic_cast<Expression*>(node);
671  mExpressions[i].reset(expr);
672  mExpressions[i]->setParent(this);
673  return true;
674  }
675 
676  /// @brief Alias for CommaOperator::children
677  inline size_t size() const { return mExpressions.size(); }
678  /// @brief Query whether this Expression list holds any valid expressions
679  /// @return True if this node if empty, false otherwise
680  inline bool empty() const { return mExpressions.empty(); }
681  /// @brief Append an expression to this CommaOperator, transferring
682  /// ownership to the CommaOperator and updating parent data on the
683  /// expression. If the expression is a nullptr, it is ignored.
684  inline void append(Expression* expr) {
685  if (expr) {
686  mExpressions.emplace_back(expr);
687  expr->setParent(this);
688  }
689  }
690 private:
691  std::vector<Expression::UniquePtr> mExpressions;
692 };
693 
694 /// @brief Loops represent for, while and do-while loop constructs.
695 /// These all consist of a condition - evaluated to determine if loop
696 /// iteration should continue, and a body which is the logic to be
697 /// repeated. For loops also have initial statements which are evaluated
698 /// prior to loop execution (at loop scope) and commonly used to
699 /// set up iterators, and iteration expressions which are evaluated
700 /// between iterations after the body and before the condition.
701 /// Both conditions and initial statements can be declarations or
702 /// expressions, so are Statements, and iteration expressions can
703 /// consist of multiple expressions. The loop body is a Block defining
704 /// its own scope (encapsulated by initial statement scope for for-loops).
705 /// @note Only for-loops should have initial statements and/or iteration
706 /// expressions. Also for-loops allow empty conditions to be given by
707 /// the user, this is replaced with a 'true' expression in the parser.
708 struct Loop : public Statement
709 {
710  using UniquePtr = std::unique_ptr<Loop>;
711 
712  /// @brief Construct a new Loop with the type defined by a
713  /// tokens::LoopToken, a condition Statement, a Block representing
714  /// the body and for for-loops an optional initial Statement and
715  /// iteration Expression. Ownership of all arguments is
716  /// transferred to the Loop. All arguments have their parent data
717  /// updated.
718  /// @param loopType The type of loop - for, while or do-while.
719  /// @param condition The condition Statement to determine loop repetition
720  /// @param body The Block to be repeated
721  /// @param init The (optional) for-loop initial Statement.
722  /// @param iter The (optional) for-loop iteration Expression.
723  Loop(const tokens::LoopToken loopType,
724  Statement* condition,
725  Block* body,
726  Statement* init = nullptr,
727  Expression* iter = nullptr)
728  : mLoopType(loopType)
729  , mConditional(condition)
730  , mBody(body)
731  , mInitial(init)
732  , mIteration(iter) {
733  OPENVDB_ASSERT(mConditional);
734  OPENVDB_ASSERT(mBody);
735  mConditional->setParent(this);
736  mBody->setParent(this);
737  if (mInitial) {
739  mInitial->setParent(this);
740  }
741  if (mIteration) {
743  mIteration->setParent(this);
744  }
745  }
746  /// @brief Deep copy constructor for an Loop, performing a deep copy on the
747  /// condition, body and initial Statement/iteration Expression
748  /// if they exist, ensuring parent information is updated.
749  /// @param other A const reference to another Loop to deep copy
750  Loop(const Loop& other)
751  : mLoopType(other.mLoopType)
752  , mConditional(other.mConditional->copy())
753  , mBody(other.mBody->copy())
754  , mInitial(other.hasInit() ? other.mInitial->copy() : nullptr)
755  , mIteration(other.hasIter() ? other.mIteration->copy() : nullptr) {
756  mConditional->setParent(this);
757  mBody->setParent(this);
758  if (mInitial) {
760  mInitial->setParent(this);
761  }
762  if (mIteration) {
764  mIteration->setParent(this);
765  }
766  }
767  ~Loop() override = default;
768 
769  /// @copybrief Node::copy()
770  Loop* copy() const override final { return new Loop(*this); }
771  /// @copybrief Node::nodetype()
772  NodeType nodetype() const override { return Node::LoopNode; }
773  /// @copybrief Node::nodename()
774  const char* nodename() const override { return "loop"; }
775  /// @copybrief Node::subname()
776  const char* subname() const override { return "loop"; }
777  /// @copybrief Node::basetype()
778  const Statement* basetype() const override { return this; }
779 
780  /// @copybrief Node::children()
781  size_t children() const override final { return 4; }
782  /// @copybrief Node::child()
783  const Statement* child(const size_t i) const override final {
784  if (i == 0) return mConditional.get();
785  if (i == 1) return mBody.get();
786  if (i == 2) return mInitial.get();
787  if (i == 3) return mIteration.get();
788  return nullptr;
789  }
790  /// @copybrief Node::replacechild()
791  inline bool replacechild(const size_t i, Node* node) override final
792  {
793  if (i == 0 || i == 2) {
794  Statement* stmt = dynamic_cast<Statement*>(node);
795  if (!stmt) return false;
796  if (i == 0) {
797  mConditional.reset(stmt);
798  mConditional->setParent(this);
799  }
800  else {
801  mInitial.reset(stmt);
802  mInitial->setParent(this);
803  }
804  return true;
805  }
806  else if (i == 1) {
807  Block* blk = dynamic_cast<Block*>(node);
808  if (!blk) return false;
809  mBody.reset(blk);
810  mBody->setParent(this);
811  return true;
812  }
813  else if (i == 3) {
814  Expression* expr = dynamic_cast<Expression*>(node);
815  if (!expr) return false;
816  mIteration.reset(expr);
817  mIteration->setParent(expr);
818  return true;
819  }
820  return false;
821  }
822 
823  /// @brief Query the type of loop held on this node.
824  /// @return The loop type as a tokens::LoopToken
825  inline tokens::LoopToken loopType() const { return mLoopType; }
826  /// @brief Query if this Loop has a valid initial statement
827  /// @return True if a valid initial statement exists, false otherwise
828  inline bool hasInit() const { return static_cast<bool>(this->initial()); }
829  /// @brief Query if this Loop has a valid iteration expression list
830  /// @return True if a valid iteration list exists, false otherwise
831  inline bool hasIter() const { return static_cast<bool>(this->iteration()); }
832  /// @brief Access a const pointer to the Loop condition as an abstract
833  /// statement.
834  /// @return A const pointer to the condition as a statement
835  const Statement* condition() const { return mConditional.get(); }
836  /// @brief Access a const pointer to the Loop body as a Block.
837  /// @return A const pointer to the body Block
838  const Block* body() const { return mBody.get(); }
839  /// @brief Access a const pointer to the Loop initial statement as an
840  /// abstract statement.
841  /// @return A const pointer to the initial statement as a statement
842  const Statement* initial() const { return mInitial.get(); }
843  /// @brief Access a const pointer to the Loop iteration Expression
844  /// @return A const pointer to the iteration Expression
845  const Expression* iteration() const { return mIteration.get(); }
846 
847 private:
848  const tokens::LoopToken mLoopType;
849  Statement::UniquePtr mConditional;
850  Block::UniquePtr mBody;
851  Statement::UniquePtr mInitial;
852  Expression::UniquePtr mIteration;
853 };
854 
855 /// @brief ConditionalStatements represents all combinations of 'if', 'else'
856 /// and 'else if' syntax and semantics. A single ConditionalStatement
857 /// only ever represents up to two branches; an 'if' (true) and an
858 /// optional 'else' (false). ConditionalStatements are nested within
859 /// the second 'else' branch to support 'else if' logic. As well as both
860 /// 'if' and 'else' branches, a ConditionalStatement also holds an
861 /// Expression related to its primary condition.
862 /// @note The first 'if' branch is referred to as the 'true' branch. The
863 /// second 'else' branch is referred to as the 'false' branch.
865 {
866  using UniquePtr = std::unique_ptr<ConditionalStatement>;
867 
868  /// @brief Construct a new ConditionalStatement with an Expression
869  /// representing the primary condition, a Block representing the
870  /// 'true' branch and an optional Block representing the 'false'
871  /// branch. Ownership of all arguments is transferred to the
872  /// ConditionalStatement. All arguments have their parent data
873  /// updated.
874  /// @param conditional The Expression to construct the condition from
875  /// @param trueBlock The Block to construct the true branch from
876  /// @param falseBlock The (optional) Block to construct the false branch
877  /// from
879  Block* trueBlock,
880  Block* falseBlock = nullptr)
881  : mConditional(conditional)
882  , mTrueBranch(trueBlock)
883  , mFalseBranch(falseBlock) {
884  OPENVDB_ASSERT(mConditional);
885  OPENVDB_ASSERT(mTrueBranch);
886  mConditional->setParent(this);
887  mTrueBranch->setParent(this);
888  if (mFalseBranch) mFalseBranch->setParent(this);
889  }
890  /// @brief Deep copy constructor for an ConditionalStatement, performing a
891  /// deep copy on the condition and both held branches (Blocks),
892  /// ensuring parent information is updated.
893  /// @param other A const reference to another ConditionalStatement to deep
894  /// copy
896  : mConditional(other.mConditional->copy())
897  , mTrueBranch(other.mTrueBranch->copy())
898  , mFalseBranch(other.hasFalse() ? other.mFalseBranch->copy() : nullptr) {
899  mConditional->setParent(this);
900  mTrueBranch->setParent(this);
901  if (mFalseBranch) mFalseBranch->setParent(this);
902  }
903  ~ConditionalStatement() override = default;
904 
905  /// @copybrief Node::copy()
906  ConditionalStatement* copy() const override final {
907  return new ConditionalStatement(*this);
908  }
909  /// @copybrief Node::nodetype()
910  NodeType nodetype() const override { return Node::ConditionalStatementNode; }
911  /// @copybrief Node::nodename()
912  const char* nodename() const override { return "conditional statement"; }
913  /// @copybrief Node::subname()
914  const char* subname() const override { return "cond"; }
915  /// @copybrief Node::basetype()
916  const Statement* basetype() const override { return this; }
917 
918  /// @copybrief Node::children()
919  size_t children() const override final { return 3; }
920  /// @copybrief Node::child()
921  const Statement* child(const size_t i) const override final {
922  if (i == 0) return this->condition();
923  if (i == 1) return this->trueBranch();
924  if (i == 2) return this->falseBranch();
925  return nullptr;
926  }
927  /// @copybrief Node::replacechild()
928  inline bool replacechild(const size_t i, Node* node) override final
929  {
930  if (i == 0) {
931  Expression* expr = dynamic_cast<Expression*>(node);
932  if (!expr) return false;
933  mConditional.reset(expr);
934  mConditional->setParent(this);
935  return true;
936  }
937  else if (i == 1 || i == 2) {
938  Block* blk = dynamic_cast<Block*>(node);
939  if (!blk) return false;
940  if (i == 1) {
941  mTrueBranch.reset(blk);
942  mTrueBranch->setParent(this);
943  }
944  else {
945  mFalseBranch.reset(blk);
946  mFalseBranch->setParent(this);
947  }
948  return true;
949  }
950  return false;
951  }
952 
953  /// @brief Query if this ConditionalStatement has a valid 'false' branch
954  /// @return True if a valid 'false' branch exists, false otherwise
955  inline bool hasFalse() const {
956  return static_cast<bool>(this->falseBranch());
957  }
958  /// @brief Query the number of branches held by this ConditionalStatement.
959  /// This is only ever 1 or 2.
960  /// @return 2 if a valid 'true' and 'false' branch exist, 1 otherwise
961  size_t branchCount() const {
962  return this->hasFalse() ? 2 : 1;
963  }
964  /// @brief Access a const pointer to the ConditionalStatements condition
965  /// as an abstract expression.
966  /// @return A const pointer to the condition as an expression
967  const Expression* condition() const { return mConditional.get(); }
968  /// @brief Access a const pointer to the ConditionalStatements 'true'
969  /// branch as a Block
970  /// @return A const pointer to the 'true' branch
971  const Block* trueBranch() const { return mTrueBranch.get(); }
972  /// @brief Access a const pointer to the ConditionalStatements 'false'
973  /// branch as a Block
974  /// @return A const pointer to the 'false' branch
975  const Block* falseBranch() const { return mFalseBranch.get(); }
976 private:
977  Expression::UniquePtr mConditional;
978  Block::UniquePtr mTrueBranch;
979  Block::UniquePtr mFalseBranch;
980 };
981 
982 /// @brief A BinaryOperator represents a single binary operation between a
983 /// left hand side (LHS) and right hand side (RHS) expression. The
984 /// operation type is stored as a tokens::OperatorToken enumerated type
985 /// on the node. AX grammar guarantees that this token will only ever
986 /// be a valid binary operator token type when initialized by the
987 /// parser.
988 struct BinaryOperator : public Expression
989 {
990  using UniquePtr = std::unique_ptr<BinaryOperator>;
991 
992  /// @brief Construct a new BinaryOperator with a given
993  /// tokens::OperatorToken and a valid LHS and RHS expression,
994  /// transferring ownership of the expressions to the BinaryOperator
995  /// and updating parent data on the expressions.
996  /// @param left The left hand side of the binary expression
997  /// @param right The right hand side of the binary expression
998  /// @param op The binary token representing the operation to perform.
999  /// Should not be an assignment token.
1001  Expression* right,
1002  const tokens::OperatorToken op)
1003  : mLeft(left)
1004  , mRight(right)
1005  , mOperation(op) {
1006  OPENVDB_ASSERT(mLeft);
1007  OPENVDB_ASSERT(mRight);
1008  mLeft->setParent(this);
1009  mRight->setParent(this);
1010  }
1011  /// @brief Construct a new BinaryOperator with a string, delegating
1012  /// construction to the above BinaryOperator constructor.
1013  /// @param left The left hand side of the binary expression
1014  /// @param right The right hand side of the binary expression
1015  /// @param op A string representing the binary operation to perform
1017  Expression* right,
1018  const std::string& op)
1019  : BinaryOperator(left, right, tokens::operatorTokenFromName(op)) {}
1020  /// @brief Deep copy constructor for a BinaryOperator, performing a
1021  /// deep copy on both held expressions, ensuring parent information
1022  /// is updated.
1023  /// @param other A const reference to another BinaryOperator to deep copy
1025  : mLeft(other.mLeft->copy())
1026  , mRight(other.mRight->copy())
1027  , mOperation(other.mOperation) {
1028  mLeft->setParent(this);
1029  mRight->setParent(this);
1030  }
1031  ~BinaryOperator() override = default;
1032 
1033  /// @copybrief Node::copy()
1034  BinaryOperator* copy() const override final {
1035  return new BinaryOperator(*this);
1036  }
1037  /// @copybrief Node::nodetype()
1038  NodeType nodetype() const override { return Node::BinaryOperatorNode; }
1039  /// @copybrief Node::nodename()
1040  const char* nodename() const override { return "binary"; }
1041  /// @copybrief Node::subname()
1042  const char* subname() const override { return "bin"; }
1043  /// @copybrief Node::basetype()
1044  const Expression* basetype() const override { return this; }
1045  /// @copybrief Node::children()
1046  size_t children() const override final { return 2; }
1047  /// @copybrief Node::child()
1048  const Expression* child(const size_t i) const override final {
1049  if (i == 0) return mLeft.get();
1050  if (i == 1) return mRight.get();
1051  return nullptr;
1052  }
1053  /// @copybrief Node::replacechild()
1054  inline bool replacechild(const size_t i, Node* node) override final {
1055  if (i > 1) return false;
1056  Expression* expr = dynamic_cast<Expression*>(node);
1057  if (!expr) return false;
1058  if (i == 0) {
1059  mLeft.reset(expr);
1060  mLeft->setParent(this);
1061  }
1062  else if (i == 1) {
1063  mRight.reset(expr);
1064  mRight->setParent(this);
1065  }
1066  return true;
1067  }
1068 
1069  /// @brief Query the type of binary operation held on this node.
1070  /// @return The binary operation as a tokens::OperatorToken
1071  inline tokens::OperatorToken operation() const { return mOperation; }
1072  /// @brief Access a const pointer to the BinaryOperator LHS as an abstract
1073  /// expression
1074  /// @return A const pointer to the LHS expression
1075  const Expression* lhs() const { return mLeft.get(); }
1076  /// @brief Access a const pointer to the BinaryOperator RHS as an abstract
1077  /// expression
1078  /// @return A const pointer to the RHS expression
1079  const Expression* rhs() const { return mRight.get(); }
1080 private:
1081  Expression::UniquePtr mLeft;
1082  Expression::UniquePtr mRight;
1083  const tokens::OperatorToken mOperation;
1084 };
1085 
1086 /// @brief A TernaryOperator represents a ternary (conditional) expression
1087 /// 'a ? b : c' which evaluates to 'b' if 'a' is true and 'c' if 'a' is false.
1088 /// Requires 'b' and 'c' to be convertibly typed expressions, or both void.
1089 /// The 'true' expression ('b') is optional with the conditional expression 'a'
1090 /// returned if it evaluates to true, otherwise returning 'c'. Note that 'a'
1091 /// will only be evaluated once in this case.
1093 {
1094  using UniquePtr = std::unique_ptr<TernaryOperator>;
1095 
1096  /// @brief Construct a new TernaryOperator with a conditional expression
1097  /// and true (optional) and false expressions, transferring
1098  /// ownership of the expressions to the TernaryOperator
1099  /// and updating parent data on the expressions.
1100  /// @param conditional The conditional expression determining the expression
1101  /// selection
1102  /// @param trueExpression The (optional) expression evaluated if the condition
1103  /// is true
1104  /// @param falseExpression The expression evaluated if the condition is false
1106  Expression* trueExpression,
1107  Expression* falseExpression)
1108  : mConditional(conditional)
1109  , mTrueBranch(trueExpression)
1110  , mFalseBranch(falseExpression) {
1111  OPENVDB_ASSERT(mConditional);
1112  OPENVDB_ASSERT(mFalseBranch);
1113  mConditional->setParent(this);
1114  if (mTrueBranch) mTrueBranch->setParent(this);
1115  mFalseBranch->setParent(this);
1116  }
1117  /// @brief Deep copy constructor for a TernaryOperator, performing a
1118  /// deep copy on held expressions, ensuring parent information
1119  /// is updated.
1120  /// @param other A const reference to another TernaryOperator to deep copy
1122  : mConditional(other.mConditional->copy())
1123  , mTrueBranch(other.hasTrue() ? other.mTrueBranch->copy() : nullptr)
1124  , mFalseBranch(other.mFalseBranch->copy()) {
1125  mConditional->setParent(this);
1126  if (mTrueBranch) mTrueBranch->setParent(this);
1127  mFalseBranch->setParent(this);
1128  }
1129  ~TernaryOperator() override = default;
1130 
1131  /// @copybrief Node::copy()
1132  TernaryOperator* copy() const override final {
1133  return new TernaryOperator(*this);
1134  }
1135  /// @copybrief Node::nodetype()
1136  NodeType nodetype() const override { return Node::TernaryOperatorNode; }
1137  /// @copybrief Node::nodename()
1138  const char* nodename() const override { return "ternary"; }
1139  /// @copybrief Node::subname()
1140  const char* subname() const override { return "tern"; }
1141  /// @copybrief Node::basetype()
1142  const Expression* basetype() const override { return this; }
1143  /// @copybrief Node::children()
1144  size_t children() const override final { return 3; }
1145  /// @copybrief Node::child()
1146  const Expression* child(const size_t i) const override final {
1147  if (i == 0) return mConditional.get();
1148  if (i == 1) return mTrueBranch.get();
1149  if (i == 2) return mFalseBranch.get();
1150  return nullptr;
1151  }
1152  /// @copybrief Node::replacechild()
1153  inline bool replacechild(const size_t i, Node* node) override final {
1154  if (i > 2) return false;
1155  Expression* expr = dynamic_cast<Expression*>(node);
1156  if (!expr) return false;
1157  if (i == 0) {
1158  mConditional.reset(expr);
1159  mConditional->setParent(this);
1160  }
1161  else if (i == 1) {
1162  mTrueBranch.reset(expr);
1163  mTrueBranch->setParent(this);
1164  }
1165  else if (i == 2) {
1166  mFalseBranch.reset(expr);
1167  mFalseBranch->setParent(this);
1168  }
1169  return true;
1170  }
1171 
1172  /// @brief Query whether or not this has an optional if-true branch.
1173  bool hasTrue() const { return static_cast<bool>(this->trueBranch()); }
1174  /// @brief Access a const pointer to the TernaryOperator conditional as
1175  /// an abstract expression
1176  /// @return A const pointer to the conditional expression
1177  const Expression* condition() const { return mConditional.get(); }
1178  /// @brief Access a const pointer to the TernaryOperator true expression as
1179  /// an abstract expression
1180  /// @return A const pointer to the true expression
1181  const Expression* trueBranch() const { return mTrueBranch.get(); }
1182  /// @brief Access a const pointer to the TernaryOperator false expression as
1183  /// an abstract expression
1184  /// @return A const pointer to the false expression
1185  const Expression* falseBranch() const { return mFalseBranch.get(); }
1186 private:
1187  Expression::UniquePtr mConditional;
1188  Expression::UniquePtr mTrueBranch;
1189  Expression::UniquePtr mFalseBranch;
1190 };
1191 
1192 /// @brief AssignExpressions represents a similar object construction to a
1193 /// BinaryOperator. AssignExpressions can be chained together and are
1194 /// thus derived as Expressions rather than Statements.
1195 /// @note AssignExpressions can either be direct or compound assignments. The
1196 /// latter is represented by the last argument in the primary
1197 /// constructor which is expected to be a valid binary token.
1199 {
1200  using UniquePtr = std::unique_ptr<AssignExpression>;
1201 
1202  /// @brief Construct a new AssignExpression with valid LHS and RHS
1203  /// expressions, transferring ownership of the expressions to the
1204  /// AssignExpression and updating parent data on the expressions.
1205  /// @param lhs The left hand side of the assign expression
1206  /// @param rhs The right hand side of the assign expression
1207  /// @param op The compound assignment token, if any
1210  : mLHS(lhs)
1211  , mRHS(rhs)
1212  , mOperation(op) {
1213  OPENVDB_ASSERT(mLHS);
1214  OPENVDB_ASSERT(mRHS);
1215  mLHS->setParent(this);
1216  mRHS->setParent(this);
1217  }
1218  /// @brief Deep copy constructor for an AssignExpression, performing a
1219  /// deep copy on both held expressions, ensuring parent information
1220  /// is updated.
1221  /// @param other A const reference to another AssignExpression to deep
1222  /// copy
1224  : mLHS(other.mLHS->copy())
1225  , mRHS(other.mRHS->copy())
1226  , mOperation(other.mOperation) {
1227  mLHS->setParent(this);
1228  mRHS->setParent(this);
1229  }
1230  ~AssignExpression() override = default;
1231 
1232  /// @copybrief Node::copy()
1233  AssignExpression* copy() const override final {
1234  return new AssignExpression(*this);
1235  }
1236  /// @copybrief Node::nodetype()
1237  NodeType nodetype() const override { return Node::AssignExpressionNode; }
1238  /// @copybrief Node::nodename()
1239  const char* nodename() const override { return "assignment expression"; }
1240  /// @copybrief Node::subname()
1241  const char* subname() const override { return "asgn"; }
1242  /// @copybrief Node::basetype()
1243  const Expression* basetype() const override { return this; }
1244  /// @copybrief Node::children()
1245  size_t children() const override final { return 2; }
1246  /// @copybrief Node::child()
1247  const Expression* child(const size_t i) const override final {
1248  if (i == 0) return this->lhs();
1249  if (i == 1) return this->rhs();
1250  return nullptr;
1251  }
1252  /// @copybrief Node::replacechild()
1253  inline bool replacechild(const size_t i, Node* node) override final {
1254  if (i > 1) return false;
1255  Expression* expr = dynamic_cast<Expression*>(node);
1256  if (!expr) return false;
1257  if (i == 0) {
1258  mLHS.reset(expr);
1259  mLHS->setParent(this);
1260  }
1261  else if (i == 1) {
1262  mRHS.reset(expr);
1263  mRHS->setParent(this);
1264  }
1265  return true;
1266  }
1267 
1268  /// @brief Query whether or not this is a compound AssignExpression.
1269  /// Compound AssignExpressions are assignments which read and write
1270  /// to the LHS value. i.e. +=, -=, *= etc
1271  /// @return The binary operation as a tokens::OperatorToken
1272  inline bool isCompound() const { return mOperation != tokens::EQUALS; }
1273  /// @brief Query the actual operational type of this AssignExpression. For
1274  /// simple (non-compound) AssignExpressions, tokens::EQUALS is
1275  /// returned.
1276  inline tokens::OperatorToken operation() const { return mOperation; }
1277  /// @brief Access a const pointer to the AssignExpression LHS as an
1278  /// abstract expression
1279  /// @return A const pointer to the LHS expression
1280  const Expression* lhs() const { return mLHS.get(); }
1281  /// @brief Access a const pointer to the AssignExpression RHS as an
1282  //// abstract expression
1283  /// @return A const pointer to the RHS expression
1284  const Expression* rhs() const { return mRHS.get(); }
1285 private:
1286  Expression::UniquePtr mLHS;
1287  Expression::UniquePtr mRHS;
1288  const tokens::OperatorToken mOperation;
1289 };
1290 
1291 /// @brief A Crement node represents a single increment '++' and decrement '--'
1292 /// operation. As well as it's crement type, it also stores whether
1293 /// the semantics constructed a post or pre-crement i.e. ++a or a++.
1294 struct Crement : public Expression
1295 {
1296  using UniquePtr = std::unique_ptr<Crement>;
1297 
1298  /// @brief A simple enum representing the crement type.
1299  enum Operation {
1301  Decrement
1302  };
1303 
1304  /// @brief Construct a new Crement with a valid expression, transferring
1305  /// ownership of the expression to the Crement node and updating
1306  /// parent data on the expression.
1307  /// @param expr The expression to crement
1308  /// @param op The type of crement operation; Increment or Decrement
1309  /// @param post True if the crement operation is a post crement i.e. a++,
1310  /// false if the operation is a pre crement i.e. ++a
1311  Crement(Expression* expr, const Operation op, bool post)
1312  : mExpression(expr)
1313  , mOperation(op)
1314  , mPost(post) {
1315  mExpression->setParent(this);
1316  }
1317  /// @brief Deep copy constructor for a Crement, performing a deep copy on
1318  /// the underlying expressions, ensuring parent information is
1319  /// updated.
1320  /// @param other A const reference to another Crement to deep copy
1321  Crement(const Crement& other)
1322  : mExpression(other.mExpression->copy())
1323  , mOperation(other.mOperation)
1324  , mPost(other.mPost) {
1325  mExpression->setParent(this);
1326  }
1327  ~Crement() override = default;
1328 
1329  /// @copybrief Node::copy()
1330  Crement* copy() const override final { return new Crement(*this); }
1331  /// @copybrief Node::nodetype()
1332  NodeType nodetype() const override { return Node::CrementNode; }
1333  /// @copybrief Node::nodename()
1334  const char* nodename() const override { return "crement"; }
1335  /// @copybrief Node::subname()
1336  const char* subname() const override { return "crmt"; }
1337  /// @copybrief Node::basetype()
1338  const Expression* basetype() const override { return this; }
1339  //
1340  /// @copybrief Node::children()
1341  size_t children() const override final { return 1; }
1342  /// @copybrief Node::child()
1343  const Expression* child(const size_t i) const override final {
1344  if (i == 0) return this->expression();
1345  return nullptr;
1346  }
1347  /// @copybrief Node::replacechild()
1348  inline bool replacechild(const size_t i, Node* node) override final {
1349  if (i != 0) return false;
1350  Expression* expr = dynamic_cast<Expression*>(node);
1351  if (!expr) return false;
1352  mExpression.reset(expr);
1353  mExpression->setParent(this);
1354  return true;
1355  }
1356 
1357  /// @brief Query the type of the Crement operation. This does not hold
1358  /// post or pre-crement information.
1359  /// @return The Crement operation being performed. This is either an
1360  /// Crement::Increment or Crement::Decrement.
1361  inline Operation operation() const { return mOperation; }
1362  /// @brief Query if this Crement node represents an incrementation ++
1363  /// @return True if this node is performing an increment
1364  inline bool increment() const { return mOperation == Increment; }
1365  /// @brief Query if this Crement node represents an decrement --
1366  /// @return True if this node is performing an decrement
1367  inline bool decrement() const { return mOperation == Decrement; }
1368  /// @brief Query if this Crement node represents a pre crement ++a
1369  /// @return True if this node is performing a pre crement
1370  inline bool pre() const { return !mPost; }
1371  /// @brief Query if this Crement node represents a post crement a++
1372  /// @return True if this node is performing a post crement
1373  inline bool post() const { return mPost; }
1374  /// @brief Access a const pointer to the expression being crements as an
1375  /// abstract Expression
1376  /// @return A const pointer to the expression
1377  const Expression* expression() const { return mExpression.get(); }
1378 private:
1379  Expression::UniquePtr mExpression;
1380  const Operation mOperation;
1381  const bool mPost;
1382 };
1383 
1384 /// @brief A UnaryOperator represents a single unary operation on an
1385 /// expression. The operation type is stored as a tokens::OperatorToken
1386 /// enumerated type on the node. AX grammar guarantees that this token
1387 /// will only every be a valid unary operator token type when
1388 /// initialized by the parser.
1389 struct UnaryOperator : public Expression
1390 {
1391  using UniquePtr = std::unique_ptr<UnaryOperator>;
1392 
1393  /// @brief Construct a new UnaryOperator with a given tokens::OperatorToken
1394  /// and a valid expression, transferring ownership of the expression
1395  /// to the UnaryOperator and updating parent data on the expression.
1396  /// @param expr The expression to perform the unary operator on
1397  /// @param op The unary token representing the operation to perform.
1399  : mExpression(expr)
1400  , mOperation(op) {
1401  OPENVDB_ASSERT(mExpression);
1402  mExpression->setParent(this);
1403  }
1404  /// @brief Construct a new UnaryOperator with a string, delegating
1405  /// construction to the above UnaryOperator constructor.
1406  /// @param op A string representing the unary operation to perform
1407  /// @param expr The expression to perform the unary operator on
1408  UnaryOperator(Expression* expr, const std::string& op)
1409  : UnaryOperator(expr, tokens::operatorTokenFromName(op)) {}
1410  /// @brief Deep copy constructor for a UnaryOperator, performing a deep
1411  /// copy on the underlying expressions, ensuring parent information
1412  /// is updated.
1413  /// @param other A const reference to another UnaryOperator to deep copy
1415  : mExpression(other.mExpression->copy())
1416  , mOperation(other.mOperation) {
1417  mExpression->setParent(this);
1418  }
1419  ~UnaryOperator() override = default;
1420 
1421  /// @copybrief Node::copy()
1422  UnaryOperator* copy() const override final { return new UnaryOperator(*this); }
1423  /// @copybrief Node::nodetype()
1424  NodeType nodetype() const override { return Node::UnaryOperatorNode; }
1425  /// @copybrief Node::nodename()
1426  const char* nodename() const override { return "unary"; }
1427  /// @copybrief Node::subname()
1428  const char* subname() const override { return "unry"; }
1429  /// @copybrief Node::basetype()
1430  const Expression* basetype() const override { return this; }
1431  /// @copybrief Node::children()
1432  size_t children() const override final { return 1; }
1433  /// @copybrief Node::child()
1434  const Expression* child(const size_t i) const override final {
1435  if (i == 0) return this->expression();
1436  return nullptr;
1437  }
1438  /// @copybrief Node::replacechild()
1439  inline bool replacechild(const size_t i, Node* node) override final {
1440  if (i != 0) return false;
1441  Expression* expr = dynamic_cast<Expression*>(node);
1442  if (!expr) return false;
1443  mExpression.reset(expr);
1444  mExpression->setParent(this);
1445  return true;
1446  }
1447 
1448  /// @brief Query the type of unary operation held on this node.
1449  /// @return The unary operation as a tokens::OperatorToken
1450  inline tokens::OperatorToken operation() const { return mOperation; }
1451  /// @brief Access a const pointer to the UnaryOperator expression as an
1452  /// abstract expression
1453  /// @return A const pointer to the expression
1454  const Expression* expression() const { return mExpression.get(); }
1455 private:
1456  Expression::UniquePtr mExpression;
1457  const tokens::OperatorToken mOperation;
1458 };
1459 
1460 /// @brief Cast nodes represent the conversion of an underlying expression to
1461 /// a target type. Cast nodes are typically constructed from functional
1462 /// notation and do not represent construction of the target type,
1463 /// rather a type-casted conversion.
1464 struct Cast : public Expression
1465 {
1466  using UniquePtr = std::unique_ptr<Cast>;
1467 
1468  /// @brief Construct a new Cast with a valid expression and a target
1469  /// tokens::CoreType, transferring ownership of the expression to
1470  /// the Cast and updating parent data on the expression.
1471  /// @param expr The expression to perform the cast operator on
1472  /// @param type The target cast type
1473  Cast(Expression* expr, const tokens::CoreType type)
1474  : Expression()
1475  , mType(type)
1476  , mExpression(expr) {
1477  OPENVDB_ASSERT(mExpression);
1478  mExpression->setParent(this);
1479  }
1480  /// @brief Deep copy constructor for a Cast node, performing a deep copy on
1481  /// the underlying expressions, ensuring parent information is
1482  /// updated.
1483  /// @param other A const reference to another Cast node to deep copy
1484  Cast(const Cast& other)
1485  : Expression()
1486  , mType(other.mType)
1487  , mExpression(other.mExpression->copy()) {
1488  mExpression->setParent(this);
1489  }
1490  ~Cast() override = default;
1491 
1492  /// @copybrief Node::copy()
1493  Cast* copy() const override final { return new Cast(*this); }
1494  /// @copybrief Node::nodetype()
1495  NodeType nodetype() const override { return Node::CastNode; }
1496  /// @copybrief Node::nodename()
1497  const char* nodename() const override { return "cast"; }
1498  /// @copybrief Node::subname()
1499  const char* subname() const override { return "cast"; }
1500  /// @copybrief Node::basetype()
1501  const Expression* basetype() const override { return this; }
1502  /// @copybrief Node::children()
1503  size_t children() const override final { return 1; }
1504  /// @copybrief Node::child()
1505  const Expression* child(const size_t i) const override final {
1506  if (i == 0) return this->expression();
1507  return nullptr;
1508  }
1509  /// @copybrief Node::replacechild()
1510  inline bool replacechild(const size_t i, Node* node) override final {
1511  if (i != 0) return false;
1512  Expression* expr = dynamic_cast<Expression*>(node);
1513  if (!expr) return false;
1514  mExpression.reset(expr);
1515  mExpression->setParent(this);
1516  return true;
1517  }
1518 
1519  /// @brief Access to the target type
1520  /// @return a tokens::CoreType enumerable type therepresenting the target type
1521  inline tokens::CoreType type() const { return mType; }
1522  /// @brief Get the target type as a front end AX type/token string
1523  /// @note This returns the associated token to the type, not necessarily
1524  /// equal to the OpenVDB type string
1525  /// @return A string representing the type/token
1526  inline std::string typestr() const {
1527  return ast::tokens::typeStringFromToken(mType);
1528  }
1529  /// @brief Access a const pointer to the Cast node's expression as an
1530  /// abstract expression
1531  /// @return A const pointer to the expression
1532  const Expression* expression() const { return mExpression.get(); }
1533 private:
1534  const tokens::CoreType mType;
1535  Expression::UniquePtr mExpression;
1536 };
1537 
1538 /// @brief FunctionCalls represent a single call to a function and any provided
1539 /// arguments. The argument list can be empty. The function name is
1540 /// expected to exist in the AX function registry.
1541 struct FunctionCall : public Expression
1542 {
1543  using UniquePtr = std::unique_ptr<FunctionCall>;
1544 
1545  /// @brief Construct a new FunctionCall with a given function identifier
1546  /// and an optional argument, transferring ownership of any
1547  /// provided argument to the FunctionCall and updating parent data
1548  /// on the arguments.
1549  /// @param function The name/identifier of the function
1550  /// @param argument Function argument
1551  FunctionCall(const std::string& function,
1552  Expression* argument = nullptr)
1553  : mFunctionName(function)
1554  , mArguments() {
1555  this->append(argument);
1556  }
1557  /// @brief Construct a new FunctionCall with a given function identifier
1558  /// and optional argument list, transferring ownership of any
1559  /// provided arguments to the FunctionCall and updating parent data
1560  /// on the arguments.
1561  /// @param function The name/identifier of the function
1562  /// @param arguments Function arguments
1563  FunctionCall(const std::string& function,
1564  const std::vector<Expression*>& arguments)
1565  : mFunctionName(function)
1566  , mArguments() {
1567  mArguments.reserve(arguments.size());
1568  for (Expression* arg : arguments) {
1569  this->append(arg);
1570  }
1571  }
1572  /// @brief Deep copy constructor for a FunctionCall, performing a deep copy
1573  /// on all held function arguments, ensuring parent information is
1574  /// updated.
1575  /// @param other A const reference to another FunctionCall to deep copy
1577  : mFunctionName(other.mFunctionName)
1578  , mArguments() {
1579  mArguments.reserve(other.mArguments.size());
1580  for (const Expression::UniquePtr& expr : other.mArguments) {
1581  this->append(expr->copy());
1582  }
1583  }
1584  ~FunctionCall() override = default;
1585 
1586  /// @copybrief Node::copy()
1587  FunctionCall* copy() const override final { return new FunctionCall(*this); }
1588  /// @copybrief Node::nodetype()
1589  NodeType nodetype() const override { return Node::FunctionCallNode; }
1590  /// @copybrief Node::nodename()
1591  const char* nodename() const override { return "function call"; }
1592  /// @copybrief Node::subname()
1593  const char* subname() const override { return "call"; }
1594  /// @copybrief Node::basetype()
1595  const Expression* basetype() const override { return this; }
1596  /// @copybrief Node::children()
1597  size_t children() const override final { return this->size(); }
1598  /// @copybrief Node::child()
1599  const Expression* child(const size_t i) const override final {
1600  if (i >= mArguments.size()) return nullptr;
1601  return mArguments[i].get();
1602  }
1603  /// @copybrief Node::replacechild()
1604  inline bool replacechild(const size_t i, Node* node) override final {
1605  if (mArguments.size() <= i) return false;
1606  Expression* expr = dynamic_cast<Expression*>(node);
1607  mArguments[i].reset(expr);
1608  mArguments[i]->setParent(this);
1609  return true;
1610  }
1611 
1612  /// @brief Access the function name/identifier
1613  /// @return A const reference to the function name
1614  inline const std::string& name() const { return mFunctionName; }
1615  /// @brief Query the total number of arguments stored on this function
1616  /// @return The number of arguments. Can be 0
1617  inline size_t numArgs() const { return mArguments.size(); }
1618 
1619  /// @brief Alias for FunctionCall::children
1620  inline size_t size() const { return mArguments.size(); }
1621  /// @brief Query whether this Expression list holds any valid expressions
1622  /// @return True if this node if empty, false otherwise
1623  inline bool empty() const { return mArguments.empty(); }
1624  /// @brief Appends an argument to this function call, transferring
1625  /// ownership to the FunctionCall and updating parent data on the
1626  /// expression. If the expression is a nullptr, it is ignored.
1627  inline void append(Expression* expr) {
1628  if (expr) {
1629  mArguments.emplace_back(expr);
1630  expr->setParent(this);
1631  }
1632  }
1633 private:
1634  const std::string mFunctionName;
1635  std::vector<Expression::UniquePtr> mArguments;
1636 };
1637 
1638 /// @brief Keywords represent keyword statements defining changes in execution.
1639 /// These include those that define changes in loop execution such as
1640 /// break and continue, as well as return statements.
1641 struct Keyword : public Statement
1642 {
1643  using UniquePtr = std::unique_ptr<Keyword>;
1644 
1645  /// @brief Construct a new Keyword with a given tokens::KeywordToken.
1646  /// @param keyw The keyword token.
1648  : mKeyword(keyw) {}
1649  /// @brief Deep copy constructor for a Keyword.
1650  /// @param other A const reference to another Keyword to deep copy
1651  Keyword(const Keyword& other)
1652  : mKeyword(other.mKeyword) {}
1653  ~Keyword() override = default;
1654 
1655  /// @copybrief Node::copy()
1656  Keyword* copy() const override final { return new Keyword(*this); }
1657  /// @copybrief Node::nodetype()
1658  NodeType nodetype() const override { return Node::KeywordNode; }
1659  /// @copybrief Node::nodename()
1660  const char* nodename() const override { return "keyword"; }
1661  /// @copybrief Node::subname()
1662  const char* subname() const override { return "keyw"; }
1663  /// @copybrief Node::basetype()
1664  const Statement* basetype() const override { return this; }
1665  /// @copybrief Node::children()
1666  size_t children() const override final { return 0; }
1667  /// @copybrief Node::child()
1668  const Node* child(const size_t) const override final {
1669  return nullptr;
1670  }
1671  /// @brief Query the keyword held on this node.
1672  /// @return The keyword as a tokens::KeywordToken
1673  inline tokens::KeywordToken keyword() const { return mKeyword; }
1674 
1675 private:
1676  const tokens::KeywordToken mKeyword;
1677 };
1678 
1679 /// @brief ArrayUnpack represent indexing operations into AX container types,
1680 /// primarily vectors and matrices indexed by the square brackets []
1681 /// syntax. Multiple levels of indirection (multiple components) can
1682 /// be specified but current construction is limited to either a single
1683 /// or double component lookup. Providing two components infers a matrix
1684 /// indexing operation.
1685 /// @note Single indexing operations are still valid for matrix indexing
1686 struct ArrayUnpack : public Expression
1687 {
1688  using UniquePtr = std::unique_ptr<ArrayUnpack>;
1689 
1690  /// @brief Construct a new ArrayUnpack with a valid expression, an initial
1691  /// component (as an expression) to the first access and an optional
1692  /// second component (as an expression) to a second access.
1693  /// @note Providing a second component automatically infers this
1694  /// ArrayUnpack as a matrix indexing operation. Ownership is
1695  /// transferred and parent data is updated for all arguments.
1696  /// @param expr The expression to perform the unpacking operation on
1697  /// @param component0 The first component access
1698  /// @param component1 The second component access
1700  Expression* component0,
1701  Expression* component1 = nullptr)
1702  : mIdx0(component0)
1703  , mIdx1(component1)
1704  , mExpression(expr) {
1705  OPENVDB_ASSERT(mIdx0);
1706  OPENVDB_ASSERT(mExpression);
1707  mIdx0->setParent(this);
1708  if(mIdx1) mIdx1->setParent(this);
1709  mExpression->setParent(this);
1710  }
1711  /// @brief Deep copy constructor for a ArrayUnpack, performing a deep
1712  /// copy on the expression being indexed and all held components,
1713  /// ensuring parent information is updated.
1714  /// @param other A const reference to another ArrayUnpack to deep copy
1715  ArrayUnpack(const ArrayUnpack& other)
1716  : ArrayUnpack(other.mExpression->copy(),
1717  other.mIdx0->copy(),
1718  other.mIdx1 ? other.mIdx1->copy() : nullptr) {}
1719 
1720  ~ArrayUnpack() override = default;
1721 
1722  /// @copybrief Node::copy()
1723  ArrayUnpack* copy() const override final { return new ArrayUnpack(*this); }
1724  /// @copybrief Node::nodetype()
1725  NodeType nodetype() const override { return Node::ArrayUnpackNode; }
1726  /// @copybrief Node::nodename()
1727  const char* nodename() const override { return "array unpack"; }
1728  /// @copybrief Node::subname()
1729  const char* subname() const override { return "unpk"; }
1730  /// @copybrief Node::basetype()
1731  const Expression* basetype() const override { return this; }
1732  /// @copybrief Node::children()
1733  size_t children() const override final { return 3; }
1734  /// @copybrief Node::child()
1735  const Statement* child(const size_t i) const override final {
1736  if (i == 0) return this->component0();
1737  if (i == 1) return this->component1();
1738  if (i == 2) return this->expression();
1739  return nullptr;
1740  }
1741  /// @copybrief Node::replacechild()
1742  inline bool replacechild(const size_t i, Node* node) override final {
1743  if (i > 2) return false;
1744  Expression* expr = dynamic_cast<Expression*>(node);
1745  if (!expr) return false;
1746  if (i == 0) mIdx0.reset(expr);
1747  if (i == 1) mIdx1.reset(expr);
1748  if (i == 2) mExpression.reset(expr);
1749  expr->setParent(this);
1750  return true;
1751  }
1752 
1753  /// @brief Access a const pointer to the first component being used as an
1754  /// abstract Expression
1755  /// @return A const pointer to the first component
1756  inline const Expression* component0() const { return mIdx0.get(); }
1757  /// @brief Access a const pointer to the second component being used as an
1758  /// abstract Expression
1759  /// @note This can be a nullptr for single indexing operations
1760  /// @return A const pointer to the second component
1761  inline const Expression* component1() const { return mIdx1.get(); }
1762  /// @brief Access a const pointer to the expression being indexed as an
1763  /// abstract Expression
1764  /// @return A const pointer to the expression
1765  inline const Expression* expression() const { return mExpression.get(); }
1766  /// @brief Query whether this ArrayUnpack operation must be a matrix
1767  /// indexing operation by checking the presence of a second
1768  /// component access.
1769  /// @note This method only guarantees that the indexing operation must be
1770  /// a matrix index. Single indexing is also valid for matrices and
1771  /// other multi dimensional containers
1772  /// @return True if this is a double indexing operation, only valid for
1773  /// matrices
1774  inline bool isMatrixIndex() const {
1775  // assumes that component0 is always valid
1776  return static_cast<bool>(this->component1());
1777  }
1778 private:
1779  Expression::UniquePtr mIdx0, mIdx1;
1780  Expression::UniquePtr mExpression;
1781 };
1782 
1783 /// @brief ArrayPacks represent temporary container creations of arbitrary
1784 /// sizes, typically generated through the use of curly braces {}.
1785 struct ArrayPack : public Expression
1786 {
1787  using UniquePtr = std::unique_ptr<ArrayPack>;
1788 
1789  /// @brief Construct a new ArrayPack with a single expression, transferring
1790  /// ownership of the expression to the ArrayPack and updating parent
1791  /// data on the expression. If the expression is a nullptr, it is
1792  /// ignored.
1793  /// @param expression The Expression to construct from
1794  ArrayPack(Expression* expression)
1795  : mExpressions() {
1796  this->append(expression);
1797  }
1798  /// @brief Construct a new ArrayPack transferring ownership of any
1799  /// provided arguments to the ArrayPack and updating parent data
1800  /// on the arguments.
1801  /// @param arguments ArrayPack arguments
1802  ArrayPack(const std::vector<Expression*>& arguments)
1803  : mExpressions() {
1804  mExpressions.reserve(arguments.size());
1805  for (Expression* arg : arguments) {
1806  this->append(arg);
1807  }
1808  }
1809  /// @brief Deep copy constructor for a ArrayPack, performing a deep copy
1810  /// on all held arguments, ensuring parent information is updated.
1811  /// @param other A const reference to another ArrayPack to deep copy
1812  ArrayPack(const ArrayPack& other)
1813  : mExpressions() {
1814  mExpressions.reserve(other.mExpressions.size());
1815  for (const Expression::UniquePtr& expr : other.mExpressions) {
1816  this->append(expr->copy());
1817  }
1818  }
1819  ~ArrayPack() override = default;
1820 
1821  /// @copybrief Node::copy()
1822  ArrayPack* copy() const override final { return new ArrayPack(*this); }
1823  /// @copybrief Node::nodetype()
1824  NodeType nodetype() const override { return Node::ArrayPackNode; }
1825  /// @copybrief Node::nodename()
1826  const char* nodename() const override { return "array pack"; }
1827  /// @copybrief Node::subname()
1828  const char* subname() const override { return "pack"; }
1829  /// @copybrief Node::basetype()
1830  const Expression* basetype() const override { return this; }
1831  /// @copybrief Node::children()
1832  size_t children() const override final { return this->size(); }
1833  /// @copybrief Node::child()
1834  const Expression* child(const size_t i) const override final {
1835  if (i >= mExpressions.size()) return nullptr;
1836  return mExpressions[i].get();
1837  }
1838  /// @copybrief Node::replacechild()
1839  inline bool replacechild(const size_t i, Node* node) override final {
1840  if (mExpressions.size() <= i) return false;
1841  Expression* expr = dynamic_cast<Expression*>(node);
1842  mExpressions[i].reset(expr);
1843  mExpressions[i]->setParent(this);
1844  return true;
1845  }
1846 
1847  /// @brief Alias for ArrayPack::children
1848  inline size_t size() const { return mExpressions.size(); }
1849  /// @brief Query whether this Expression list holds any valid expressions
1850  /// @return True if this node if empty, false otherwise
1851  inline bool empty() const { return mExpressions.empty(); }
1852  /// @brief Appends an argument to this ArrayPack, transferring ownership
1853  /// to the ArrayPack and updating parent data on the expression.
1854  /// If the expression is a nullptr, it is ignored.
1855  inline void append(Expression* expr) {
1856  if (expr) {
1857  mExpressions.emplace_back(expr);
1858  expr->setParent(this);
1859  }
1860  }
1861 private:
1862  std::vector<Expression::UniquePtr> mExpressions;
1863 };
1864 
1865 /// @brief Attributes represent any access to a primitive value, typically
1866 /// associated with the '@' symbol syntax. Note that the AST does not
1867 /// store any additional information on the given attribute other than
1868 /// its name and type, which together form a unique Attribute identifier
1869 /// known as the Attribute 'token'. A 'primitive value' in this instance
1870 /// refers to a value on an OpenVDB Volume or OpenVDB Points tree.
1871 /// @note The ExternalVariable AST node works in a similar way
1872 /// @note An Attribute is a complete "leaf-level" AST node. It has no children
1873 /// and nothing derives from it.
1874 struct Attribute : public Variable
1875 {
1876  using UniquePtr = std::unique_ptr<Attribute>;
1877 
1878  /// @brief Construct a new Attribute with a given name and type. Optionally
1879  /// also mark it as inferred type creation (no type was directly
1880  /// specified)
1881  /// @param name The name of the attribute
1882  /// @param type The type of the attribute
1883  /// @param inferred Whether the provided type was directly specified
1884  /// (false).
1885  Attribute(const std::string& name, const tokens::CoreType type,
1886  const bool inferred = false)
1887  : Variable(name)
1888  , mType(type)
1889  , mTypeInferred(inferred) {}
1890  /// @brief Construct a new Attribute with a given name and type/token
1891  /// string, delegating construction to the above Attribute
1892  /// constructor.
1893  /// @param name The name of the attribute
1894  /// @param token The type/token string of the attribute
1895  /// @param inferred Whether the provided type was directly specified
1896  /// (false).
1897  Attribute(const std::string& name, const std::string& token,
1898  const bool inferred = false)
1899  : Attribute(name, tokens::tokenFromTypeString(token), inferred) {}
1900  /// @brief Deep copy constructor for a Attribute
1901  /// @note No parent information needs updating as an Attribute is a
1902  /// "leaf level" node (contains no children)
1903  /// @param other A const reference to another Attribute to deep copy
1904  Attribute(const Attribute& other)
1905  : Variable(other)
1906  , mType(other.mType)
1907  , mTypeInferred(other.mTypeInferred) {}
1908  ~Attribute() override = default;
1909 
1910  /// @copybrief Node::copy()
1911  Attribute* copy() const override final { return new Attribute(*this); }
1912  /// @copybrief Node::nodetype()
1913  NodeType nodetype() const override { return Node::AttributeNode; }
1914  /// @copybrief Node::nodename()
1915  const char* nodename() const override { return "attribute"; }
1916  /// @copybrief Node::subname()
1917  const char* subname() const override { return "atr"; }
1918  /// @copybrief Node::basetype()
1919  const Variable* basetype() const override { return this; }
1920 
1921  /// @brief Query whether this attribute was accessed via inferred syntax
1922  /// i.e. \@P or \@myattribute
1923  /// @return True if inferred syntax was used
1924  inline bool inferred() const { return mTypeInferred; }
1925  /// @brief Access the type that was used to access this attribute
1926  /// @return The type used to access this attribute as a tokens::CoreType
1927  inline tokens::CoreType type() const { return mType; }
1928  /// @brief Get the access type as a front end AX type/token string
1929  /// @note This returns the associated token to the type, not necessarily
1930  /// equal to the OpenVDB type string
1931  /// @return A string representing the type/token
1932  inline std::string typestr() const {
1933  return ast::tokens::typeStringFromToken(mType);
1934  }
1935  /// @brief Construct and return the full attribute token identifier. See
1936  /// Attribute::tokenFromNameType
1937  /// @return A string representing the attribute token.
1938  inline std::string tokenname() const {
1939  return Attribute::tokenFromNameType(this->name(), this->type());
1940  }
1941 
1942  /// @brief Static method returning the symbol associated with an Attribute
1943  /// access as defined by AX Grammar
1944  /// @return The '@' character as a char
1945  static inline char symbolseparator() { return '@'; }
1946  /// @brief Static method returning the full unique attribute token
1947  /// identifier by consolidating its name and type such that
1948  /// token = tokenstr + '\@' + name, where tokenstr is the AX type
1949  /// token as a string, converted from the provided CoreType.
1950  /// @note This identifier is unique for accesses to the same attribute
1951  /// @note Due to inferred and single character accesses in AX, this return
1952  /// value does not necessarily represent the original syntax used to
1953  /// access this attribute. For example, \@myattrib will be stored
1954  /// and returned as float\@myattrib.
1955  /// @param name The name of the attribute
1956  /// @param type The CoreType of the attribute
1957  /// @return A string representing the attribute token.
1958  static inline std::string
1959  tokenFromNameType(const std::string& name, const tokens::CoreType type) {
1960  return ast::tokens::typeStringFromToken(type) +
1961  Attribute::symbolseparator() + name;
1962  }
1963  /// @brief Static method which splits a valid attribute token into its name
1964  /// and type counterparts. If the token cannot be split, neither
1965  /// name or type are updated and false is returned.
1966  /// @param token The token to split.
1967  /// @param name Set to the second part of the attribute token,
1968  /// representing the name. If a nullptr, it is ignored
1969  /// @param type Set to the first part of the attribute token,
1970  /// representing the type. If a nullptr, it is ignored. Note
1971  /// that this can be empty if the attribute token has an
1972  /// inferred type or a single character.
1973  /// @return True if the provided attribute token could be split
1974  static inline bool
1975  nametypeFromToken(const std::string& token, std::string* name, std::string* type) {
1976  const size_t at = token.find(symbolseparator());
1977  if (at == std::string::npos) return false;
1978  if (type) {
1979  *type = token.substr(0, at);
1980  if (type->empty()) {
1982  }
1983  }
1984  if (name) *name = token.substr(at + 1, token.size());
1985  return true;
1986  }
1987 private:
1988  const tokens::CoreType mType;
1989  const bool mTypeInferred;
1990 };
1991 
1992 /// @brief ExternalVariable represent any access to external (custom) data,
1993 /// typically associated with the '$' symbol syntax. Note that the AST
1994 /// does not store any additional information on the given external
1995 /// other than its name and type, which together form a unique external
1996 /// identifier known as the ExternalVariable 'token'. This token is used
1997 /// by the compiler to map user provided values to these external
1998 /// values.
1999 /// @note The Attribute AST node works in a similar way
2000 /// @note An ExternalVariable is a complete "leaf-level" AST node. It has no
2001 /// children and nothing derives from it.
2003 {
2004  using UniquePtr = std::unique_ptr<ExternalVariable>;
2005 
2006  /// @brief Construct a new ExternalVariable with a given name and type
2007  /// @param name The name of the attribute
2008  /// @param type The type of the attribute
2009  ExternalVariable(const std::string& name, const tokens::CoreType type)
2010  : Variable(name)
2011  , mType(type) {}
2012  /// @brief Construct a new ExternalVariable with a given name and type/token
2013  /// string, delegating construction to the above ExternalVariable
2014  /// constructor.
2015  /// @param name The name of the attribute
2016  /// @param token The type/token string of the attribute
2017  ExternalVariable(const std::string& name, const std::string& token)
2018  : ExternalVariable(name, tokens::tokenFromTypeString(token)) {}
2019  /// @brief Deep copy constructor for a ExternalVariable
2020  /// @note No parent information needs updating as an ExternalVariable is a
2021  /// "leaf level" node (contains no children)
2022  /// @param other A const reference to another ExternalVariable to deep
2023  /// copy
2025  : Variable(other)
2026  , mType(other.mType) {}
2027  ~ExternalVariable() override = default;
2028 
2029  /// @copybrief Node::copy()
2030  ExternalVariable* copy() const override final {
2031  return new ExternalVariable(*this);
2032  }
2033  /// @copybrief Node::nodetype()
2034  NodeType nodetype() const override { return Node::ExternalVariableNode; }
2035  /// @copybrief Node::nodename()
2036  const char* nodename() const override { return "external"; }
2037  /// @copybrief Node::subname()
2038  const char* subname() const override { return "ext"; }
2039  /// @copybrief Node::basetype()
2040  const Variable* basetype() const override { return this; }
2041 
2042  /// @brief Access the type that was used to access this external variable
2043  /// @return The type used to access this external as a tokens::CoreType
2044  inline tokens::CoreType type() const { return mType; }
2045  /// @brief Get the access type as a front end AX type/token string
2046  /// @note This returns the associated token to the type, not necessarily
2047  /// equal to the OpenVDB type string
2048  /// @return A string representing the type/token
2049  inline std::string typestr() const {
2050  return ast::tokens::typeStringFromToken(mType);
2051  }
2052  /// @brief Construct and return the full external token identifier. See
2053  /// ExternalVariable::tokenFromNameType
2054  /// @return A string representing the external variable token.
2055  inline const std::string tokenname() const {
2056  return ExternalVariable::tokenFromNameType(this->name(), this->type());
2057  }
2058 
2059  /// @brief Static method returning the symbol associated with an
2060  /// ExternalVariable access as defined by AX Grammar
2061  /// @return The '$' character as a char
2062  static inline char symbolseparator() { return '$'; }
2063  /// @brief Static method returning the full unique external token
2064  /// identifier by consolidating its name and type such that
2065  /// token = tokenstr + '$' + name, where tokenstr is the AX type
2066  /// token as a string, converted from the provided CoreType.
2067  /// @note This identifier is unique for accesses to the same external
2068  /// @note Due to inferred and single character accesses in AX, this return
2069  /// value does not necessarily represent the original syntax used to
2070  /// access this external. For example, v$data will be stored and
2071  /// returned as vec3f$data.
2072  /// @param name The name of the external
2073  /// @param type The CoreType of the external
2074  /// @return A string representing the external token.
2075  static inline std::string
2076  tokenFromNameType(const std::string& name, const tokens::CoreType type) {
2077  return ast::tokens::typeStringFromToken(type) +
2078  ExternalVariable::symbolseparator() + name;
2079  }
2080  /// @brief Static method which splits a valid external token into its name
2081  /// and type counterparts. If the token cannot be split, neither
2082  /// name or type are updated and false is returned.
2083  /// @param token The token to split.
2084  /// @param name Set to the second part of the external token,
2085  /// representing the name. If a nullptr, it is ignored
2086  /// @param type Set to the first part of the external token,
2087  /// representing the type. If a nullptr, it is ignored. Note
2088  /// that this can be empty if the external token has an
2089  /// inferred type or a single character.
2090  /// @return True if the provided external token could be split
2091  static inline bool
2092  nametypeFromToken(const std::string& token, std::string* name, std::string* type) {
2093  const size_t at = token.find(symbolseparator());
2094  if (at == std::string::npos) return false;
2095  if (type) {
2096  *type = token.substr(0, at);
2097  if (type->empty()) {
2099  }
2100  }
2101  if (name) *name = token.substr(at + 1, token.size());
2102  return true;
2103  }
2104 private:
2105  const tokens::CoreType mType;
2106 };
2107 
2108 /// @brief Local AST nodes represent a single accesses to a local variable.
2109 /// The only store the name of the variable being accessed.
2110 /// @note A Local is a complete "leaf-level" AST node. It has no children and
2111 /// nothing derives from it.
2112 struct Local : public Variable
2113 {
2114  using UniquePtr = std::unique_ptr<Local>;
2115 
2116  /// @brief Construct a Local with a given name
2117  /// @param name The name of the local variable being accessed
2118  Local(const std::string& name)
2119  : Variable(name) {}
2120  ~Local() override = default;
2121 
2122  /// @copybrief Node::copy()
2123  Local* copy() const override final { return new Local(*this); }
2124  /// @copybrief Node::nodetype()
2125  NodeType nodetype() const override { return Node::LocalNode; }
2126  /// @copybrief Node::nodename()
2127  const char* nodename() const override { return "local"; }
2128  /// @copybrief Node::subname()
2129  const char* subname() const override { return "lcl"; }
2130  /// @copybrief Node::basetype()
2131  const Variable* basetype() const override { return this; }
2132 };
2133 
2134 /// @brief DeclareLocal AST nodes symbolize a single type declaration of a
2135 /// local variable. These store the local variables that They also however store its
2136 /// specified type. These have the important distinction of representing
2137 /// the initial creation and allocation of a variable, in comparison to
2138 /// a Local node which only represents access.
2139 struct DeclareLocal : public Statement
2140 {
2141  using UniquePtr = std::unique_ptr<DeclareLocal>;
2142 
2143  /// @brief Construct a new DeclareLocal with a given name and type
2144  /// @param type The type of the declaration
2145  /// @param local The local variable being declared
2146  /// @param init The initialiser expression of the local
2147  DeclareLocal(const tokens::CoreType type, Local* local, Expression* init = nullptr)
2148  : mType(type)
2149  , mLocal(local)
2150  , mInit(init) {
2151  OPENVDB_ASSERT(mLocal);
2152  mLocal->setParent(this);
2153  if (mInit) mInit->setParent(this);
2154  }
2155  /// @brief Deep copy constructor for a DeclareLocal
2156  /// @note No parent information needs updating as an DeclareLocal is a
2157  /// "leaf level" node (contains no children)
2158  /// @param other A const reference to another DeclareLocal to deep copy
2160  : mType(other.mType)
2161  , mLocal(other.mLocal->copy())
2162  , mInit(other.hasInit() ? other.mInit->copy() : nullptr) {
2163  mLocal->setParent(this);
2164  if (mInit) mInit->setParent(this);
2165  }
2166  ~DeclareLocal() override = default;
2167 
2168  /// @copybrief Node::copy()
2169  DeclareLocal* copy() const override final { return new DeclareLocal(*this); }
2170  /// @copybrief Node::nodetype()
2171  NodeType nodetype() const override { return Node::DeclareLocalNode; }
2172  /// @copybrief Node::nodename()
2173  const char* nodename() const override { return "declaration"; }
2174  /// @copybrief Node::subname()
2175  const char* subname() const override { return "dcl"; }
2176  /// @copybrief Node::basetype()
2177  const Statement* basetype() const override { return this; }
2178  /// @copybrief Node::children()
2179  size_t children() const override final { return 2; }
2180  /// @copybrief Node::child()
2181  const Expression* child(const size_t i) const override final {
2182  if (i == 0) return this->local();
2183  if (i == 1) return this->init();
2184  return nullptr;
2185  }
2186  /// @copybrief Node::replacechild()
2187  inline bool replacechild(const size_t i, Node* node) override final {
2188  if (i > 1) return false;
2189  if (i == 0) {
2190  Local* local = dynamic_cast<Local*>(node);
2191  if (!local) return false;
2192  mLocal.reset(local);
2193  mLocal->setParent(this);
2194  }
2195  else {
2196  Expression* init = dynamic_cast<Expression*>(node);
2197  if (!init) return false;
2198  mInit.reset(init);
2199  mInit->setParent(this);
2200  }
2201  return true;
2202  }
2203 
2204  /// @brief Access the type that was specified at which to create the given
2205  /// local
2206  /// @return The declaration type
2207  inline tokens::CoreType type() const { return mType; }
2208  /// @brief Get the declaration type as a front end AX type/token string
2209  /// @note This returns the associated token to the type, not necessarily
2210  /// equal to the OpenVDB type string
2211  /// @return A string representing the type/token
2212  inline std::string typestr() const {
2213  return ast::tokens::typeStringFromToken(mType);
2214  }
2215  /// @brief Query if this declaration has an initialiser
2216  /// @return True if an initialiser exists, false otherwise
2217  inline bool hasInit() const { return static_cast<bool>(this->init()); }
2218 
2219  /// @brief Access a const pointer to the Local
2220  /// @return A const pointer to the local
2221  const Local* local() const { return mLocal.get(); }
2222  /// @brief Access a const pointer to the initialiser
2223  /// @return A const pointer to the initialiser
2224  const Expression* init() const { return mInit.get(); }
2225 
2226 private:
2227  const tokens::CoreType mType;
2228  Local::UniquePtr mLocal; // could be Variable for attribute declaration
2229  Expression::UniquePtr mInit;
2230 };
2231 
2232 
2233 /// @brief A Value (literal) AST node holds either literal text or absolute
2234 /// value information on all numerical, string and boolean constants.
2235 /// A single instance of a Value is templated on the requested scalar,
2236 /// boolean or string type. If scalar or boolean value is constructed
2237 /// from a string (as typically is the case in the parser), the value is
2238 /// automatically converted to its numerical representation. If this
2239 /// fails, the original text is stored instead.
2240 /// @note All numerical values are stored as their highest possible precision
2241 /// type to support overflowing without storing the original string
2242 /// data. The original string data is only required if the value is too
2243 /// large to be stored in these highest precision types (usually a
2244 /// uint64_t for scalars or double for floating points).
2245 /// @note Numerical values are guaranteed to be positive (if constructed from
2246 /// the AX parser). Negative values are represented by a combination of
2247 /// a UnaryOperator holding a Value AST node.
2248 /// @note Note that Value AST nodes representing strings are specialized and
2249 /// are guranteed to be "well-formed" (there is no numerical conversion)
2250 /// @note A Value is a complete "leaf-level" AST node. It has no children and
2251 /// nothing derives from it.
2252 template <typename T>
2253 struct Value : public ValueBase
2254 {
2255  using UniquePtr = std::unique_ptr<Value<T>>;
2256 
2257  using Type = T;
2258  /// @brief Integers and Floats store their value as ContainerType, which is
2259  /// guaranteed to be at least large enough to represent the maximum
2260  /// possible supported type for the requested precision.
2261  using ContainerType = typename std::conditional<
2262  std::is_integral<T>::value, uint64_t, T>::type;
2263 
2264  /// @brief The list of supported numerical constants.
2265  /// @note Strings are specialized and handled separately
2266  static constexpr bool IsSupported =
2267  std::is_same<T, bool>::value ||
2268  std::is_same<T, int16_t>::value ||
2269  std::is_same<T, int32_t>::value ||
2270  std::is_same<T, int64_t>::value ||
2271  std::is_same<T, float>::value ||
2272  std::is_same<T, double>::value;
2273  static_assert(IsSupported, "Incompatible ast::Value node instantiated.");
2274 
2275  /// @brief Directly construct a Value from a source integer, float or
2276  /// boolean, guaranteeing valid construction. Note that the provided
2277  /// argument should not be negative
2278  Value(const ContainerType value)
2279  : mValue(value) {}
2280  /// @brief Deep copy constructor for a Value
2281  /// @note No parent information needs updating as a Value is a "leaf
2282  /// level" node (contains no children)
2283  /// @param other A const reference to another Value to deep copy
2284  Value(const Value<T>& other)
2285  : mValue(other.mValue) {}
2286  ~Value() override = default;
2287 
2288  /// @copybrief Node::copy()
2289  Value<Type>* copy() const override final { return new Value<Type>(*this); }
2290  /// @copybrief Node::nodetype()
2291  NodeType nodetype() const override {
2292  if (std::is_same<T, bool>::value) return Node::ValueBoolNode;
2293  if (std::is_same<T, int16_t>::value) return Node::ValueInt16Node;
2294  if (std::is_same<T, int32_t>::value) return Node::ValueInt32Node;
2295  if (std::is_same<T, int64_t>::value) return Node::ValueInt64Node;
2296  if (std::is_same<T, float>::value) return Node::ValueFloatNode;
2297  if (std::is_same<T, double>::value) return Node::ValueDoubleNode;
2298  }
2299  /// @copybrief Node::nodename()
2300  const char* nodename() const override {
2301  if (std::is_same<T, bool>::value) return "boolean literal";
2302  if (std::is_same<T, int16_t>::value) return "int16 literal";
2303  if (std::is_same<T, int32_t>::value) return "int32 literal";
2304  if (std::is_same<T, int64_t>::value) return "int64 literal";
2305  if (std::is_same<T, float>::value) return "float (32bit) literal";
2306  if (std::is_same<T, double>::value) return "double (64bit) literal";
2307  }
2308  /// @copybrief Node::subname()
2309  const char* subname() const override {
2310  if (std::is_same<T, bool>::value) return "bool";
2311  if (std::is_same<T, int16_t>::value) return "i16";
2312  if (std::is_same<T, int32_t>::value) return "i32";
2313  if (std::is_same<T, int64_t>::value) return "i64";
2314  if (std::is_same<T, float>::value) return "flt";
2315  if (std::is_same<T, double>::value) return "dbl";
2316  }
2317  /// @copybrief Node::basetype()
2318  const ValueBase* basetype() const override { return this; }
2319 
2320  /// @brief Access the value as its stored type
2321  /// @return The value as its stored ContainerType
2322  inline ContainerType asContainerType() const { return mValue; }
2323  /// @brief Access the value as its requested (templated) type
2324  /// @return The value as its templed type T
2325  inline T value() const { return static_cast<T>(mValue); }
2326 
2327 private:
2328  // A container of a max size defined by LiteralValueContainer to hold values
2329  // which may be out of scope. This is only used for warnings
2330  const ContainerType mValue;
2331 };
2332 
2333 /// @brief Specialization of Values for strings
2334 template <>
2335 struct Value<std::string> : public ValueBase
2336 {
2337  using UniquePtr = std::unique_ptr<Value<std::string>>;
2338 
2339  using Type = std::string;
2340  /// @brief Construct a new Value string from a string
2341  /// @param value The string to copy onto this Value
2342  Value(const Type& value) : mValue(value) {}
2343  /// @brief Deep copy constructor for a Value string
2344  /// @note No parent information needs updating as a Value is a "leaf
2345  /// level" node (contains no children)
2346  /// @param other A const reference to another Value string to deep copy
2347  Value(const Value<Type>& other) : mValue(other.mValue) {}
2348  ~Value() override = default;
2349 
2350  Value<Type>* copy() const override final { return new Value<Type>(*this); }
2351  NodeType nodetype() const override { return Node::ValueStrNode; }
2352  const char* nodename() const override { return "string value"; }
2353  const char* subname() const override { return "str"; }
2354  const ValueBase* basetype() const override { return this; }
2355 
2356  /// @brief Access the string
2357  /// @return A const reference to the string
2358  inline const std::string& value() const { return mValue; }
2359 private:
2360  const Type mValue;
2361 };
2362 
2363 } // namespace ast
2364 } // namespace ax
2365 
2366 } // namespace OPENVDB_VERSION_NAME
2367 } // namespace openvdb
2368 
2369 #endif // OPENVDB_AX_AST_HAS_BEEN_INCLUDED
2370 
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1664
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1604
AssignExpressions represents a similar object construction to a BinaryOperator. AssignExpressions can...
Definition: AST.h:1198
virtual const Node * basetype() const
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:176
Operation
A simple enum representing the crement type.
Definition: AST.h:1299
Local(const std::string &name)
Construct a Local with a given name.
Definition: AST.h:2118
virtual size_t children() const =0
Virtual method for accessing child information. Returns the number of children a given AST node owns...
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:668
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:348
std::string typestr() const
Get the access type as a front end AX type/token string.
Definition: AST.h:1932
Local AST nodes represent a single accesses to a local variable. The only store the name of the varia...
Definition: AST.h:2112
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1348
const Statement * condition() const
Access a const pointer to the Loop condition as an abstract statement.
Definition: AST.h:835
std::unique_ptr< Expression > UniquePtr
Definition: AST.h:328
Value(const ContainerType value)
Directly construct a Value from a source integer, float or boolean, guaranteeing valid construction...
Definition: AST.h:2278
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:430
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:2181
size_t size() const
Alias for Block::children.
Definition: AST.h:541
Attributes represent any access to a primitive value, typically associated with the &#39;@&#39; symbol syntax...
Definition: AST.h:1874
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1662
KeywordToken
Definition: Tokens.h:314
tokens::CoreType type() const
Access the type that was used to access this attribute.
Definition: AST.h:1927
Keyword(const Keyword &other)
Deep copy constructor for a Keyword.
Definition: AST.h:1651
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1146
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy. It represents an entire conversion of a valid AX string.
Definition: AST.h:562
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1439
const Expression * component1() const
Access a const pointer to the second component being used as an abstract Expression.
Definition: AST.h:1761
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1497
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1505
OperatorToken operatorTokenFromName(const std::string &name)
Definition: Tokens.h:221
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1341
Concrete AST nodes.
Definition: AST.h:386
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1042
Variables are a base type for Locals, Attributes and ExternalVariables. Unlike other abstract types...
Definition: AST.h:337
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1834
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:2309
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:590
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1725
ArrayPack * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1822
ConditionalStatement * copy() const override final
The deep copy method for a Node.
Definition: AST.h:906
const Block * falseBranch() const
Access a const pointer to the ConditionalStatements &#39;false&#39; branch as a Block.
Definition: AST.h:975
const Expression * falseBranch() const
Access a const pointer to the TernaryOperator false expression as an abstract expression.
Definition: AST.h:1185
const Expression * rhs() const
Access a const pointer to the BinaryOperator RHS as an abstract expression.
Definition: AST.h:1079
ValueBases are a base class for anything that holds a value (literal). Derived classes store the actu...
Definition: AST.h:361
bool hasIter() const
Query if this Loop has a valid iteration expression list.
Definition: AST.h:831
T value() const
Access the value as its requested (templated) type.
Definition: AST.h:2325
tokens::KeywordToken keyword() const
Query the keyword held on this node.
Definition: AST.h:1673
const Expression * trueBranch() const
Access a const pointer to the TernaryOperator true expression as an abstract expression.
Definition: AST.h:1181
UnaryOperator(Expression *expr, const tokens::OperatorToken op)
Construct a new UnaryOperator with a given tokens::OperatorToken and a valid expression, transferring ownership of the expression to the UnaryOperator and updating parent data on the expression.
Definition: AST.h:1398
void addStatement(Statement *stmnt)
Adds a statement to this block, transferring ownership to the block and updating parent data on the s...
Definition: AST.h:545
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1666
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:597
ExternalVariable represent any access to external (custom) data, typically associated with the &#39;$&#39; sy...
Definition: AST.h:2002
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1040
static bool nametypeFromToken(const std::string &token, std::string *name, std::string *type)
Static method which splits a valid external token into its name and type counterparts. If the token cannot be split, neither name or type are updated and false is returned.
Definition: AST.h:2092
FunctionCall * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1587
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1742
ContainerType asContainerType() const
Access the value as its stored type.
Definition: AST.h:2322
static std::string tokenFromNameType(const std::string &name, const tokens::CoreType type)
Static method returning the full unique external token identifier by consolidating its name and type ...
Definition: AST.h:2076
StatementList(const std::vector< Statement * > &statements)
Construct a new StatementList from a vector of statements, transferring ownership of all valid statem...
Definition: AST.h:406
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1046
std::string typestr() const
Get the target type as a front end AX type/token string.
Definition: AST.h:1526
std::unique_ptr< Statement > UniquePtr
Definition: AST.h:314
void addStatement(Statement *stmnt)
Adds a statement to this statement list, transferring ownership to the statement list and updating pa...
Definition: AST.h:456
Loop(const Loop &other)
Deep copy constructor for an Loop, performing a deep copy on the condition, body and initial Statemen...
Definition: AST.h:750
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1424
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1733
static bool nametypeFromToken(const std::string &token, std::string *name, std::string *type)
Static method which splits a valid attribute token into its name and type counterparts. If the token cannot be split, neither name or type are updated and false is returned.
Definition: AST.h:1975
const Expression * lhs() const
Access a const pointer to the BinaryOperator LHS as an abstract expression.
Definition: AST.h:1075
Crement(const Crement &other)
Deep copy constructor for a Crement, performing a deep copy on the underlying expressions, ensuring parent information is updated.
Definition: AST.h:1321
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:919
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:2175
tokens::OperatorToken operation() const
Query the type of binary operation held on this node.
Definition: AST.h:1071
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:2036
Definition: axparser.h:124
void append(Expression *expr)
Appends an argument to this ArrayPack, transferring ownership to the ArrayPack and updating parent da...
Definition: AST.h:1855
const Node * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:317
ArrayPacks represent temporary container creations of arbitrary sizes, typically generated through th...
Definition: AST.h:1785
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:2351
ArrayPack(const std::vector< Expression * > &arguments)
Construct a new ArrayPack transferring ownership of any provided arguments to the ArrayPack and updat...
Definition: AST.h:1802
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:2352
ConditionalStatement(Expression *conditional, Block *trueBlock, Block *falseBlock=nullptr)
Construct a new ConditionalStatement with an Expression representing the primary condition, a Block representing the &#39;true&#39; branch and an optional Block representing the &#39;false&#39; branch. Ownership of all arguments is transferred to the ConditionalStatement. All arguments have their parent data updated.
Definition: AST.h:878
const std::string & value() const
Access the string.
Definition: AST.h:2358
bool hasInit() const
Query if this Loop has a valid initial statement.
Definition: AST.h:828
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1826
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1915
const Block * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:599
std::string typestr() const
Get the declaration type as a front end AX type/token string.
Definition: AST.h:2212
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1495
std::unique_ptr< FunctionCall > UniquePtr
Definition: AST.h:1543
StatementList()
Construct a new StatementList with an empty list.
Definition: AST.h:391
Definition: Coord.h:590
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:428
std::unique_ptr< Block > UniquePtr
Definition: AST.h:478
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1510
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:652
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:2129
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1336
Cast(const Cast &other)
Deep copy constructor for a Cast node, performing a deep copy on the underlying expressions, ensuring parent information is updated.
Definition: AST.h:1484
Value(const Value< T > &other)
Deep copy constructor for a Value.
Definition: AST.h:2284
A UnaryOperator represents a single unary operation on an expression. The operation type is stored as...
Definition: AST.h:1389
ConditionalStatement(const ConditionalStatement &other)
Deep copy constructor for an ConditionalStatement, performing a deep copy on the condition and both h...
Definition: AST.h:895
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1499
A BinaryOperator represents a single binary operation between a left hand side (LHS) and right hand s...
Definition: AST.h:988
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1432
Definition: axparser.h:72
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1731
NodeType
An enumerated list of node types for all concrete node types. These can be used for faster evaluation...
Definition: AST.h:118
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:515
void setParent(Node *parent)
Set this node&#39;s parent. This is used during construction of an AST and should not be used...
Definition: AST.h:277
const Variable * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1919
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:565
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:521
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1334
ConditionalStatements represents all combinations of &#39;if&#39;, &#39;else&#39; and &#39;else if&#39; syntax and semantics...
Definition: AST.h:864
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:2187
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:2034
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1138
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:776
const Variable * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:2131
OutGridT XformOp & op
Definition: ValueTransformer.h:139
Value(const Value< Type > &other)
Deep copy constructor for a Value string.
Definition: AST.h:2347
Expressions are comprised of full or potentially partial parts of a full statement that may not neces...
Definition: AST.h:326
TernaryOperator(const TernaryOperator &other)
Deep copy constructor for a TernaryOperator, performing a deep copy on held expressions, ensuring parent information is updated.
Definition: AST.h:1121
size_t children() const override
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:368
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1428
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:661
const Expression * expression() const
Access a const pointer to the expression being crements as an abstract Expression.
Definition: AST.h:1377
const Expression * init() const
Access a const pointer to the initialiser.
Definition: AST.h:2224
Value< Type > * copy() const override final
The deep copy method for a Node.
Definition: AST.h:2289
Operation operation() const
Query the type of the Crement operation. This does not hold post or pre-crement information.
Definition: AST.h:1361
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1917
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:366
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1426
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:2125
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1591
Cast * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1493
A Value (literal) AST node holds either literal text or absolute value information on all numerical...
Definition: AST.h:2253
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1593
const std::string tokenname() const
Construct and return the full external token identifier. See ExternalVariable::tokenFromNameType.
Definition: AST.h:2055
bool hasFalse() const
Query if this ConditionalStatement has a valid &#39;false&#39; branch.
Definition: AST.h:955
BinaryOperator(const BinaryOperator &other)
Deep copy constructor for a BinaryOperator, performing a deep copy on both held expressions, ensuring parent information is updated.
Definition: AST.h:1024
FunctionCall(const FunctionCall &other)
Deep copy constructor for a FunctionCall, performing a deep copy on all held function arguments...
Definition: AST.h:1576
const Block * body() const
Access a const pointer to the Loop body as a Block.
Definition: AST.h:838
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:656
CommaOperator()
Construct a new CommaOperator with an expr set.
Definition: AST.h:612
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:524
Attribute(const Attribute &other)
Deep copy constructor for a Attribute.
Definition: AST.h:1904
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:531
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:658
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1253
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1239
bool inferred() const
Query whether this attribute was accessed via inferred syntax i.e. @P or @myattribute.
Definition: AST.h:1924
Loops represent for, while and do-while loop constructs. These all consist of a condition - evaluated...
Definition: AST.h:708
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:2300
CommaOperator * copy() const override final
The deep copy method for a Node.
Definition: AST.h:648
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:916
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1243
tokens::CoreType type() const
Access the type that was specified at which to create the given local.
Definition: AST.h:2207
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:2171
Block(const std::vector< Statement * > &statements)
Construct a new Block from a vector of statements, transferring ownership of all valid statements to ...
Definition: AST.h:496
std::string Type
Definition: AST.h:2339
Variable(const Variable &other)
Definition: AST.h:343
bool empty() const
Query whether this Expression list holds any valid expressions.
Definition: AST.h:1623
bool isMatrixIndex() const
Query whether this ArrayUnpack operation must be a matrix indexing operation by checking the presence...
Definition: AST.h:1774
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1247
ArrayUnpack(const ArrayUnpack &other)
Deep copy constructor for a ArrayUnpack, performing a deep copy on the expression being indexed and a...
Definition: AST.h:1715
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1038
bool empty() const
Query whether this Expression list holds any valid expressions.
Definition: AST.h:1851
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:2173
Attribute * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1911
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
const std::string & name() const
Definition: AST.h:353
LoopToken
Definition: Tokens.h:296
Block(const Block &other)
Deep copy constructor for a Block, performing a deep copy on every held statement, ensuring parent information is updated.
Definition: AST.h:505
Abstract (pure-virtual) AST nodes.
Definition: AST.h:312
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1501
bool hasInit() const
Query if this declaration has an initialiser.
Definition: AST.h:2217
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:588
DeclareLocal(const DeclareLocal &other)
Deep copy constructor for a DeclareLocal.
Definition: AST.h:2159
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:791
ArrayPack(Expression *expression)
Construct a new ArrayPack with a single expression, transferring ownership of the expression to the A...
Definition: AST.h:1794
Cast(Expression *expr, const tokens::CoreType type)
Construct a new Cast with a valid expression and a target tokens::CoreType, transferring ownership of...
Definition: AST.h:1473
const ValueBase * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:2354
tokens::CoreType type() const
Access to the target type.
Definition: AST.h:1521
const Expression * expression() const
Access a const pointer to the Cast node&#39;s expression as an abstract expression.
Definition: AST.h:1532
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1729
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1660
BinaryOperator * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1034
CoreType
Definition: Tokens.h:31
const Statement * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:437
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1343
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1434
size_t branchCount() const
Query the number of branches held by this ConditionalStatement. This is only ever 1 or 2...
Definition: AST.h:961
int64_t childidx() const
Returns the child index of this node in relation to its parent, or -1 if no valid index is found (usu...
Definition: AST.h:212
virtual const Node * child(const size_t index) const =0
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: Exceptions.h:13
A Block node represents a scoped list of statements. It may comprise of 0 or more statements...
Definition: AST.h:476
TernaryOperator(Expression *conditional, Expression *trueExpression, Expression *falseExpression)
Construct a new TernaryOperator with a conditional expression and true (optional) and false expressio...
Definition: AST.h:1105
Attribute(const std::string &name, const tokens::CoreType type, const bool inferred=false)
Construct a new Attribute with a given name and type. Optionally also mark it as inferred type creati...
Definition: AST.h:1885
tokens::OperatorToken operation() const
Query the type of unary operation held on this node.
Definition: AST.h:1450
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:912
ArrayUnpack(Expression *expr, Expression *component0, Expression *component1=nullptr)
Construct a new ArrayUnpack with a valid expression, an initial component (as an expression) to the f...
Definition: AST.h:1699
const Expression * condition() const
Access a const pointer to the TernaryOperator conditional as an abstract expression.
Definition: AST.h:1177
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1589
size_t size() const
Alias for StatementList::children.
Definition: AST.h:452
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:654
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:2291
std::unique_ptr< Local > UniquePtr
Definition: AST.h:2114
tokens::OperatorToken operation() const
Query the actual operational type of this AssignExpression. For simple (non-compound) AssignExpressio...
Definition: AST.h:1276
std::unique_ptr< Node > UniquePtr
Definition: AST.h:105
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:592
const Expression * expression() const
Access a const pointer to the UnaryOperator expression as an abstract expression. ...
Definition: AST.h:1454
bool increment() const
Query if this Crement node represents an incrementation ++.
Definition: AST.h:1364
bool replace(Node *node)
In place replacement. Attempts to replace this node at its specific location within its Abstract Synt...
Definition: AST.h:248
AssignExpression * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1233
Loop * copy() const override final
The deep copy method for a Node.
Definition: AST.h:770
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1332
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1658
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:663
Block(Statement *statement)
Construct a new Block with a single statement, transferring ownership of the statement to the block a...
Definition: AST.h:487
const std::string & name() const
Access the function name/identifier.
Definition: AST.h:1614
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1237
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:432
ExternalVariable(const std::string &name, const std::string &token)
Construct a new ExternalVariable with a given name and type/token string, delegating construction to ...
Definition: AST.h:2017
std::string typestr() const
Get the access type as a front end AX type/token string.
Definition: AST.h:2049
Local * copy() const override final
The deep copy method for a Node.
Definition: AST.h:2123
Cast nodes represent the conversion of an underlying expression to a target type. Cast nodes are typi...
Definition: AST.h:1464
ArrayUnpack * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1723
const Expression * condition() const
Access a const pointer to the ConditionalStatements condition as an abstract expression.
Definition: AST.h:967
TernaryOperator * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1132
StatementList * copy() const override
The deep copy method for a Node.
Definition: AST.h:424
A Crement node represents a single increment &#39;++&#39; and decrement &#39;–&#39; operation. As well as it&#39;s creme...
Definition: AST.h:1294
const Statement * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:526
static char symbolseparator()
Static method returning the symbol associated with an ExternalVariable access as defined by AX Gramma...
Definition: AST.h:2062
std::unique_ptr< CommaOperator > UniquePtr
Definition: AST.h:609
const Node * child(const size_t) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1668
BinaryOperator(Expression *left, Expression *right, const std::string &op)
Construct a new BinaryOperator with a string, delegating construction to the above BinaryOperator con...
Definition: AST.h:1016
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:774
static char symbolseparator()
Static method returning the symbol associated with an Attribute access as defined by AX Grammar...
Definition: AST.h:1945
const Statement * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:783
bool post() const
Query if this Crement node represents a post crement a++.
Definition: AST.h:1373
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:781
static std::string tokenFromNameType(const std::string &name, const tokens::CoreType type)
Static method returning the full unique attribute token identifier by consolidating its name and type...
Definition: AST.h:1959
size_t numArgs() const
Query the total number of arguments stored on this function.
Definition: AST.h:1617
const Statement * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1735
const ValueBase * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:2318
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:914
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:426
Variable(const std::string &name)
Definition: AST.h:341
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1595
size_t children() const override
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:350
bool isType() const
Query whether or not this node is of a specific (derived) type. This method should be used to check i...
Definition: AST.h:185
std::string typeStringFromToken(const CoreType type)
Definition: Tokens.h:118
T Type
Definition: AST.h:2257
std::shared_ptr< Node > Ptr
Definition: AST.h:104
Value< Type > * copy() const override final
The deep copy method for a Node.
Definition: AST.h:2350
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:928
std::unique_ptr< ArrayPack > UniquePtr
Definition: AST.h:1787
void append(Expression *expr)
Append an expression to this CommaOperator, transferring ownership to the CommaOperator and updating ...
Definition: AST.h:684
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1830
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1245
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:778
StatementList(Statement *statement)
Construct a new StatementList with a single statement, transferring ownership of the statement to the...
Definition: AST.h:397
DeclareLocal AST nodes symbolize a single type declaration of a local variable. These store the local...
Definition: AST.h:2139
BinaryOperator(Expression *left, Expression *right, const tokens::OperatorToken op)
Construct a new BinaryOperator with a given tokens::OperatorToken and a valid LHS and RHS expression...
Definition: AST.h:1000
const Expression * iteration() const
Access a const pointer to the Loop iteration Expression.
Definition: AST.h:845
bool hasTrue() const
Query whether or not this has an optional if-true branch.
Definition: AST.h:1173
FunctionCall(const std::string &function, Expression *argument=nullptr)
Construct a new FunctionCall with a given function identifier and an optional argument, transferring ownership of any provided argument to the FunctionCall and updating parent data on the arguments.
Definition: AST.h:1551
Keyword(const tokens::KeywordToken keyw)
Construct a new Keyword with a given tokens::KeywordToken.
Definition: AST.h:1647
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1054
Various function and operator tokens used throughout the AST and code generation. ...
bool isCompound() const
Query whether or not this is a compound AssignExpression. Compound AssignExpressions are assignments ...
Definition: AST.h:1272
Attribute(const std::string &name, const std::string &token, const bool inferred=false)
Construct a new Attribute with a given name and type/token string, delegating construction to the abo...
Definition: AST.h:1897
size_t size() const
Alias for ArrayPack::children.
Definition: AST.h:1848
const Expression * rhs() const
Access a const pointer to the AssignExpression RHS as an.
Definition: AST.h:1284
std::unique_ptr< StatementList > UniquePtr
Definition: AST.h:388
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1839
Tree(Block *block=new Block())
Construct a new Tree from a given Block, transferring ownership of the Block to the tree and updating...
Definition: AST.h:572
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:2177
tokens::LoopToken loopType() const
Query the type of loop held on this node.
Definition: AST.h:825
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:2353
Keywords represent keyword statements defining changes in execution. These include those that define ...
Definition: AST.h:1641
AssignExpression(const AssignExpression &other)
Deep copy constructor for an AssignExpression, performing a deep copy on both held expressions...
Definition: AST.h:1223
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1338
const Expression * component0() const
Access a const pointer to the first component being used as an abstract Expression.
Definition: AST.h:1756
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1832
size_t size() const
Alias for FunctionCall::children.
Definition: AST.h:1620
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:1727
DeclareLocal(const tokens::CoreType type, Local *local, Expression *init=nullptr)
Construct a new DeclareLocal with a given name and type.
Definition: AST.h:2147
AssignExpression(Expression *lhs, Expression *rhs, const tokens::OperatorToken op=tokens::EQUALS)
Construct a new AssignExpression with valid LHS and RHS expressions, transferring ownership of the ex...
Definition: AST.h:1208
typename std::conditional< std::is_integral< T >::value, uint64_t, T >::type ContainerType
Integers and Floats store their value as ContainerType, which is guaranteed to be at least large enou...
Definition: AST.h:2262
FunctionCalls represent a single call to a function and any provided arguments. The argument list can...
Definition: AST.h:1541
tokens::CoreType type() const
Access the type that was used to access this external variable.
Definition: AST.h:2044
std::string tokenname() const
Construct and return the full attribute token identifier. See Attribute::tokenFromNameType.
Definition: AST.h:1938
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:2127
CommaOperator(Expression *expression)
Construct a new CommaOperator with a single expression, transferring ownership of the expression to t...
Definition: AST.h:618
const Local * local() const
Access a const pointer to the Local.
Definition: AST.h:2221
Definition: axparser.h:84
DeclareLocal * copy() const override final
The deep copy method for a Node.
Definition: AST.h:2169
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:2038
const Statement * initial() const
Access a const pointer to the Loop initial statement as an abstract statement.
Definition: AST.h:842
const char * nodename() const override
Virtual method for accessing node name information.
Definition: AST.h:517
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:435
bool pre() const
Query if this Crement node represents a pre crement ++a.
Definition: AST.h:1370
size_t size() const
Alias for CommaOperator::children.
Definition: AST.h:677
CoreType tokenFromTypeString(const std::string &type)
Definition: Tokens.h:66
Block()
Construct a new Block with an empty list.
Definition: AST.h:481
const Node * child(const size_t) const override
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:369
Crement(Expression *expr, const Operation op, bool post)
Construct a new Crement with a valid expression, transferring ownership of the expression to the Crem...
Definition: AST.h:1311
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:1153
StatementList(const StatementList &other)
Deep copy constructor for a StatementList, performing a deep copy on every held statement, ensuring parent information is updated.
Definition: AST.h:416
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1503
FunctionCall(const std::string &function, const std::vector< Expression * > &arguments)
Construct a new FunctionCall with a given function identifier and optional argument list...
Definition: AST.h:1563
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1142
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:2179
UnaryOperator * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1422
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1599
const Variable * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:2040
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
Crement * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1330
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition: AST.h:102
const Block * trueBranch() const
Access a const pointer to the ConditionalStatements &#39;true&#39; branch as a Block.
Definition: AST.h:971
UnaryOperator(Expression *expr, const std::string &op)
Construct a new UnaryOperator with a string, delegating construction to the above UnaryOperator const...
Definition: AST.h:1408
CommaOperator(const std::vector< Expression * > &expressions)
Construct a new CommaOperator from a vector of expression, transferring ownership of all valid expres...
Definition: AST.h:627
Keyword * copy() const override final
The deep copy method for a Node.
Definition: AST.h:1656
Tree * copy() const override final
The deep copy method for a Node.
Definition: AST.h:586
const Node * child(const size_t) const override
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:351
const Expression * expression() const
Access a const pointer to the expression being indexed as an abstract Expression. ...
Definition: AST.h:1765
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:519
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1136
const Statement * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:331
void append(Expression *expr)
Appends an argument to this function call, transferring ownership to the FunctionCall and updating pa...
Definition: AST.h:1627
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1144
const Statement * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:921
const Node * parent() const
Access a const pointer to this nodes parent.
Definition: AST.h:272
ExternalVariable * copy() const override final
The deep copy method for a Node.
Definition: AST.h:2030
size_t children() const override final
Virtual method for accessing child information. Returns the number of children a given AST node owns...
Definition: AST.h:1597
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1044
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:910
Tree(const Tree &other)
Deep copy constructor for a Tree, performing a deep copy on the held Block, ensuring parent informati...
Definition: AST.h:579
CommaOperator(const CommaOperator &other)
Deep copy constructor for an CommaOperator, performing a deep copy on every held expression, ensuring parent information is updated.
Definition: AST.h:638
OperatorToken
Definition: Tokens.h:150
ArrayPack(const ArrayPack &other)
Deep copy constructor for a ArrayPack, performing a deep copy on all held arguments, ensuring parent information is updated.
Definition: AST.h:1812
bool decrement() const
Query if this Crement node represents an decrement –.
Definition: AST.h:1367
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1913
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:1824
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1140
ArrayUnpack represent indexing operations into AX container types, primarily vectors and matrices ind...
Definition: AST.h:1686
UnaryOperator(const UnaryOperator &other)
Deep copy constructor for a UnaryOperator, performing a deep copy on the underlying expressions...
Definition: AST.h:1414
const Expression * child(const size_t i) const override final
Virtual method for accessing child information. Returns a const pointer to a child node at the given ...
Definition: AST.h:1048
NodeType nodetype() const override
Virtual method for accessing node type information.
Definition: AST.h:772
bool replacechild(const size_t i, Node *node) override final
Virtual method that attempted to replace a child at a given index with a provided node type...
Definition: AST.h:442
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1241
A TernaryOperator represents a ternary (conditional) expression &#39;a ? b : c&#39; which evaluates to &#39;b&#39; if...
Definition: AST.h:1092
Value(const Type &value)
Construct a new Value string from a string.
Definition: AST.h:2342
ExternalVariable(const std::string &name, const tokens::CoreType type)
Construct a new ExternalVariable with a given name and type.
Definition: AST.h:2009
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
Block * copy() const override final
The deep copy method for a Node.
Definition: AST.h:513
const char * subname() const override
Virtual method for accessing node name information.
Definition: AST.h:1828
const Expression * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:1430
Loop(const tokens::LoopToken loopType, Statement *condition, Block *body, Statement *init=nullptr, Expression *iter=nullptr)
Construct a new Loop with the type defined by a tokens::LoopToken, a condition Statement, a Block representing the body and for for-loops an optional initial Statement and iteration Expression. Ownership of all arguments is transferred to the Loop. All arguments have their parent data updated.
Definition: AST.h:723
const Node * basetype() const override
Virtual method for accessing a node&#39;s base class. Note that if this is called explicitly on an instan...
Definition: AST.h:594
bool empty() const
Query whether this Expression list holds any valid expressions.
Definition: AST.h:680
ExternalVariable(const ExternalVariable &other)
Deep copy constructor for a ExternalVariable.
Definition: AST.h:2024
const Expression * lhs() const
Access a const pointer to the AssignExpression LHS as an abstract expression.
Definition: AST.h:1280