Parser - Visitor test
This commit is contained in:
parent
103fbcb6f2
commit
67b644ac54
2 changed files with 245 additions and 0 deletions
10
opast.hh
10
opast.hh
|
@ -99,6 +99,11 @@ class T_InstrListNode : public A_Node
|
||||||
typename IType ,
|
typename IType ,
|
||||||
typename... ArgTypes
|
typename... ArgTypes
|
||||||
> IType& add( ArgTypes&&... args );
|
> IType& add( ArgTypes&&... args );
|
||||||
|
|
||||||
|
uint32_t size( ) const noexcept
|
||||||
|
{ return instructions_.size( ); }
|
||||||
|
A_InstructionNode& node( const uint32_t index ) const noexcept
|
||||||
|
{ return *instructions_[ index ]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<
|
template<
|
||||||
|
@ -189,6 +194,11 @@ class T_RootNode : public A_Node
|
||||||
{ return hasFunction( "*init*" ); }
|
{ return hasFunction( "*init*" ); }
|
||||||
bool hasFrame( ) noexcept
|
bool hasFrame( ) noexcept
|
||||||
{ return hasFunction( "*frame*" ); }
|
{ return hasFunction( "*frame*" ); }
|
||||||
|
|
||||||
|
uint32_t nFunctions( ) const noexcept
|
||||||
|
{ return functions_.size( ); }
|
||||||
|
A_FuncNode& function( const uint32_t index ) const noexcept
|
||||||
|
{ return *functions_.values( )[ index ]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
235
parsercheck.cc
235
parsercheck.cc
|
@ -8,6 +8,232 @@ using namespace opast;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/*============================================================================*/
|
||||||
|
// FIXME TESTING, MOVE THIS LATER
|
||||||
|
|
||||||
|
template< typename NodeType >
|
||||||
|
class T_Visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using T_Node = NodeType;
|
||||||
|
|
||||||
|
// Node browser. Returns the Nth child of the specified node, or null
|
||||||
|
// if there are no children left.
|
||||||
|
using F_NodeBrowser = std::function< T_Node*( T_Node& , uint32_t ) >;
|
||||||
|
|
||||||
|
// Node action. Second parameter indicates whether the action is
|
||||||
|
// being called before (false) or after (true) visiting the children.
|
||||||
|
using F_NodeAction = std::function< bool( T_Node& , bool ) >;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum E_State_ {
|
||||||
|
BEFORE , CHILDREN , AFTER
|
||||||
|
};
|
||||||
|
struct T_NodeRef_ {
|
||||||
|
T_Node* node;
|
||||||
|
uint32_t child;
|
||||||
|
E_State_ state{ BEFORE };
|
||||||
|
|
||||||
|
explicit T_NodeRef_( T_Node* node )
|
||||||
|
: node( node ) , child( 0 ) {}
|
||||||
|
explicit T_NodeRef_( T_Node* node , uint32_t child )
|
||||||
|
: node( node ) , child( child ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
F_NodeBrowser nodeBrowser_;
|
||||||
|
T_Array< T_NodeRef_ > stack_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
T_Visitor( ) = delete;
|
||||||
|
T_Visitor( T_Visitor const& ) noexcept = default;
|
||||||
|
T_Visitor( T_Visitor&& ) noexcept = default;
|
||||||
|
|
||||||
|
explicit T_Visitor( F_NodeBrowser browser ) noexcept;
|
||||||
|
|
||||||
|
void visit( T_Node& root , F_NodeAction action );
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline T_Visitor< T >::T_Visitor(
|
||||||
|
F_NodeBrowser browser ) noexcept
|
||||||
|
: nodeBrowser_( std::move( browser ) )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline void T_Visitor< T >::visit(
|
||||||
|
T_Node& root ,
|
||||||
|
F_NodeAction action )
|
||||||
|
{
|
||||||
|
stack_.addNew( &root , 0 );
|
||||||
|
|
||||||
|
while ( !stack_.empty( ) ) {
|
||||||
|
auto& n( stack_.last( ) );
|
||||||
|
switch ( n.state ) {
|
||||||
|
case BEFORE:
|
||||||
|
n.state = action( *n.node , false ) ? CHILDREN : AFTER;
|
||||||
|
break;
|
||||||
|
case CHILDREN: {
|
||||||
|
T_Node* child( nodeBrowser_( *n.node , n.child ++ ) );
|
||||||
|
if ( child ) {
|
||||||
|
stack_.addNew( child , 0 );
|
||||||
|
} else {
|
||||||
|
n.state = AFTER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AFTER:
|
||||||
|
action( *n.node , true );
|
||||||
|
stack_.removeLast( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
A_Node* OpASTBrowser(
|
||||||
|
A_Node& node ,
|
||||||
|
const uint32_t child )
|
||||||
|
{
|
||||||
|
switch ( node.type( ) ) {
|
||||||
|
|
||||||
|
// Root node
|
||||||
|
case A_Node::ROOT: {
|
||||||
|
auto& n( (T_RootNode&) node );
|
||||||
|
if ( child < n.nFunctions( ) ) {
|
||||||
|
return &n.function( child );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions / special blocks
|
||||||
|
case A_Node::DECL_FN: case A_Node::DECL_INIT: case A_Node::DECL_FRAME:
|
||||||
|
if ( child == 0 ) {
|
||||||
|
auto& n( (A_FuncNode&) node );
|
||||||
|
return &n.instructions( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Instruction list
|
||||||
|
case A_Node::ILIST: {
|
||||||
|
auto& n( (T_InstrListNode&) node );
|
||||||
|
if ( child < n.size( ) ) {
|
||||||
|
return &n.node( child );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unary operators
|
||||||
|
case A_Node::EXPR_NEG: case A_Node::EXPR_INV:
|
||||||
|
case A_Node::EXPR_NOT: case A_Node::EXPR_SIN:
|
||||||
|
case A_Node::EXPR_COS: case A_Node::EXPR_TAN:
|
||||||
|
case A_Node::EXPR_SQRT: case A_Node::EXPR_EXP:
|
||||||
|
case A_Node::EXPR_LN:
|
||||||
|
{
|
||||||
|
auto& n( (T_UnaryOperatorNode&) node );
|
||||||
|
if ( child == 0 && n.hasArgument( ) ) {
|
||||||
|
return &n.argument( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary operators
|
||||||
|
case A_Node::EXPR_ADD: case A_Node::EXPR_SUB:
|
||||||
|
case A_Node::EXPR_MUL: case A_Node::EXPR_DIV:
|
||||||
|
case A_Node::EXPR_POW:
|
||||||
|
case A_Node::EXPR_CMP_EQ: case A_Node::EXPR_CMP_NE:
|
||||||
|
case A_Node::EXPR_CMP_GT: case A_Node::EXPR_CMP_GE:
|
||||||
|
case A_Node::EXPR_CMP_LT: case A_Node::EXPR_CMP_LE:
|
||||||
|
{
|
||||||
|
auto& n( (T_BinaryOperatorNode&) node );
|
||||||
|
if ( child == 0 && n.hasLeft( ) ) {
|
||||||
|
return &n.left( );
|
||||||
|
}
|
||||||
|
if ( child < 2 && n.hasRight( ) ) {
|
||||||
|
return &n.right( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes that do not have children
|
||||||
|
case A_Node::EXPR_ID: case A_Node::EXPR_CONST:
|
||||||
|
case A_Node::OP_PROGRAM: case A_Node::OP_PIPELINE:
|
||||||
|
case A_Node::OP_INPUT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Profile instruction
|
||||||
|
case A_Node::OP_PROFILE:
|
||||||
|
if ( child == 0 ) {
|
||||||
|
return &( ((T_ProfileInstrNode&) node).instructions( ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Call instruction
|
||||||
|
case A_Node::OP_CALL:
|
||||||
|
{
|
||||||
|
auto& n( (T_CallInstrNode&) node );
|
||||||
|
if ( child < n.arguments( ) ) {
|
||||||
|
return &n.argument( child );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditional instruction
|
||||||
|
case A_Node::OP_COND:
|
||||||
|
{
|
||||||
|
auto& n( (T_CondInstrNode&) node );
|
||||||
|
auto c = child;
|
||||||
|
if ( n.hasExpression( ) ) {
|
||||||
|
if ( c == 0 ) {
|
||||||
|
return &n.expression( );
|
||||||
|
}
|
||||||
|
c --;
|
||||||
|
}
|
||||||
|
if ( !n.cases( ).empty( ) ) {
|
||||||
|
if ( c < n.cases( ).size( ) ) {
|
||||||
|
return &n.getCase( n.cases( )[ c ] );
|
||||||
|
}
|
||||||
|
c -= n.cases( ).size( );
|
||||||
|
}
|
||||||
|
if ( n.hasDefaultCase( ) && c == 0 ) {
|
||||||
|
return &n.defaultCase( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set instruction
|
||||||
|
case A_Node::OP_SET:
|
||||||
|
if ( child == 0 ) {
|
||||||
|
auto& n( (T_SetInstrNode&) node );
|
||||||
|
if ( n.hasExpression( ) ) {
|
||||||
|
return &n.expression( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Texture instruction
|
||||||
|
case A_Node::OP_TEXTURE:
|
||||||
|
{
|
||||||
|
auto& n( (T_TextureInstrNode&) node );
|
||||||
|
auto c = child;
|
||||||
|
if ( n.hasWidth( ) ) {
|
||||||
|
if ( c == 0 ) {
|
||||||
|
return &n.width( );
|
||||||
|
}
|
||||||
|
c --;
|
||||||
|
}
|
||||||
|
if ( n.hasHeight( ) && c == 0 ) {
|
||||||
|
return &n.height( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*============================================================================*/
|
||||||
|
|
||||||
|
|
||||||
void PrintStreamError(
|
void PrintStreamError(
|
||||||
char const* const prefix ,
|
char const* const prefix ,
|
||||||
T_String const& name ,
|
T_String const& name ,
|
||||||
|
@ -69,6 +295,15 @@ int main( int argc , char** argv )
|
||||||
T_Parser parser;
|
T_Parser parser;
|
||||||
if ( parser.parse( srdOut.list( ) ) ) {
|
if ( parser.parse( srdOut.list( ) ) ) {
|
||||||
printf( "Success!\n" );
|
printf( "Success!\n" );
|
||||||
|
|
||||||
|
auto result( parser.result( ) );
|
||||||
|
T_Visitor< A_Node > visitor( OpASTBrowser );
|
||||||
|
visitor.visit( *result , []( A_Node& node , bool enter ) {
|
||||||
|
if ( enter ) {
|
||||||
|
printf( "Enter node %p\n" , &node );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
T_StringBuilder sb;
|
T_StringBuilder sb;
|
||||||
|
|
Loading…
Reference in a new issue