Syntax tree - Visitors

Syntax trees can return a pre-configured visitor object that can be used
to visit all the nodes. Also added a method to create a "root node"
handle for the visitor, because I'm a lazy bastard.
This commit is contained in:
Emmanuel BENOîT 2018-03-31 22:11:00 +02:00
parent a9762a901e
commit b659f2f237
3 changed files with 159 additions and 1 deletions
include/ebcl

View file

@ -6,6 +6,7 @@
#define _H_EBCL_SYNTAXTREE
#include <ebcl/Types.hh>
#include <ebcl/Arrays.hh>
#include <ebcl/Algorithms.hh>
namespace ebcl {
@ -29,11 +30,29 @@ template<
public:
using E_Node = NodeType;
using T_Self = T_SyntaxTree< NodeType , InPlaceSize >;
static constexpr size_t StorageSize
= T_VariantExt< InPlaceSize >::StorageSize;
private:
// A node, as seen from a visitor
struct T_Node
{
T_Self const& tree;
uint32_t node;
T_Node( ) = delete;
T_Node( T_Self const& tree , uint32_t node ) noexcept;
T_Node( T_Node const& other ) noexcept;
T_Node( T_Node&& other ) noexcept;
T_Node& operator =( T_Node const& other ) noexcept;
T_Node& operator =( T_Node&& other ) noexcept;
};
// Visitor type. "References" are actually values.
using T_Visitor = ::ebcl::T_Visitor< T_Node , T_Node >;
private:
// Internal storage for nodes
struct T_Node_
{
// Node type
@ -108,6 +127,14 @@ template<
// Access the data stored inside a node
template< typename D >
D& dataOf( uint32_t node );
//----------------------------------------------------------------------
// Return a visitor suitable for this syntax tree
T_Visitor visitor( ) const noexcept;
// Return the root node in a format that can be fed to a visitor
T_Node root( ) const noexcept;
};
template< typename T , size_t S >

View file

@ -10,6 +10,51 @@ namespace ebcl {
/*= T_SyntaxTree =============================================================*/
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_Node::T_Node(
T_Self const& tree ,
const uint32_t node ) noexcept
: tree{ tree } , node{ node }
{
// EMPTY
}
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_Node::T_Node(
T_Node const& other ) noexcept
: tree{ other.tree } , node{ other.node }
{
// EMPTY
}
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_Node::T_Node(
T_Node&& other ) noexcept
: T_Node( other )
{
// EMPTY
}
template< typename T , size_t S >
typename T_SyntaxTree< T , S >::T_Node& T_SyntaxTree< T , S >::T_Node::operator =(
T_SyntaxTree< T , S >::T_Node const& other ) noexcept
{
assert( &other.tree == &tree );
node = other.node;
return *this;
}
template< typename T , size_t S >
typename T_SyntaxTree< T , S >::T_Node& T_SyntaxTree< T , S >::T_Node::operator =(
T_SyntaxTree< T , S >::T_Node&& other ) noexcept
{
assert( &other.tree == &tree );
node = other.node;
return *this;
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_Node_::T_Node_(
const T nodeType ,
@ -157,6 +202,28 @@ D& T_SyntaxTree< T , S >::dataOf(
return nodes_[ node ].data.template value< D >( );
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
typename T_SyntaxTree< T , S >::T_Visitor T_SyntaxTree< T , S >::visitor( ) const noexcept
{
return T_Visitor{
[this]( T_Node node , uint32_t child ) -> T_Optional< T_Node > {
auto const& n{ nodes_[ node.node ] };
if ( child >= n.children.size( ) ) {
return {};
}
return T_Node{ node.tree , n.children[ child ] };
}
};
}
template< typename T , size_t S >
typename T_SyntaxTree< T , S >::T_Node T_SyntaxTree< T , S >::root( ) const noexcept
{
return T_Node{ *this , 0 };
}
} // namespace
#endif // _H_EBCL_INLINE_SYNTAXTREE