corelib/include/ebcl/inline/SyntaxTree.hh
Emmanuel BENOîT b659f2f237 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.
2018-03-31 22:11:00 +02:00

229 lines
5.6 KiB
C++

/******************************************************************************/
/* ABSTRACT SYNTAX TREE - INLINE CODE******************************************/
/******************************************************************************/
#ifndef _H_EBCL_INLINE_SYNTAXTREE
#define _H_EBCL_INLINE_SYNTAXTREE
#include <ebcl/SyntaxTree.hh>
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 ,
const uint32_t parent ) noexcept
: type{ nodeType } , parent{ parent }
{
// EMPTY
}
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_Node_::T_Node_(
T_Node_&& other ) noexcept
: type{ other.type } , parent{ other.parent } ,
children{ std::move( other.children ) } ,
data{ std::move( other.data ) }
{
// EMPTY
}
template< typename T , size_t S >
typename T_SyntaxTree< T , S >::T_Node_& T_SyntaxTree< T , S >::T_Node_::operator =(
T_Node_&& other ) noexcept
{
type = other.type;
parent = other.parent;
children = std::move( other.children );
data = std::move( other.data );
return *this;
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_SyntaxTree(
const T rootType ) noexcept
: nodes_( 64 )
{
nodes_.addNew( rootType , 0 );
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
T_SyntaxTree< T , S >::T_SyntaxTree(
T_SyntaxTree< T , S >&& other ) noexcept
: nodes_{ std::move( other.nodes_ ) }
{
// EMPTY
}
template< typename T , size_t S >
T_SyntaxTree< T , S >& T_SyntaxTree< T , S >::operator =(
T_SyntaxTree< T , S >&& other ) noexcept
{
nodes_ = std::move( other.nodes_ );
return *this;
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
T_SyntaxTree< T , S >& T_SyntaxTree< T , S >::swap(
T_SyntaxTree< T , S >& other ) noexcept
{
using std::swap;
swap( nodes_ , other.nodes_ );
return *this;
}
template< typename T , size_t S >
void swap( T_SyntaxTree< T , S >& lhs ,
T_SyntaxTree< T , S >& rhs ) noexcept
{
lhs.swap( rhs );
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
T T_SyntaxTree< T , S >::typeOf(
const uint32_t node ) const noexcept
{
return nodes_[ node ].type;
}
template< typename T , size_t S >
uint32_t T_SyntaxTree< T , S >::parentOf(
const uint32_t node ) const noexcept
{
return nodes_[ node ].parent;
}
template< typename T , size_t S >
T_AutoArray< uint32_t , 8 > const& T_SyntaxTree< T , S >::childrenOf(
const uint32_t node ) const noexcept
{
return nodes_[ node ].children;
}
template< typename T , size_t S >
bool T_SyntaxTree< T , S >::hasData(
const uint32_t node ) const noexcept
{
return bool( nodes_[ node ].data );
}
template< typename T , size_t S >
template< typename D >
D const& T_SyntaxTree< T , S >::dataOf(
const uint32_t node ) const
{
return nodes_[ node ].data.template value< D >( );
}
/*----------------------------------------------------------------------------*/
template< typename T , size_t S >
uint32_t T_SyntaxTree< T , S >::addChild(
const uint32_t parent ,
const E_Node type ) noexcept
{
T_Node_ node{ type , parent };
const auto idx{ nodes_.add( std::move( node ) ) };
assert( idx != parent );
nodes_[ parent ].children.add( idx );
return idx;
}
template< typename T , size_t S >
template< typename D , typename ... ArgTypes >
D& T_SyntaxTree< T , S >::newData(
const uint32_t node ,
ArgTypes&& ... args )
{
auto& data{ nodes_[ node ].data };
data.template setNew< D >( std::forward< ArgTypes >( args ) ... );
return data.template value< D >( );
}
template< typename T , size_t S >
template< typename D >
D& T_SyntaxTree< T , S >::dataOf(
const uint32_t node )
{
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