#pragma once #include "odbg.hh" #include namespace opast { using namespace ebcl; class T_RootNode; class A_Node { public: enum E_Type { ROOT , // Root node ILIST , // Instruction list // DECL_INIT , // Initialisation block DECL_FRAME , // Frame block DECL_FN , // Function // OP_CALL , // Function call OP_COND , // Conditional instruction OP_FRAMEBUFFER ,// Define framebuffer OP_FULLSCREEN , // Draw a fullscreen quad OP_INPUT , // Input declaration OP_ODBG , // Output debugging OP_PIPELINE , // Shader pipeline declaration OP_PROFILE , // Profiling block OP_PROGRAM , // Shader program declaration OP_SAMPLER , // Define sampler OP_SET , // Set instruction OP_TEXTURE , // Define texture OP_UNIFORMS , // Set uniforms OP_VIEWPORT , // Set viewport // "Use-" instructions OP_USE_FRAMEBUFFER , OP_USE_PIPELINE , OP_USE_PROGRAM , OP_USE_TEXTURE , // Unary operators EXPR_NEG , EXPR_INV , EXPR_NOT , EXPR_SIN , EXPR_COS , EXPR_TAN , EXPR_SQRT , EXPR_EXP , EXPR_LN , // Binary operators EXPR_ADD , EXPR_SUB , EXPR_MUL , EXPR_DIV , EXPR_POW , // Binary operators - comparisons EXPR_CMP_EQ , EXPR_CMP_NE , EXPR_CMP_GT , EXPR_CMP_GE , EXPR_CMP_LT , EXPR_CMP_LE , // EXPR_ID , // Variable access EXPR_INPUT , // Input value access EXPR_CONST , // Numeric constant }; 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; }; // Browser function to be used with T_Visitor extern A_Node* ASTVisitorBrowser( A_Node& node , const uint32_t child ) noexcept; /*============================================================================*/ // Some instructions are restricted to either the initialisation code or the // frame code. enum class E_InstrRestriction { INIT , FRAME }; using T_InstrRestriction = T_Flags< E_InstrRestriction >; // Base class for instruction nodes class A_InstructionNode : public A_Node { private: const T_InstrRestriction restriction_; protected: A_InstructionNode( const E_Type type , A_Node& parent , T_InstrRestriction restriction = {} ) noexcept : A_Node( type , &parent ) , restriction_( restriction ) { assert( !restriction_.isSet({ E_InstrRestriction::INIT , E_InstrRestriction::FRAME }) ); } public: T_InstrRestriction restriction( ) const noexcept { return restriction_; } }; // 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 : A_Node( ILIST , &parent ) { } template< typename IType , typename... ArgTypes > 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< typename IType , typename... ArgTypes > inline IType& T_InstrListNode::add( ArgTypes&&... args ) { instructions_.add( NewOwned< IType >( *this , std::forward< ArgTypes >( args ) ... ) ); return (IType&) *instructions_.last( ); } /*----------------------------------------------------------------------------*/ // Function-like nodes class A_FuncNode : public A_Node { private: T_String name_; T_InstrListNode instructions_; 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_; } T_InstrListNode& instructions( ) noexcept { return instructions_; } T_InstrListNode const& instructions( ) const noexcept { return instructions_; } }; using P_InstrListNode = T_OwnPtr< T_InstrListNode >; // 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; // --------------------------------------------------------------------- // 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; // --------------------------------------------------------------------- bool hasFunction( T_String const& name ) noexcept { return functions_.contains( name ); } bool hasInit( ) noexcept { return hasFunction( "*init*" ); } bool hasFrame( ) noexcept { return hasFunction( "*frame*" ); } uint32_t nFunctions( ) const noexcept { return functions_.size( ); } int32_t functionIndex( T_String const& name ) const noexcept { return functions_.indexOf( name ); } A_FuncNode& function( const uint32_t index ) const noexcept { return *functions_.values( )[ index ]; } }; /*----------------------------------------------------------------------------*/ // Init & frame functions class T_SpecialFuncNode : public A_FuncNode { public: T_SpecialFuncNode( bool isInit , T_RootNode& parent ) noexcept : A_FuncNode( isInit , &parent ) { } }; // 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 : A_FuncNode( name , &parent ) { } // 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; uint32_t arguments( ) const noexcept { return argNames_.size( ); } }; /*----------------------------------------------------------------------------*/ // Base class for expressions class A_ExpressionNode : public A_Node { protected: A_ExpressionNode( E_Type type , A_Node& parent ) noexcept : A_Node( type , &parent ) { } }; using P_ExpressionNode = T_OwnPtr< A_ExpressionNode >; /*============================================================================*/ // Function call class T_CallInstrNode : public A_InstructionNode { private: T_String id_; T_SRDLocation idLocation_; T_AutoArray< P_ExpressionNode , 8 > arguments_; public: T_CallInstrNode( T_InstrListNode& parent , T_SRDToken const& idToken ) noexcept : A_InstructionNode( OP_CALL , parent ) , id_( idToken.stringValue( ) ) , idLocation_( idToken.location( ) ) { } void addArgument( P_ExpressionNode expr ) noexcept { if ( expr ) { arguments_.add( std::move( expr ) ); } } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } uint32_t arguments( ) const noexcept { return arguments_.size( ); } A_ExpressionNode& argument( const uint32_t index ) const noexcept { return *arguments_[ index ]; } }; // Conditional instruction class T_CondInstrNode : public A_InstructionNode { private: P_ExpressionNode expression_; T_KeyValueTable< int64_t , P_InstrListNode > cases_; P_InstrListNode defaultCase_; public: explicit T_CondInstrNode( T_InstrListNode& parent ) noexcept : A_InstructionNode( OP_COND , parent ) { } void setExpression( P_ExpressionNode expression ) noexcept { expression_ = std::move( expression ); } bool hasExpression( ) const noexcept { return bool( expression_ ); } A_ExpressionNode& expression( ) const noexcept { return *expression_; } void setCase( const int64_t value , P_InstrListNode instrList ) noexcept { if ( instrList ) { cases_.set( value , std::move( instrList ) ); } } void rmCase( const int64_t value ) noexcept { cases_.remove( value ); } T_Array< int64_t > const& cases( ) const noexcept { return cases_.keys( ); } bool hasCase( const int64_t value ) const noexcept { return cases_.contains( value ); } T_InstrListNode& getCase( const int64_t value ) const noexcept { return **cases_.get( value ); } void setDefaultCase( P_InstrListNode defaultCase ) noexcept { defaultCase_ = std::move( defaultCase ); } bool hasDefaultCase( ) const noexcept { return bool( defaultCase_ ); } T_InstrListNode& defaultCase( ) const noexcept { return *defaultCase_; } }; // Framebuffer definition instruction class T_FramebufferInstrNode : public A_InstructionNode { private: T_String idFramebuffer_; T_SRDLocation locFramebuffer_; T_AutoArray< T_String , 8 > idColorAttachments_; T_AutoArray< T_SRDLocation , 8 > locColorAttachments_; T_String idDepthAttachment_; T_SRDLocation locDepthAttachment_; public: T_FramebufferInstrNode( T_InstrListNode& parent , T_SRDToken const& identifier ) noexcept : A_InstructionNode( OP_FRAMEBUFFER , parent , E_InstrRestriction::FRAME ) , idFramebuffer_( identifier.stringValue( ) ) , locFramebuffer_( identifier.location( ) ) { } // --------------------------------------------------------------------- T_String const& id( ) const noexcept { return idFramebuffer_; } T_SRDLocation const& idLocation( ) const noexcept { return locFramebuffer_; } // --------------------------------------------------------------------- bool addColorAttachment( T_SRDToken const& id ) noexcept; uint32_t colorAttachments( ) const noexcept { return idColorAttachments_.size( ); } T_String const& colorAttachment( const uint32_t index ) const noexcept { return idColorAttachments_[ index ]; } T_SRDLocation const& colorAttachmentLocation( const uint32_t index ) const noexcept { return locColorAttachments_[ index ]; } // --------------------------------------------------------------------- bool setDepthAttachment( T_SRDToken const& token ) noexcept; bool hasDepthAttachment( ) const noexcept { return bool( idDepthAttachment_ ); } T_String const& depthAttachment( ) const noexcept { return idDepthAttachment_; } T_SRDLocation const& depthAttachmentLocation( ) const noexcept { return locDepthAttachment_; } }; // Fullscreen quad instruction class T_FullscreenInstrNode : public A_InstructionNode { public: T_FullscreenInstrNode( T_InstrListNode& parent ) noexcept : A_InstructionNode( OP_FULLSCREEN , parent , E_InstrRestriction::INIT ) { } }; // Input declaration class T_InputInstrNode : public A_InstructionNode { private: T_String name_; T_SRDLocation nameLocation_; float defValue_; T_SRDLocation dvLocation_; public: T_InputInstrNode( T_InstrListNode& parent , T_SRDToken const& tName ) noexcept : A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) , name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) ) {} T_InputInstrNode( T_InstrListNode& parent , T_SRDToken const& tName , T_SRDToken const& tDefault ) noexcept : A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) , name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) ) , defValue_( tDefault.floatValue( ) ) , dvLocation_( tDefault.location( ) ) {} T_String const& name( ) const noexcept { return name_; } T_SRDLocation const& nameLocation( ) const noexcept { return nameLocation_; } float defValue( ) const noexcept { return defValue_; } T_SRDLocation const& defValueLocation( ) const noexcept { return dvLocation_; } }; // Output debugging class T_OutputDebugInstrNode : public A_InstructionNode { private: T_String idTexture_; T_SRDLocation locTexture_; E_ODbgMode mode_; T_SRDLocation locMode_; T_String description_; T_SRDLocation locDescription_; public: T_OutputDebugInstrNode( T_InstrListNode& parent , T_SRDToken const& texture , const E_ODbgMode mode , T_SRDLocation const& modeLocation , T_SRDToken const& description ) noexcept; T_String const& texture( ) const noexcept { return idTexture_; } T_SRDLocation const& textureLocation( ) const noexcept { return locTexture_; } E_ODbgMode mode( ) const noexcept { return mode_; } T_SRDLocation const& modeLocation( ) const noexcept { return locMode_; } T_String const& description( ) const noexcept { return description_; } T_SRDLocation const& descriptionLocation( ) const noexcept { return locDescription_; } }; // 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 : A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) , id_( idToken.stringValue( ) ) , idLocation_( idToken.location( ) ) { } explicit T_PipelineInstrNode( T_InstrListNode& parent ) noexcept : A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) , id_( "*invalid*" ) , idLocation_{ } { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } // 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 : A_InstructionNode( OP_PROFILE , parent , E_InstrRestriction::INIT ) , text_( text ) , instructions_( *this ) { } 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 : A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) , id_( idToken.stringValue( ) ) , idLocation_( idToken.location( ) ) , path_( pathToken.stringValue( ) ) , pathLocation_( pathToken.location( ) ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } }; // Sampler definition class T_SamplerInstrNode : public A_InstructionNode { private: struct T_Sampling_ { T_SRDLocation location; E_TexSampling mode; }; struct T_Mipmaps_ { T_SRDLocation location; T_Optional< E_TexSampling > mode; }; struct T_Wrapping_ { T_SRDLocation location; E_TexWrap mode; }; struct T_LOD_ { T_SRDLocation location; P_ExpressionNode min; P_ExpressionNode max; }; T_String id_; T_SRDLocation idLocation_; T_Optional< T_Sampling_ > sampling_; T_Optional< T_Mipmaps_ > mipmaps_; T_Optional< T_Wrapping_ > wrapping_; T_Optional< T_LOD_ > lod_; public: T_SamplerInstrNode( T_InstrListNode& parent , T_SRDToken const& id ) noexcept : A_InstructionNode( OP_SAMPLER , parent ) , id_( id.stringValue( ) ) , idLocation_( id.location( ) ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } // Attempt to set sampling mode, mipmap mode, wrapping mode or // LOD minimal/maximal, returning the location of the previous // definition if there was one. T_Optional< T_SRDLocation > setSampling( E_TexSampling mode , T_SRDLocation const& location ) noexcept; T_Optional< T_SRDLocation > setMipmapSampling( E_TexSampling mode , T_SRDLocation const& location ) noexcept; T_Optional< T_SRDLocation > setNoMipmap( T_SRDLocation const& location ) noexcept; T_Optional< T_SRDLocation > setWrapping( E_TexWrap mode , T_SRDLocation const& location ) noexcept; T_Optional< T_SRDLocation > setLOD( T_SRDLocation const& location , P_ExpressionNode min , P_ExpressionNode max ) noexcept; // Get either the defined values or the defaults E_TexSampling sampling( ) const noexcept { return sampling_ ? sampling_->mode : E_TexSampling::NEAREST; } T_Optional< E_TexSampling > mipmap( ) const noexcept { return mipmaps_ ? mipmaps_->mode : T_Optional< E_TexSampling >{}; } E_TexWrap wrapping( ) const noexcept { return wrapping_ ? wrapping_->mode : E_TexWrap::REPEAT; } A_ExpressionNode* minLod( ) const noexcept { return lod_ ? lod_->min.get( ) : nullptr; } A_ExpressionNode* maxLod( ) const noexcept { return lod_ ? lod_->max.get( ) : nullptr; } }; // Setting a global variable class T_SetInstrNode : public A_InstructionNode { private: T_String id_; T_SRDLocation idLocation_; P_ExpressionNode expression_; public: T_SetInstrNode( T_InstrListNode& parent , T_SRDToken const& idToken ) noexcept : A_InstructionNode( OP_SET , parent ) , id_( idToken.stringValue( ) ) , idLocation_( idToken.location( ) ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } void setExpression( P_ExpressionNode expression ) noexcept { expression_ = std::move( expression ); } bool hasExpression( ) const noexcept { return bool( expression_ ); } A_ExpressionNode& expression( ) const noexcept { return *expression_; } }; // Texture definition class T_TextureInstrNode : public A_InstructionNode { private: T_String id_; T_SRDLocation idLocation_; E_TexType type_; P_ExpressionNode width_; P_ExpressionNode height_; public: T_TextureInstrNode( T_InstrListNode& parent , T_SRDToken const& id , E_TexType type ) noexcept : A_InstructionNode( OP_TEXTURE , parent , E_InstrRestriction::FRAME ) , id_( id.stringValue( ) ) , idLocation_( id.location( ) ) , type_( type ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } void setWidth( P_ExpressionNode width ) noexcept { width_ = std::move( width ); } bool hasWidth( ) const noexcept { return bool( width_ ); } A_ExpressionNode& width( ) const noexcept { return *width_; } void setHeight( P_ExpressionNode height ) noexcept { height_ = std::move( height ); } bool hasHeight( ) const noexcept { return bool( height_ ); } A_ExpressionNode& height( ) const noexcept { return *height_; } }; // Uniform setting instruction class T_UniformsInstrNode : public A_InstructionNode { private: bool integers_; T_String progId_; T_SRDLocation progIdLocation_; uint32_t uloc_; T_SRDLocation ulocLocation_; T_StaticArray< P_ExpressionNode , 4 > values_; public: T_UniformsInstrNode( T_InstrListNode& parent , const bool integers , T_SRDToken const& prog , T_SRDToken const& loc ) noexcept : A_InstructionNode( OP_UNIFORMS , parent ) , integers_( integers ) , progId_( prog.stringValue( ) ) , progIdLocation_( prog.location( ) ) , uloc_( loc.longValue( ) ) , ulocLocation_( loc.location( ) ) { } bool integers( ) const noexcept { return integers_; } T_String const& progId( ) const noexcept { return progId_; } T_SRDLocation const& progIdLocation( ) const noexcept { return progIdLocation_; } uint32_t uloc( ) const noexcept { return uloc_; } T_SRDLocation const& ulocLocation( ) const noexcept { return ulocLocation_; } void addValue( P_ExpressionNode value ) noexcept { if ( value ) { values_.add( std::move( value ) ); } } uint32_t values( ) const noexcept { return values_.size( ); } A_ExpressionNode& value( const uint32_t index ) const noexcept { return *values_[ index ]; } }; // Use-* instructions (framebuffers, programs, pipelines) // Also serves as the base for use-texture class T_UseInstrNode : public A_InstructionNode { public: enum E_Type { FRAMEBUFFER , PIPELINE , PROGRAM , TEXTURE }; private: T_String id_; T_SRDLocation idLocation_; public: T_UseInstrNode( T_InstrListNode& parent , const E_Type type , T_SRDToken const& identifier ) noexcept : A_InstructionNode( ([type]() { switch ( type ) { case FRAMEBUFFER: return OP_USE_FRAMEBUFFER; case PIPELINE: return OP_USE_PIPELINE; case PROGRAM: return OP_USE_PROGRAM; case TEXTURE: return OP_USE_TEXTURE; } std::abort( ); } )( ) , parent ) , id_( identifier.stringValue( ) ) , idLocation_( identifier.location( ) ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } }; // Texture/sampler use instructions class T_UseTextureInstrNode : public T_UseInstrNode { private: uint32_t bank_; T_SRDLocation bankLocation_; T_String samplerId_; T_SRDLocation samplerIdLocation_; public: T_UseTextureInstrNode( T_InstrListNode& parent , T_SRDToken const& bank , T_SRDToken const& identifier , T_SRDToken const& sampler ) noexcept : T_UseInstrNode( parent , TEXTURE , identifier ) , bank_( bank.longValue( ) ) , bankLocation_( bank.location( ) ) , samplerId_( sampler.stringValue( ) ) , samplerIdLocation_( sampler.location( ) ) { } uint32_t bank( ) const noexcept { return bank_; } T_SRDLocation const& bankLocation( ) const noexcept { return bankLocation_; } T_String const& samplerId( ) const noexcept { return samplerId_; } T_SRDLocation const& samplerIdLocation( ) const noexcept { return samplerIdLocation_; } }; // Viewport instruction class T_ViewportInstrNode : public A_InstructionNode { public: enum E_Parameter { PX , PY , PWIDTH , PHEIGHT }; private: P_ExpressionNode parameters_[ 4 ]; public: T_ViewportInstrNode( T_InstrListNode& parent ) noexcept : A_InstructionNode( OP_VIEWPORT , parent , E_InstrRestriction::INIT ) { } void setParameter( const E_Parameter p , P_ExpressionNode height ) noexcept { parameters_[ int( p ) ] = std::move( height ); } bool hasParameter( const E_Parameter p ) const noexcept { return bool( parameters_[ int( p ) ] ); } A_ExpressionNode& parameter( const E_Parameter p ) const noexcept { return *parameters_[ int( p ) ]; } }; /*============================================================================*/ // A constant value class T_ConstantExprNode : public A_ExpressionNode { private: bool wasFloat_; double vFloat_; int64_t vInt_; public: T_ConstantExprNode( A_Node& parent , T_SRDToken const& token ) noexcept : A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( token.type( ) == E_SRDTokenType::FLOAT ) , vFloat_( token.floatValue( ) ) , vInt_( token.longValue( ) ) { location( ) = token.location( ); } T_ConstantExprNode( A_Node& parent , int64_t value ) noexcept : A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( false ) , vFloat_( value ) , vInt_( value ) { } T_ConstantExprNode( A_Node& parent , double value ) noexcept : A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( true ) , vFloat_( value ) , vInt_( (int64_t) value ) { } bool wasFloat( ) const noexcept { return wasFloat_; } double floatValue( ) const noexcept { return vFloat_; } int64_t intValue( ) const noexcept { return vInt_; } }; // An identifier used in an expression class T_IdentifierExprNode : public A_ExpressionNode { private: T_String id_; public: T_IdentifierExprNode( A_Node& parent , T_SRDToken const& token ) noexcept : T_IdentifierExprNode( parent , token.stringValue( ) ) { location( ) = token.location( ); } T_IdentifierExprNode( A_Node& parent , T_String const& id ) noexcept : A_ExpressionNode( EXPR_ID , parent ) , id_( id ) { } T_String const& id( ) const noexcept { return id_; } }; // Access to an input value class T_InputExprNode : public A_ExpressionNode { private: T_String id_; T_SRDLocation idLocation_; public: T_InputExprNode( A_Node& parent , T_SRDToken const& token ) noexcept : A_ExpressionNode( EXPR_INPUT , parent ) , id_( token.stringValue( ) ) , idLocation_( token.location( ) ) { } T_String const& id( ) const noexcept { return id_; } T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } }; // A unary operator class T_UnaryOperatorNode : public A_ExpressionNode { public: enum E_Operator { NEG , INV , NOT , SIN , COS , TAN , SQRT , EXP , LN }; private: E_Operator op_; P_ExpressionNode argument_; public: T_UnaryOperatorNode( A_Node& parent , const E_Operator op ) noexcept; E_Operator op( ) const noexcept { return op_; } void setArgument( P_ExpressionNode argument ) noexcept { argument_ = std::move( argument ); } bool hasArgument( ) const noexcept { return bool( argument_ ); } A_ExpressionNode const& argument( ) const noexcept { return *argument_; } A_ExpressionNode& argument( ) noexcept { return *argument_; } }; // A binary operator class T_BinaryOperatorNode : public A_ExpressionNode { public: enum E_Operator { ADD , SUB , MUL , DIV , POW , CMP_EQ , CMP_NE , CMP_GT , CMP_GE , CMP_LT , CMP_LE , }; private: E_Operator op_; P_ExpressionNode left_; P_ExpressionNode right_; public: T_BinaryOperatorNode( A_Node& parent , const E_Operator op ) noexcept; E_Operator op( ) const noexcept { return op_; } void setLeft( P_ExpressionNode left ) noexcept { left_ = std::move( left ); } void setRight( P_ExpressionNode right ) noexcept { right_ = std::move( right ); } bool hasLeft( ) const noexcept { return bool( left_ ); } bool hasRight( ) const noexcept { return bool( right_ ); } A_ExpressionNode const& left( ) const noexcept { return *left_; } A_ExpressionNode& left( ) noexcept { return *left_; } A_ExpressionNode const& right( ) const noexcept { return *right_; } A_ExpressionNode& right( ) noexcept { return *right_; } }; /*============================================================================*/ 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