void TAstNodeForSentence::ParseSemantic() const
{
	auto type1 = TAstNodeOperator::GetSymbolType(m_firstChild->GetFirstChild()->GetSibling());
	auto type2 = TAstNodeOperator::GetSymbolType(m_firstChild->GetSibling());
	auto type3 = TAstNodeOperator::GetSymbolType(m_firstChild->GetSibling()->GetSibling());

	if ((type1 != SYMBOL_TYPE::TYPE_INTERGER && type1 != SYMBOL_TYPE::TYPE_DOUBLE)
		|| (type2 != SYMBOL_TYPE::TYPE_INTERGER && type2 != SYMBOL_TYPE::TYPE_DOUBLE)
		|| (type3 != SYMBOL_TYPE::TYPE_INTERGER && type3 != SYMBOL_TYPE::TYPE_DOUBLE))
	{
		throw TInterpreterException(TInterpreterException::FOR_SENTENCE_SHOULD_USE_INTERGER_OR_DOUBLE, m_firstChild->GetToken()->LineNumber());
	}

	auto child = m_firstChild->GetSibling()->GetSibling()->GetSibling();
	while (child)
	{
		child->ParseSemantic();
		child = child->GetSibling();
	}
}
/*!***************************************************************************
 @Function			ParseEffect
 @Output			effect			effect data object
 @Input				nStartLine		start line number
 @Input				nEndLine		end line number
 @Output			pReturnError	error string
 @Return			bool			true if parse is successful
 @Description		Parses the EFFECT section of the PFX file.
*****************************************************************************/
bool CPVRTPFXParser::ParseEffect(SPVRTPFXParserEffect &effect, const int nStartLine, const int nEndLine, CPVRTString * const pReturnError)
{
	bool bName = false;
	bool bVertShader = false;
	bool bFragShader = false;

	effect.pszName					= NULL;
	effect.pszAnnotation			= NULL;
	effect.pszVertexShaderName		= NULL;
	effect.pszFragmentShaderName	= NULL;

	effect.nMaxTextures				= 100;
	effect.nNumTextures				= 0;
	effect.psTextures				= new SPVRTPFXParserEffectTexture[effect.nMaxTextures];

	effect.nMaxUniforms				= 100;
	effect.nNumUniforms				= 0;
	effect.psUniform				= new SPVRTPFXParserSemantic[effect.nMaxUniforms];

	effect.nMaxAttributes			= 100;
	effect.nNumAttributes			= 0;
	effect.psAttribute				= new SPVRTPFXParserSemantic[effect.nMaxAttributes];

	for(int i = nStartLine+1; i < nEndLine; i++)
	{
		// Skip blank lines
		if(!*m_psContext->ppszEffectFile[i])
			continue;

		char *str = strtok (m_psContext->ppszEffectFile[i]," ");
		if(str != NULL)
		{
			if(strcmp(str, "[ANNOTATION]") == 0)
			{
				if(effect.pszAnnotation)
				{
					sprintf(errorMsg, "ANNOTATION redefined in [EFFECT] on line %d: \n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}

				i++;		// Skip the block-start
				if(!ConcatenateLinesUntil(
					effect.pszAnnotation,
					i,
					m_psContext->ppszEffectFile,
					m_psContext->nNumLines,
					"[/ANNOTATION]"))
				{
					return false;
				}
			}
			else if(strcmp(str, "VERTEXSHADER") == 0)
			{
				if(bVertShader)
				{
					sprintf(errorMsg, "VERTEXSHADER redefined in [EFFECT] on line %d: \n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}

				str = strtok(NULL, " ");
				if(str == NULL)
				{
					sprintf(errorMsg, "VERTEXSHADER missing value in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}
				effect.pszVertexShaderName = (char*)malloc((strlen(str)+1) * sizeof(char));
				strcpy(effect.pszVertexShaderName, str);

				bVertShader = true;
			}
			else if(strcmp(str, "FRAGMENTSHADER") == 0)
			{
				if(bFragShader)
				{
					sprintf(errorMsg, "FRAGMENTSHADER redefined in [EFFECT] on line %d: \n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}

				str = strtok(NULL, " ");
				if(str == NULL)
				{
					sprintf(errorMsg, "FRAGMENTSHADER missing value in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}
				effect.pszFragmentShaderName = (char*)malloc((strlen(str)+1) * sizeof(char));
				strcpy(effect.pszFragmentShaderName, str);

				bFragShader = true;
			}
			else if(strcmp(str, "TEXTURE") == 0)
			{
				if(effect.nNumTextures < effect.nMaxTextures)
				{
					// texture number
					str = strtok(NULL, " ");
					if(str != NULL)
						effect.psTextures[effect.nNumTextures].nNumber = atoi(str);
					else
					{
						sprintf(errorMsg, "TEXTURE missing value in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
						*pReturnError = errorMsg;
						return false;
					}

					// texture name
					str = strtok(NULL, " ");
					if(str != NULL)
					{
						effect.psTextures[effect.nNumTextures].pszName = (char*)malloc(strlen(str) + 1);
						strcpy(effect.psTextures[effect.nNumTextures].pszName, str);
					}
					else
					{
						sprintf(errorMsg, "TEXTURE missing value in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
						*pReturnError = errorMsg;
						return false;
					}

					++effect.nNumTextures;
				}
				else
				{
					sprintf(errorMsg, "Too many textures in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}
			}
			else if(strcmp(str, "UNIFORM") == 0)
			{
				if(effect.nNumUniforms < effect.nMaxUniforms)
				{
					if(!ParseSemantic(effect.psUniform[effect.nNumUniforms], i, nEndLine, pReturnError))
						return false;
					effect.nNumUniforms++;
				}
				else
				{
					sprintf(errorMsg, "Too many uniforms in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}
			}
			else if(strcmp(str, "ATTRIBUTE") == 0)
			{
				if(effect.nNumAttributes < effect.nMaxAttributes)
				{
					if(!ParseSemantic(effect.psAttribute[effect.nNumAttributes], i, nEndLine, pReturnError))
						return false;
					effect.nNumAttributes++;
				}
				else
				{
					sprintf(errorMsg, "Too many attributes in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[i]);
					*pReturnError = errorMsg;
					return false;
				}
			}
			else if(strcmp(str, "NAME") == 0)
			{
				if(bName)
				{
					sprintf(errorMsg, "NAME redefined in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[nStartLine]);
					*pReturnError = errorMsg;
					return false;
				}

				str = strtok (NULL, " ");
				if(str == NULL)
				{
					sprintf(errorMsg, "NAME missing value in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[nStartLine]);
					*pReturnError = errorMsg;
					return false;
				}

				effect.pszName = (char *)malloc((strlen(str)+1) * sizeof(char));
				strcpy(effect.pszName, str);
				bName = true;
			}
			else
			{
				sprintf(errorMsg, "Unknown keyword '%s' in [EFFECT] on line %d\n", str, m_psContext->pnFileLineNumber[i]);
				*pReturnError = errorMsg;
				return false;
			}
		}
		else
		{
			sprintf(errorMsg, "Missing arguments in [EFFECT] on line %d: %s\n", m_psContext->pnFileLineNumber[i], m_psContext->ppszEffectFile[i]);
			*pReturnError = errorMsg;
			return false;
		}

	}

	if(!bName)
	{
		sprintf(errorMsg, "No 'NAME' found in [EFFECT] on line %d\n", m_psContext->pnFileLineNumber[nStartLine]);
		*pReturnError = errorMsg;
		return false;
	}
	if(!bVertShader)
	{
		sprintf(errorMsg, "No 'VERTEXSHADER' defined in [EFFECT] starting on line %d: \n", m_psContext->pnFileLineNumber[nStartLine-1]);
		*pReturnError = errorMsg;
		return false;
	}
	if(!bFragShader)
	{
		sprintf(errorMsg, "No 'FRAGMENTSHADER' defined in [EFFECT] starting on line %d: \n", m_psContext->pnFileLineNumber[nStartLine-1]);
		*pReturnError = errorMsg;
		return false;
	}

	return true;
}