demotool/opast.hh

300 lines
7.2 KiB
C++
Raw Normal View History

2017-11-06 10:15:38 +01:00
#pragma once
//#ifndef REAL_BUILD
# include "externals.hh"
//#endif
#include <ebcl/SRDData.hh>
namespace opast {
using namespace ebcl;
class T_RootNode;
class A_Node
{
public:
enum E_Type {
2017-11-06 14:06:21 +01:00
ROOT , // Root node
ILIST , // Instruction list
2017-11-06 10:15:38 +01:00
//
2017-11-06 14:06:21 +01:00
DECL_INIT , // Initialisation block
DECL_FRAME , // Frame block
DECL_FN , // Function
2017-11-06 10:15:38 +01:00
//
2017-11-06 14:06:21 +01:00
OP_PIPELINE , // Shader pipeline declaration
OP_PROFILE , // Profiling block
OP_PROGRAM , // Shader program declaration
OP_SET , // Set instruction
2017-11-06 10:15:38 +01:00
//
2017-11-06 14:06:21 +01:00
EXPR_ADD , // Binary ops: add
EXPR_MUL , // Binary ops: mul
EXPR_SUB , // Binary ops: sub
EXPR_DIV , // Binary ops: div
EXPR_VAR , // Variable access
EXPR_CONST , // Numeric constant
2017-11-06 10:15:38 +01:00
};
private:
const E_Type type_;
A_Node* const parent_;
T_SRDLocation location_;
protected:
explicit A_Node( const E_Type type ,
A_Node* const parent ) noexcept;
public:
virtual ~A_Node( ) = 0;
E_Type type( ) const noexcept
{ return type_; }
T_SRDLocation& location( ) noexcept
{ return location_; }
T_SRDLocation const& location( ) const noexcept
{ return location_; }
A_Node& parent( ) const noexcept
{ assert( parent_ ); return *parent_; }
T_RootNode& root( ) const noexcept;
};
/*----------------------------------------------------------------------------*/
2017-11-06 14:06:21 +01:00
class A_InstructionNode : public A_Node
{
protected:
A_InstructionNode( E_Type type ,
A_Node& parent ) noexcept
: A_Node( type , &parent )
{}
};
// Nodes that store lists of instructions
class T_InstrListNode : public A_Node
{
private:
T_Array< T_OwnPtr< A_InstructionNode > > instructions_;
public:
T_InstrListNode( A_Node& parent ) noexcept;
template<
typename IType ,
typename... ArgTypes
> IType& add( ArgTypes&&... args );
};
template<
typename IType ,
typename... ArgTypes
> inline IType& T_InstrListNode::add(
ArgTypes&&... args )
{
instructions_.add( NewOwned< IType >( *this ,
std::forward< ArgTypes >( args ) ... ) );
return (IType&) *instructions_.last( );
}
/*----------------------------------------------------------------------------*/
2017-11-06 10:15:38 +01:00
// Function-like nodes
class A_FuncNode : public A_Node
{
private:
T_String name_;
2017-11-06 14:06:21 +01:00
T_InstrListNode instructions_;
2017-11-06 10:15:38 +01:00
protected:
// For init or frame entry points.
// isInit = true => init entry point
// isInit = false => frame entry point
explicit A_FuncNode( bool isInit ,
T_RootNode* const parent ) noexcept;
// For normal functions
explicit A_FuncNode( T_String const& name ,
T_RootNode* const parent ) noexcept;
public:
T_String const& name( ) const noexcept
{ return name_; }
2017-11-06 14:06:21 +01:00
T_InstrListNode& instructions( ) noexcept
{ return instructions_; }
T_InstrListNode const& instructions( ) const noexcept
{ return instructions_; }
2017-11-06 10:15:38 +01:00
};
// Root node, keeps track of the whole tree and related data (function table,
// assets...)
class T_RootNode : public A_Node
{
private:
T_ObjectTable< T_String , T_OwnPtr< A_FuncNode > > functions_;
public:
T_RootNode( ) noexcept;
2017-11-06 14:06:21 +01:00
// ---------------------------------------------------------------------
2017-11-06 10:15:38 +01:00
// Return type for addFunction. We'll always return a reference to a
// function node (which may or may not be the same as the initial one,
// if there were duplicates), and we'll return the location of the
// initial function in the case of a duplicate.
struct T_AddFunctionResult
{
A_FuncNode& function;
T_Optional< T_SRDLocation > dupLocation;
T_AddFunctionResult( A_FuncNode& function ) noexcept
: function{ function } , dupLocation{}
{}
T_AddFunctionResult( A_FuncNode& function ,
T_SRDLocation const& dupLocation ) noexcept
: function{ function } , dupLocation{ dupLocation }
{}
};
// Attempts to add a function. If the function is already present in
// the table, the result will be set up with the previous declaration's
// location, and the specified function will not be modified (a duplicate
// entry will be added to the table instead).
T_AddFunctionResult addFunction(
T_OwnPtr< A_FuncNode >& function ) noexcept;
2017-11-06 14:06:21 +01:00
// ---------------------------------------------------------------------
bool hasFunction( T_String const& name ) noexcept
{ return functions_.contains( name ); }
bool hasInit( ) noexcept
{ return hasFunction( "*init*" ); }
bool hasFrame( ) noexcept
{ return hasFunction( "*frame*" ); }
2017-11-06 10:15:38 +01:00
};
/*----------------------------------------------------------------------------*/
// Init & frame functions
class T_SpecialFuncNode : public A_FuncNode
{
public:
T_SpecialFuncNode(
bool isInit ,
T_RootNode& parent ) noexcept;
};
// Normal functions
class T_FuncNode : public A_FuncNode
{
private:
T_AutoArray< T_String , 8 > argNames_;
T_AutoArray< T_SRDLocation , 8 > argLocations_;
public:
T_FuncNode( T_String const& name ,
T_RootNode& parent ) noexcept;
// Add an argument. If the argument is a duplicate, return the location
// of the initial argument.
T_Optional< T_SRDLocation > addArgument(
T_SRDToken const& token ) noexcept;
};
2017-11-06 14:06:21 +01:00
/*============================================================================*/
// Pipeline declaration instruction
class T_PipelineInstrNode : public A_InstructionNode
{
private:
T_String id_;
T_SRDLocation idLocation_;
T_StaticArray< T_String , 6 > pids_;
T_StaticArray< T_SRDLocation , 6 > pidLocations_;
public:
T_PipelineInstrNode(
T_InstrListNode& parent ,
T_SRDToken const& idToken ) noexcept;
explicit T_PipelineInstrNode(
T_InstrListNode& parent ) noexcept;
// Add a program identifier. The token is assumed to be a valid word,
// and the list of programs is assumed not to be full. If the identifer
// is already in the pipeline's list, the location of the first
// occurrence will be returned.
T_Optional< T_SRDLocation > addProgram(
T_SRDToken const& pidToken ) noexcept;
uint32_t size( ) const noexcept
{ return pids_.size( ); }
T_String const& program( const uint32_t index ) const noexcept
{ return pids_[ index ]; }
T_SRDLocation const& pLocation( const uint32_t index ) const noexcept
{ return pidLocations_[ index ]; }
};
// Profiling instruction
class T_ProfileInstrNode : public A_InstructionNode
{
private:
T_String text_;
T_InstrListNode instructions_;
public:
T_ProfileInstrNode(
T_InstrListNode& parent ,
T_String const& text ) noexcept;
T_String const& text( ) const
{ return text_; }
T_InstrListNode& instructions( ) noexcept
{ return instructions_; }
T_InstrListNode const& instructions( ) const noexcept
{ return instructions_; }
};
// Program loader instruction
class T_ProgramInstrNode : public A_InstructionNode
{
private:
T_String id_;
T_SRDLocation idLocation_;
T_String path_;
T_SRDLocation pathLocation_;
public:
T_ProgramInstrNode(
T_InstrListNode& parent ,
T_SRDToken const& idToken ,
T_SRDToken const& pathToken ) noexcept;
};
/*============================================================================*/
2017-11-06 10:15:38 +01:00
class T_Parser : public A_PrivateImplementation
{
private:
T_Array< T_SRDError > errors_;
T_OwnPtr< T_RootNode > rootNode_;
public:
T_Parser( ) noexcept;
bool parse( T_SRDList const& input ) noexcept;
T_Array< T_SRDError > const& errors( ) const noexcept
{ return errors_; }
T_OwnPtr< T_RootNode > result( ) noexcept
{ return std::move( rootNode_ ); }
};
} // namespace opast