diff --git a/opast.cc b/opast.cc index a5704c4..da080db 100644 --- a/opast.cc +++ b/opast.cc @@ -304,6 +304,7 @@ struct T_ParserImpl_ enum class E_InstrType { CALL , IF , + INPUT , PIPELINE , PROFILE , PROGRAM , @@ -319,6 +320,7 @@ struct T_ParserImpl_ add( "call" , E_InstrType::CALL ); add( "if" , E_InstrType::IF ); + add( "input" , E_InstrType::INPUT ); add( "pipeline" , E_InstrType::PIPELINE ); add( "profiling" , E_InstrType::PROFILE ); add( "program" , E_InstrType::PROGRAM ); @@ -414,27 +416,21 @@ struct T_ParserImpl_ // --------------------------------------------------------------------- - void parseCallInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parseIfInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parsePipelineInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parseProfileInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parseProgramInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parseSetInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; - void parseTextureInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept; +#define M_DPARSER_( NAME ) \ + void parse##NAME##Instruction( \ + T_InstrListNode& instructions , \ + T_SRDList const& input ) noexcept + + M_DPARSER_( Call ); + M_DPARSER_( If ); + M_DPARSER_( Input ); + M_DPARSER_( Pipeline ); + M_DPARSER_( Profile ); + M_DPARSER_( Program ); + M_DPARSER_( Set ); + M_DPARSER_( Texture ); + +#undef M_DPARSER_ // --------------------------------------------------------------------- @@ -576,6 +572,7 @@ void T_ParserImpl_::parseInstructions( switch ( *instrMap.get( iword ) ) { M_CASE_( CALL , Call ); M_CASE_( IF , If ); + M_CASE_( INPUT , Input ); M_CASE_( PIPELINE , Pipeline ); M_CASE_( PROFILE , Profile ); M_CASE_( PROGRAM , Program ); @@ -603,9 +600,12 @@ P_InstrListNode T_ParserImpl_::parseBlock( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseCallInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +#define M_INSTR_( NAME ) \ + void T_ParserImpl_::parse##NAME##Instruction( \ + T_InstrListNode& instructions , \ + T_SRDList const& input ) noexcept + +M_INSTR_( Call ) { if ( input.size( ) == 1 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) { errors.addNew( "function identifier expected" , @@ -621,9 +621,7 @@ void T_ParserImpl_::parseCallInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseIfInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( If ) { if ( input.size( ) == 1 ) { errors.addNew( "expression and 'then' block expected" , @@ -652,9 +650,34 @@ void T_ParserImpl_::parseIfInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parsePipelineInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( Input ) +{ + if ( input.size( ) < 2 || !input[ 1 ].isText( ) ) { + errors.addNew( "input identifier expected" , + input[ input.size( ) < 2 ? 0 : 1 ].location( ) ); + return; + } + if ( input.size( ) > 3 ) { + errors.addNew( "too many arguments" , input[ 3 ].location( ) ); + } + if ( input.size( ) >= 3 && !input[ 2 ].isNumeric( ) ) { + errors.addNew( "default value expected" , input[ 2 ].location( ) ); + } + + const bool hasDefault( input.size( ) >= 3 && input[ 2 ].isNumeric( ) ); + auto& instr( ([&]() -> T_InputInstrNode& { + if ( hasDefault ) { + return instructions.add< T_InputInstrNode >( + input[ 1 ] , input[ 2 ] ); + } + return instructions.add< T_InputInstrNode >( input[ 1 ] ); + })( ) ); + instr.location( ) = input[ 0 ].location( ); +} + +/*----------------------------------------------------------------------------*/ + +M_INSTR_( Pipeline ) { if ( input.size( ) < 3 ) { errors.addNew( "identifier and program identifiers expected" , @@ -699,9 +722,7 @@ void T_ParserImpl_::parsePipelineInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseProfileInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( Profile ) { const bool hasEnough( input.size( ) < 2 ); if ( hasEnough || !input[ 1 ].isText( ) ) { @@ -720,9 +741,7 @@ void T_ParserImpl_::parseProfileInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseProgramInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( Program ) { bool ok{ true }; if ( input.size( ) == 1 ) { @@ -758,9 +777,7 @@ void T_ParserImpl_::parseProgramInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseSetInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( Set ) { bool ok{ true }; if ( input.size( ) == 1 ) { @@ -794,9 +811,7 @@ void T_ParserImpl_::parseSetInstruction( /*----------------------------------------------------------------------------*/ -void T_ParserImpl_::parseTextureInstruction( - T_InstrListNode& instructions , - T_SRDList const& input ) noexcept +M_INSTR_( Texture ) { if ( input.size( ) < 2 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) { errors.addNew( "texture identifier expected" , diff --git a/opast.hh b/opast.hh index 3a6689c..bdf5016 100644 --- a/opast.hh +++ b/opast.hh @@ -25,6 +25,7 @@ class A_Node // OP_CALL , // Function call OP_COND , // Conditional instruction + OP_INPUT , // Input declaration OP_PIPELINE , // Shader pipeline declaration OP_PROFILE , // Profiling block OP_PROGRAM , // Shader program declaration @@ -233,6 +234,7 @@ using P_ExpressionNode = T_OwnPtr< A_ExpressionNode >; /*============================================================================*/ +// Function call class T_CallInstrNode : public A_InstructionNode { private: @@ -312,6 +314,41 @@ class T_CondInstrNode : public A_InstructionNode { return *defaultCase_; } }; +// 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 ) , + 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 ) , + 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_; } +}; + // Pipeline declaration instruction class T_PipelineInstrNode : public A_InstructionNode {