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