## Parse

### Description

Populates the shader definition with information from the associated file. This is the second pass at parsing the associated file, since the ParseInfo callback first parses it to compile enough information to register the shader definition and populate the preset manager.

This callback is fired when a shader implemented with this parser's language is instantiated.

### Applies To

Custom Shaders

### Syntax

    public class <plugin-item_name>
    {
            public bool Parse( Context in_context )
            {
                    ...
            }
    }

    CStatus <plugin-item_name>_Parse( CRef& in_context )
    {
            ...
    }

    function <plugin-item_name>_Parse( in_context )
    {
            ...
    }

    def <plugin-item_name>_Parse( in_context ):
            ...

    Function <plugin-item_name>_Parse( in_context )
            ...
    End Function

    sub <plugin-item_name>_Parse
    {
            my $in_context = shift;
    }

<plugin-item-name> is the parser name specified in the call to PluginRegistrar.RegisterShaderLanguageParser with any spaces converted to underscores. For example, if you register a parser in a plug-in called "My Parser", the callback function names start with "My_Parser".

### Parameters

Parameter | Language | Type | Description
--- | --- | --- | ---
in_context | Scripting and C# | Context | Context.GetAttribute("Definition") returns the ShaderDef.
| C++ | CRef& | Context::GetAttribute("Definition") returns a reference to the ShaderDef.

### Context Attributes

Attribute | Get/Set | Description
--- | --- | ---
Filename | Sets a String or CString | The full path to the file to pre-parse. ??? What is pre-parsing???
Definition | Returns or sets a ShaderDef | The shader definition to populate/query.
Errors | Returns a String or CString | The parser can output parse errors.
Warnings | Returns a String or CString | The parser can output parse warnings.

### Example

    SICALLBACK UtShaderLanguageParser_Parse( CRef& in_ctxt  )
    {
            XSI::Application app;
            XSI::Factory fact = app.GetFactory();

            /*      For this example, we use a very simple format to define the shader.
                    First line represents the prog id.
                    Following lines have this format:
                            Type space Input space Texturable space PortName
                            color|float|boolean|integer|vector2|vector3|vector4 in|out on|off $PortName
                    Until a line with a single dot is found.
                    Then, 2 strings separated by a space give the MR function name and library.                     */
            XSI::Context ctxt(in_ctxt);
            XSI::CString strFilename = ctxt.GetAttribute( L"FileName" );
            XSI::ShaderDef shaderDef = ctxt.GetAttribute( L"Definition" );

            // We'll just check if our user attribute is there
            {
                    XSI::CValue valDune;
                    valDune = shaderDef.GetAttributes().GetAttribute( L"{F2EF07FE-1B57-4245-BF08-F5556212BFDF}" );
                    assert( !valDune.IsEmpty() );
            }

            std::ifstream in( strFilename.GetAsciiString() );
            if(!in)
            {
                    ctxt.PutAttribute( L"Errors", L"Cannot open file: " + strFilename + L"\n" );
                    return CStatus::Fail;
            }

            char buf[255];

            // Skip First Line
            in.getline( buf, 255 );

            XSI::ShaderParamDefOptions optTexturableInput = fact.CreateShaderParamDefOptions();
            optTexturableInput.SetTexturable(true);

            // Port Defs
            XSI::ShaderStructParamDef currentStructDef;
            while( in.getline( buf, 255 ).eof()==false )
            {
                    if( strlen( buf ) > 0 )
                    {
                            CSIString str(buf);
                            std::vector<CSIString> tokens;
                            str.Split( L" ", tokens );

                            // Strip the enum tokens
                            XSI::CValue valEnumValues;
                            {
                                    CSIString strEnumValues;
                                    std::vector<CSIString>::iterator itEraseStart = tokens.end();
                                    bool bStartedEnum=false;
                                    for( std::vector<CSIString>::iterator it=tokens.begin(); it!=tokens.end(); ++it )
                                    {
                                            // Skip the enum token
                                            if( *it == L"enum" )
                                            {

                                                    itEraseStart = it;
                                                    bStartedEnum = true;
                                            }
                                            // Gather the enum tokens and remove them from the token list
                                            else if( bStartedEnum )
                                            {

                                                    std::vector<CSIString> enumTokens;
                                                    it->Split( L"=", enumTokens );
                                                    if( enumTokens.size() == 2 )
                                                    {
                                                            //Replace '_' by ' '
                                                            for( ULONG i=0; i<enumTokens[0].Length(); ++i )
                                                            {
                                                                    if( ((LPCWSTR)enumTokens[0])[i] == L'_' )
                                                                    {
                                                                            enumTokens[0].SetAt( i, L' ' );
                                                                    }
                                                            }

                                                            strEnumValues += enumTokens[0];
                                                            strEnumValues += L",";
                                                            strEnumValues += enumTokens[1];
                                                            strEnumValues += L";";
                                                    }
                                            }
                                    }

                                    if( bStartedEnum )
                                    {
                                            if( itEraseStart!=tokens.end() )
                                                    tokens.erase( itEraseStart, tokens.end() );

                                            if( !strEnumValues.IsEmpty() )
                                            {
                                                    valEnumValues = (LPCWSTR)strEnumValues;
                                            }
                                    }
                            }

                            if( tokens.size()==1  )
                            {
                                    if( str==L"." )
                                            break;
                                    else if( str==L"endstruct")
                                            currentStructDef=CRef();
                            }
                            else if( tokens.size()==4 )
                            {
                                    XSI::CString strParamName = (LPCWSTR)tokens[3];

                                    CSIString strType = tokens[0];

                                    bool bIsInput= tokens[1]==L"in";
                                    bool bTexturable= tokens[2]==L"on";
                                    bool bIsArray =false;

                                    if( strType.Right(2) == L"[]" )
                                    {
                                            bIsArray = true;
                                            strType.TruncateRight(2);
                                    }

                                    XSI::siShaderParameterType eType = siScalarParameterType;
                                    if( strType == L"color"  )
                                            eType = siColorParameterType;
                                    if( strType == L"float" )
                                            eType = siScalarParameterType;
                                    else if( strType == L"vector2" )
                                            eType = siVector2ParameterType;
                                    else if( strType == L"vector3" )
                                            eType = siVectorParameterType;
                                    else if( strType == L"vector4" )
                                            eType = siVector4ParameterType;
                                    else if( strType == L"boolean" )
                                            eType = siBooleanParameterType;
                                    else if( strType == L"integer" )
                                            eType = siIntegerParameterType;
                                    else if( strType == L"reference" )
                                            eType = siReferenceParameterType;
                                    else if ( strType == L"matrix4")
                                            eType = siMatrixParameterType;
                                    else if ( strType == L"matrix3")
                                            eType = siMatrix3ParameterType;
                                    else if ( strType == L"string")
                                            eType = siStringParameterType;
                                    else if ( strType == L"quaternion")
                                            eType = siQuaternionParameterType;
                                    else if ( strType == L"fcurve")
                                            eType = siProfileCurveParameterType;
                                    else if ( strType == L"gradient")
                                            eType = siGradientParameterType;
                                    else if ( strType == L"texture")
                                            eType = siTextureParameterType;
                                    else if ( strType == L"tspace")
                                            eType = siTextureSpaceParameterType;
                                    else if ( strType == L"struct" && !currentStructDef.IsValid() )
                                            eType = siStructParameterType;

                                    // Now add the port.
                                    XSI::ShaderParamDef paramDef;

                                    bTexturable &= bIsInput;

                                    XSI::ShaderParamDefContainer pdefContainer;
                                    if( currentStructDef.IsValid() )
                                            pdefContainer = currentStructDef.GetSubParamDefs();
                                    else if( bIsInput )
                                            pdefContainer = shaderDef.GetInputParamDefs();
                                    else
                                            pdefContainer = shaderDef.GetOutputParamDefs();

                                    if( !bIsArray )
                                    {
                                            paramDef = pdefContainer.AddParamDef( strParamName, eType, bTexturable ? optTexturableInput :CRef() );

                                            if( eType == siStructParameterType )
                                            {
                                                    currentStructDef = paramDef;
                                            }
                                    }
                                    else
                                    {
                                            paramDef = pdefContainer.AddArrayParamDef( strParamName, eType, bTexturable ? optTexturableInput :CRef() );

                                            XSI::ShaderArrayParamDef arrayDef = paramDef;

                                            XSI::ShaderParamDef itemDef = arrayDef.GetArrayItemDef();

                                            if( eType == siStructParameterType )
                                            {
                                                    currentStructDef = itemDef;
                                            }
                                    }

                                    // Set the enum values
                                    if( !valEnumValues.IsEmpty() )
                                            paramDef.GetAttributes().SetAttribute( L"PPGPortEnumValues", valEnumValues );

                                    // Set tspace filter
                                    if( strType==L"tspace" )
                                    {
                                            paramDef.GetAttributes().SetAttribute( siPropertyFilterAttribute, (LONG)siUVPropertyFilter );
                                    }
                            }
                    }
            }

            if( in.getline( buf, 255 ).eof()==true )
            {
                    CSIString str(buf);
                    std::vector<CSIString> tokens;
                    str.Split( L" ", tokens );

                    // Fill MR MetaShaderDef
                    if( tokens.size()==2 || tokens.size()==3 )
                    {
                            // Texture type can connect to anything.
                            shaderDef.AddType( L"texture" );

                            XSI::MetaShaderRendererDef rendererDef = shaderDef.AddRendererDef( L"Mental Ray");
                            rendererDef.PutSymbolName( (LPCWSTR)tokens[0] );
                            rendererDef.PutCodePath( (LPCWSTR)tokens[1] );

                            CValue valVersion;

                            if( tokens.size()==2 )
                            {
                                    valVersion=(LONG)1;
                            }
                            else
                            {
                                    valVersion = (LPCWSTR)tokens[2];
                                    valVersion.ChangeType( XSI::CValue::siInt8 );
                            }

                            XSI::AttributeMap rendererOptions = rendererDef.GetRendererOptions();
                            rendererOptions.SetAttribute( L"version", valVersion );

                            // Hardcoded options by shader types.
                            if( tokens[0] == L"sib_uvwgen" )
                            {
                                    rendererOptions.SetAttribute( L"derivative1", L"on" );
                                    rendererOptions.SetAttribute( L"derivative2", L"on" );
                            }
                    }
                    else
                    {
                            ctxt.PutAttribute( L"Errors", L"Cannot find the DLL Code Section.\n" );
                            in.close();
                            return CStatus::Fail;
                    }
            }
            else
            {
                    ctxt.PutAttribute( L"Errors", L"Cannot find the DLL Code Section.\n" );
                    in.close();
                    return CStatus::Fail;
            }

            in.close();
            return CStatus::OK;
    }

### See Also

- PluginRegistrar.RegisterShaderLanguageParser
- ParseInfo
- QueryParserSettings
- Shader Parser Callbacks