## 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