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