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