Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) Module
      3  * -----------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Compiler test case.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsShaderLibrary.hpp"
     25 #include "glsShaderLibraryCase.hpp"
     26 #include "gluShaderUtil.hpp"
     27 #include "tcuResource.hpp"
     28 #include "glwEnums.hpp"
     29 
     30 #include "deInt32.h"
     31 
     32 #include <string>
     33 #include <vector>
     34 #include <fstream>
     35 #include <sstream>
     36 
     37 #include <string.h>
     38 #include <stdarg.h>
     39 #include <stdlib.h>
     40 
     41 using std::string;
     42 using std::vector;
     43 using std::ostringstream;
     44 
     45 using namespace glu;
     46 
     47 #if 0
     48 #	define PARSE_DBG(X) printf X
     49 #else
     50 #	define PARSE_DBG(X) DE_NULL_STATEMENT
     51 #endif
     52 
     53 namespace deqp
     54 {
     55 namespace gls
     56 {
     57 namespace sl
     58 {
     59 
     60 static const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
     61 
     62 DE_INLINE deBool isWhitespace (char c)
     63 {
     64 	return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
     65 }
     66 
     67 DE_INLINE deBool isEOL (char c)
     68 {
     69 	return (c == '\r') || (c == '\n');
     70 }
     71 
     72 DE_INLINE deBool isNumeric (char c)
     73 {
     74 	return deInRange32(c, '0', '9');
     75 }
     76 
     77 DE_INLINE deBool isAlpha (char c)
     78 {
     79 	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
     80 }
     81 
     82 DE_INLINE deBool isCaseNameChar (char c)
     83 {
     84 	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') || (c == '-') || (c == '.');
     85 }
     86 
     87 // \todo [2011-02-11 pyry] Should not depend on Context or TestContext!
     88 class ShaderParser
     89 {
     90 public:
     91 							ShaderParser			(tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* currentDir = DE_NULL);
     92 							~ShaderParser			(void);
     93 
     94 	vector<tcu::TestNode*>	parse					(const char* input);
     95 
     96 private:
     97 	enum Token
     98 	{
     99 		TOKEN_INVALID = 0,
    100 		TOKEN_EOF,
    101 		TOKEN_STRING,
    102 		TOKEN_SHADER_SOURCE,
    103 
    104 		TOKEN_INT_LITERAL,
    105 		TOKEN_FLOAT_LITERAL,
    106 
    107 		// identifiers
    108 		TOKEN_IDENTIFIER,
    109 		TOKEN_TRUE,
    110 		TOKEN_FALSE,
    111 		TOKEN_DESC,
    112 		TOKEN_EXPECT,
    113 		TOKEN_GROUP,
    114 		TOKEN_CASE,
    115 		TOKEN_END,
    116 		TOKEN_VALUES,
    117 		TOKEN_BOTH,
    118 		TOKEN_VERTEX,
    119 		TOKEN_FRAGMENT,
    120 		TOKEN_UNIFORM,
    121 		TOKEN_INPUT,
    122 		TOKEN_OUTPUT,
    123 		TOKEN_FLOAT,
    124 		TOKEN_FLOAT_VEC2,
    125 		TOKEN_FLOAT_VEC3,
    126 		TOKEN_FLOAT_VEC4,
    127 		TOKEN_FLOAT_MAT2,
    128 		TOKEN_FLOAT_MAT2X3,
    129 		TOKEN_FLOAT_MAT2X4,
    130 		TOKEN_FLOAT_MAT3X2,
    131 		TOKEN_FLOAT_MAT3,
    132 		TOKEN_FLOAT_MAT3X4,
    133 		TOKEN_FLOAT_MAT4X2,
    134 		TOKEN_FLOAT_MAT4X3,
    135 		TOKEN_FLOAT_MAT4,
    136 		TOKEN_INT,
    137 		TOKEN_INT_VEC2,
    138 		TOKEN_INT_VEC3,
    139 		TOKEN_INT_VEC4,
    140 		TOKEN_UINT,
    141 		TOKEN_UINT_VEC2,
    142 		TOKEN_UINT_VEC3,
    143 		TOKEN_UINT_VEC4,
    144 		TOKEN_BOOL,
    145 		TOKEN_BOOL_VEC2,
    146 		TOKEN_BOOL_VEC3,
    147 		TOKEN_BOOL_VEC4,
    148 		TOKEN_VERSION,
    149 		TOKEN_TESSELLATION_CONTROL,
    150 		TOKEN_TESSELLATION_EVALUATION,
    151 		TOKEN_GEOMETRY,
    152 		TOKEN_REQUIRE,
    153 		TOKEN_IN,
    154 		TOKEN_IMPORT,
    155 		TOKEN_PIPELINE_PROGRAM,
    156 		TOKEN_ACTIVE_STAGES,
    157 
    158 		// symbols
    159 		TOKEN_ASSIGN,
    160 		TOKEN_PLUS,
    161 		TOKEN_MINUS,
    162 		TOKEN_COMMA,
    163 		TOKEN_VERTICAL_BAR,
    164 		TOKEN_SEMI_COLON,
    165 		TOKEN_LEFT_PAREN,
    166 		TOKEN_RIGHT_PAREN,
    167 		TOKEN_LEFT_BRACKET,
    168 		TOKEN_RIGHT_BRACKET,
    169 		TOKEN_LEFT_BRACE,
    170 		TOKEN_RIGHT_BRACE,
    171 		TOKEN_GREATER,
    172 
    173 		TOKEN_LAST
    174 	};
    175 
    176 	void						parseError					(const std::string& errorStr);
    177 	float						parseFloatLiteral			(const char* str);
    178 	int							parseIntLiteral				(const char* str);
    179 	string						parseStringLiteral			(const char* str);
    180 	string						parseShaderSource			(const char* str);
    181 	void						advanceToken				(void);
    182 	void						advanceToken				(Token assumed);
    183 	void						assumeToken					(Token token);
    184 	DataType					mapDataTypeToken			(Token token);
    185 	const char*					getTokenName				(Token token);
    186 	deUint32					getShaderStageLiteralFlag	(void);
    187 	deUint32					getGLEnumFromName			(const std::string& enumName);
    188 
    189 	void						parseValueElement			(DataType dataType, ShaderCase::Value& result);
    190 	void						parseValue					(ShaderCase::ValueBlock& valueBlock);
    191 	void						parseValueBlock				(ShaderCase::ValueBlock& valueBlock);
    192 	deUint32					parseShaderStageList		(void);
    193 	void						parseRequirement			(ShaderCase::CaseRequirement& valueBlock);
    194 	void						parseExpectResult			(ShaderCase::ExpectResult& expectResult);
    195 	void						parseGLSLVersion			(glu::GLSLVersion& version);
    196 	void						parsePipelineProgram		(ShaderCase::PipelineProgram& program);
    197 	void						parseShaderCase				(vector<tcu::TestNode*>& shaderNodeList);
    198 	void						parseShaderGroup			(vector<tcu::TestNode*>& shaderNodeList);
    199 	void						parseImport					(vector<tcu::TestNode*>& shaderNodeList);
    200 
    201 	// Member variables.
    202 	tcu::TestContext&			m_testCtx;
    203 	RenderContext&				m_renderCtx;
    204 	const glu::ContextInfo&		m_contextInfo;
    205 	std::string					m_input;
    206 	const char*					m_curPtr;
    207 	Token						m_curToken;
    208 	std::string					m_curTokenStr;
    209 	const char* const			m_currentDir;
    210 };
    211 
    212 ShaderParser::ShaderParser (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* currentDir)
    213 	: m_testCtx			(testCtx)
    214 	, m_renderCtx		(renderCtx)
    215 	, m_contextInfo		(contextInfo)
    216 	, m_curPtr			(DE_NULL)
    217 	, m_curToken		(TOKEN_LAST)
    218 	, m_currentDir		(currentDir)
    219 {
    220 }
    221 
    222 ShaderParser::~ShaderParser (void)
    223 {
    224 	// nada
    225 }
    226 
    227 void ShaderParser::parseError (const std::string& errorStr)
    228 {
    229 	string atStr = string(m_curPtr, 80);
    230 	throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), "", __FILE__, __LINE__);
    231 }
    232 
    233 float ShaderParser::parseFloatLiteral (const char* str)
    234 {
    235 	return (float)atof(str);
    236 }
    237 
    238 int ShaderParser::parseIntLiteral (const char* str)
    239 {
    240 	return atoi(str);
    241 }
    242 
    243 string ShaderParser::parseStringLiteral (const char* str)
    244 {
    245 	const char*		p		= str;
    246 	char			endChar = *p++;
    247 	ostringstream	o;
    248 
    249 	while (*p != endChar && *p)
    250 	{
    251 		if (*p == '\\')
    252 		{
    253 			switch (p[1])
    254 			{
    255 				case 0:		DE_ASSERT(DE_FALSE);	break;
    256 				case 'n':	o << '\n';				break;
    257 				case 't':	o << '\t';				break;
    258 				default:	o << p[1];				break;
    259 			}
    260 
    261 			p += 2;
    262 		}
    263 		else
    264 			o << *p++;
    265 	}
    266 
    267 	return o.str();
    268 }
    269 
    270 static string removeExtraIndentation (const string& source)
    271 {
    272 	// Detect indentation from first line.
    273 	int numIndentChars = 0;
    274 	for (int ndx = 0; ndx < (int)source.length() && isWhitespace(source[ndx]); ndx++)
    275 		numIndentChars += source[ndx] == '\t' ? 4 : 1;
    276 
    277 	// Process all lines and remove preceding indentation.
    278 	ostringstream processed;
    279 	{
    280 		bool	atLineStart			= true;
    281 		int		indentCharsOmitted	= 0;
    282 
    283 		for (int pos = 0; pos < (int)source.length(); pos++)
    284 		{
    285 			char c = source[pos];
    286 
    287 			if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
    288 			{
    289 				indentCharsOmitted += c == '\t' ? 4 : 1;
    290 			}
    291 			else if (isEOL(c))
    292 			{
    293 				if (source[pos] == '\r' && source[pos+1] == '\n')
    294 				{
    295 					pos += 1;
    296 					processed << '\n';
    297 				}
    298 				else
    299 					processed << c;
    300 
    301 				atLineStart			= true;
    302 				indentCharsOmitted	= 0;
    303 			}
    304 			else
    305 			{
    306 				processed << c;
    307 				atLineStart = false;
    308 			}
    309 		}
    310 	}
    311 
    312 	return processed.str();
    313 }
    314 
    315 string ShaderParser::parseShaderSource (const char* str)
    316 {
    317 	const char*		p = str+2;
    318 	ostringstream	o;
    319 
    320 	// Eat first empty line from beginning.
    321 	while (*p == ' ') p++;
    322 	if (*p == '\n') p++;
    323 
    324 	while ((p[0] != '"') || (p[1] != '"'))
    325 	{
    326 		if (*p == '\\')
    327 		{
    328 			switch (p[1])
    329 			{
    330 				case 0:		DE_ASSERT(DE_FALSE);	break;
    331 				case 'n':	o << '\n';				break;
    332 				case 't':	o << '\t';				break;
    333 				default:	o << p[1];				break;
    334 			}
    335 
    336 			p += 2;
    337 		}
    338 		else
    339 			o << *p++;
    340 	}
    341 
    342 	return removeExtraIndentation(o.str());
    343 }
    344 
    345 void ShaderParser::advanceToken (void)
    346 {
    347 	// Skip old token.
    348 	m_curPtr += m_curTokenStr.length();
    349 
    350 	// Reset token (for safety).
    351 	m_curToken		= TOKEN_INVALID;
    352 	m_curTokenStr	= "";
    353 
    354 	// Eat whitespace & comments while they last.
    355 	for (;;)
    356 	{
    357 		while (isWhitespace(*m_curPtr))
    358 			m_curPtr++;
    359 
    360 		// Check for EOL comment.
    361 		if (*m_curPtr == '#')
    362 		{
    363 			while (*m_curPtr && !isEOL(*m_curPtr))
    364 				m_curPtr++;
    365 		}
    366 		else
    367 			break;
    368 	}
    369 
    370 	if (!*m_curPtr)
    371 	{
    372 		m_curToken = TOKEN_EOF;
    373 		m_curTokenStr = "<EOF>";
    374 	}
    375 	else if (isAlpha(*m_curPtr))
    376 	{
    377 		struct Named
    378 		{
    379 			const char*		str;
    380 			Token			token;
    381 		};
    382 
    383 		static const Named s_named[] =
    384 		{
    385 			{ "true",						TOKEN_TRUE						},
    386 			{ "false",						TOKEN_FALSE						},
    387 			{ "desc",						TOKEN_DESC						},
    388 			{ "expect",						TOKEN_EXPECT					},
    389 			{ "group",						TOKEN_GROUP						},
    390 			{ "case",						TOKEN_CASE						},
    391 			{ "end",						TOKEN_END						},
    392 			{ "values",						TOKEN_VALUES					},
    393 			{ "both",						TOKEN_BOTH						},
    394 			{ "vertex",						TOKEN_VERTEX					},
    395 			{ "fragment",					TOKEN_FRAGMENT					},
    396 			{ "uniform",					TOKEN_UNIFORM					},
    397 			{ "input",						TOKEN_INPUT						},
    398 			{ "output",						TOKEN_OUTPUT					},
    399 			{ "float",						TOKEN_FLOAT						},
    400 			{ "vec2",						TOKEN_FLOAT_VEC2				},
    401 			{ "vec3",						TOKEN_FLOAT_VEC3				},
    402 			{ "vec4",						TOKEN_FLOAT_VEC4				},
    403 			{ "mat2",						TOKEN_FLOAT_MAT2				},
    404 			{ "mat2x3",						TOKEN_FLOAT_MAT2X3				},
    405 			{ "mat2x4",						TOKEN_FLOAT_MAT2X4				},
    406 			{ "mat3x2",						TOKEN_FLOAT_MAT3X2				},
    407 			{ "mat3",						TOKEN_FLOAT_MAT3				},
    408 			{ "mat3x4",						TOKEN_FLOAT_MAT3X4				},
    409 			{ "mat4x2",						TOKEN_FLOAT_MAT4X2				},
    410 			{ "mat4x3",						TOKEN_FLOAT_MAT4X3				},
    411 			{ "mat4",						TOKEN_FLOAT_MAT4				},
    412 			{ "int",						TOKEN_INT						},
    413 			{ "ivec2",						TOKEN_INT_VEC2					},
    414 			{ "ivec3",						TOKEN_INT_VEC3					},
    415 			{ "ivec4",						TOKEN_INT_VEC4					},
    416 			{ "uint",						TOKEN_UINT						},
    417 			{ "uvec2",						TOKEN_UINT_VEC2					},
    418 			{ "uvec3",						TOKEN_UINT_VEC3					},
    419 			{ "uvec4",						TOKEN_UINT_VEC4					},
    420 			{ "bool",						TOKEN_BOOL						},
    421 			{ "bvec2",						TOKEN_BOOL_VEC2					},
    422 			{ "bvec3",						TOKEN_BOOL_VEC3					},
    423 			{ "bvec4",						TOKEN_BOOL_VEC4					},
    424 			{ "version",					TOKEN_VERSION					},
    425 			{ "tessellation_control",		TOKEN_TESSELLATION_CONTROL		},
    426 			{ "tessellation_evaluation",	TOKEN_TESSELLATION_EVALUATION	},
    427 			{ "geometry",					TOKEN_GEOMETRY					},
    428 			{ "require",					TOKEN_REQUIRE					},
    429 			{ "in",							TOKEN_IN						},
    430 			{ "import",						TOKEN_IMPORT					},
    431 			{ "pipeline_program",			TOKEN_PIPELINE_PROGRAM			},
    432 			{ "active_stages",				TOKEN_ACTIVE_STAGES				},
    433 		};
    434 
    435 		const char* end = m_curPtr + 1;
    436 		while (isCaseNameChar(*end))
    437 			end++;
    438 		m_curTokenStr = string(m_curPtr, end - m_curPtr);
    439 
    440 		m_curToken = TOKEN_IDENTIFIER;
    441 
    442 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
    443 		{
    444 			if (m_curTokenStr == s_named[ndx].str)
    445 			{
    446 				m_curToken = s_named[ndx].token;
    447 				break;
    448 			}
    449 		}
    450 	}
    451 	else if (isNumeric(*m_curPtr))
    452 	{
    453 		/* \todo [2010-03-31 petri] Hex? */
    454 		const char* p = m_curPtr;
    455 		while (isNumeric(*p))
    456 			p++;
    457 		if (*p == '.')
    458 		{
    459 			p++;
    460 			while (isNumeric(*p))
    461 				p++;
    462 
    463 			if (*p == 'e' || *p == 'E')
    464 			{
    465 				p++;
    466 				if (*p == '+' || *p == '-')
    467 					p++;
    468 				DE_ASSERT(isNumeric(*p));
    469 				while (isNumeric(*p))
    470 					p++;
    471 			}
    472 
    473 			m_curToken = TOKEN_FLOAT_LITERAL;
    474 			m_curTokenStr = string(m_curPtr, p - m_curPtr);
    475 		}
    476 		else
    477 		{
    478 			m_curToken = TOKEN_INT_LITERAL;
    479 			m_curTokenStr = string(m_curPtr, p - m_curPtr);
    480 		}
    481 	}
    482 	else if (*m_curPtr == '"' && m_curPtr[1] == '"')
    483 	{
    484 		const char*	p = m_curPtr + 2;
    485 
    486 		while ((p[0] != '"') || (p[1] != '"'))
    487 		{
    488 			DE_ASSERT(*p);
    489 			if (*p == '\\')
    490 			{
    491 				DE_ASSERT(p[1] != 0);
    492 				p += 2;
    493 			}
    494 			else
    495 				p++;
    496 		}
    497 		p += 2;
    498 
    499 		m_curToken		= TOKEN_SHADER_SOURCE;
    500 		m_curTokenStr	= string(m_curPtr, (int)(p - m_curPtr));
    501 	}
    502 	else if (*m_curPtr == '"' || *m_curPtr == '\'')
    503 	{
    504 		char		endChar = *m_curPtr;
    505 		const char*	p		= m_curPtr + 1;
    506 
    507 		while (*p != endChar)
    508 		{
    509 			DE_ASSERT(*p);
    510 			if (*p == '\\')
    511 			{
    512 				DE_ASSERT(p[1] != 0);
    513 				p += 2;
    514 			}
    515 			else
    516 				p++;
    517 		}
    518 		p++;
    519 
    520 		m_curToken		= TOKEN_STRING;
    521 		m_curTokenStr	= string(m_curPtr, (int)(p - m_curPtr));
    522 	}
    523 	else
    524 	{
    525 		struct SimpleToken
    526 		{
    527 			const char*		str;
    528 			Token			token;
    529 		};
    530 
    531 		static const SimpleToken s_simple[] =
    532 		{
    533 			{ "=",			TOKEN_ASSIGN		},
    534 			{ "+",			TOKEN_PLUS			},
    535 			{ "-",			TOKEN_MINUS			},
    536 			{ ",",			TOKEN_COMMA			},
    537 			{ "|",			TOKEN_VERTICAL_BAR	},
    538 			{ ";",			TOKEN_SEMI_COLON	},
    539 			{ "(",			TOKEN_LEFT_PAREN	},
    540 			{ ")",			TOKEN_RIGHT_PAREN	},
    541 			{ "[",			TOKEN_LEFT_BRACKET	},
    542 			{ "]",			TOKEN_RIGHT_BRACKET },
    543 			{ "{",			TOKEN_LEFT_BRACE	},
    544 			{ "}",			TOKEN_RIGHT_BRACE	},
    545 			{ ">",			TOKEN_GREATER		},
    546 		};
    547 
    548 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
    549 		{
    550 			if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
    551 			{
    552 				m_curToken		= s_simple[ndx].token;
    553 				m_curTokenStr	= s_simple[ndx].str;
    554 				return;
    555 			}
    556 		}
    557 
    558 		// Otherwise invalid token.
    559 		m_curToken = TOKEN_INVALID;
    560 		m_curTokenStr = *m_curPtr;
    561 	}
    562 }
    563 
    564 void ShaderParser::advanceToken (Token assumed)
    565 {
    566 	assumeToken(assumed);
    567 	advanceToken();
    568 }
    569 
    570 void ShaderParser::assumeToken (Token token)
    571 {
    572 	if (m_curToken != token)
    573 		parseError((string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
    574 	DE_TEST_ASSERT(m_curToken == token);
    575 }
    576 
    577 DataType ShaderParser::mapDataTypeToken (Token token)
    578 {
    579 	switch (token)
    580 	{
    581 		case TOKEN_FLOAT:			return TYPE_FLOAT;
    582 		case TOKEN_FLOAT_VEC2:		return TYPE_FLOAT_VEC2;
    583 		case TOKEN_FLOAT_VEC3:		return TYPE_FLOAT_VEC3;
    584 		case TOKEN_FLOAT_VEC4:		return TYPE_FLOAT_VEC4;
    585 		case TOKEN_FLOAT_MAT2:		return TYPE_FLOAT_MAT2;
    586 		case TOKEN_FLOAT_MAT2X3:	return TYPE_FLOAT_MAT2X3;
    587 		case TOKEN_FLOAT_MAT2X4:	return TYPE_FLOAT_MAT2X4;
    588 		case TOKEN_FLOAT_MAT3X2:	return TYPE_FLOAT_MAT3X2;
    589 		case TOKEN_FLOAT_MAT3:		return TYPE_FLOAT_MAT3;
    590 		case TOKEN_FLOAT_MAT3X4:	return TYPE_FLOAT_MAT3X4;
    591 		case TOKEN_FLOAT_MAT4X2:	return TYPE_FLOAT_MAT4X2;
    592 		case TOKEN_FLOAT_MAT4X3:	return TYPE_FLOAT_MAT4X3;
    593 		case TOKEN_FLOAT_MAT4:		return TYPE_FLOAT_MAT4;
    594 		case TOKEN_INT:				return TYPE_INT;
    595 		case TOKEN_INT_VEC2:		return TYPE_INT_VEC2;
    596 		case TOKEN_INT_VEC3:		return TYPE_INT_VEC3;
    597 		case TOKEN_INT_VEC4:		return TYPE_INT_VEC4;
    598 		case TOKEN_UINT:			return TYPE_UINT;
    599 		case TOKEN_UINT_VEC2:		return TYPE_UINT_VEC2;
    600 		case TOKEN_UINT_VEC3:		return TYPE_UINT_VEC3;
    601 		case TOKEN_UINT_VEC4:		return TYPE_UINT_VEC4;
    602 		case TOKEN_BOOL:			return TYPE_BOOL;
    603 		case TOKEN_BOOL_VEC2:		return TYPE_BOOL_VEC2;
    604 		case TOKEN_BOOL_VEC3:		return TYPE_BOOL_VEC3;
    605 		case TOKEN_BOOL_VEC4:		return TYPE_BOOL_VEC4;
    606 		default:					return TYPE_INVALID;
    607 	}
    608 }
    609 
    610 const char* ShaderParser::getTokenName (Token token)
    611 {
    612 	switch (token)
    613 	{
    614 		case TOKEN_INVALID:					return "<invalid>";
    615 		case TOKEN_EOF:						return "<eof>";
    616 		case TOKEN_STRING:					return "<string>";
    617 		case TOKEN_SHADER_SOURCE:			return "source";
    618 
    619 		case TOKEN_INT_LITERAL:				return "<int>";
    620 		case TOKEN_FLOAT_LITERAL:			return "<float>";
    621 
    622 		// identifiers
    623 		case TOKEN_IDENTIFIER:				return "<identifier>";
    624 		case TOKEN_TRUE:					return "true";
    625 		case TOKEN_FALSE:					return "false";
    626 		case TOKEN_DESC:					return "desc";
    627 		case TOKEN_EXPECT:					return "expect";
    628 		case TOKEN_GROUP:					return "group";
    629 		case TOKEN_CASE:					return "case";
    630 		case TOKEN_END:						return "end";
    631 		case TOKEN_VALUES:					return "values";
    632 		case TOKEN_BOTH:					return "both";
    633 		case TOKEN_VERTEX:					return "vertex";
    634 		case TOKEN_FRAGMENT:				return "fragment";
    635 		case TOKEN_TESSELLATION_CONTROL:	return "tessellation_control";
    636 		case TOKEN_TESSELLATION_EVALUATION:	return "tessellation_evaluation";
    637 		case TOKEN_GEOMETRY:				return "geometry";
    638 		case TOKEN_REQUIRE:					return "require";
    639 		case TOKEN_UNIFORM:					return "uniform";
    640 		case TOKEN_INPUT:					return "input";
    641 		case TOKEN_OUTPUT:					return "output";
    642 		case TOKEN_FLOAT:					return "float";
    643 		case TOKEN_FLOAT_VEC2:				return "vec2";
    644 		case TOKEN_FLOAT_VEC3:				return "vec3";
    645 		case TOKEN_FLOAT_VEC4:				return "vec4";
    646 		case TOKEN_FLOAT_MAT2:				return "mat2";
    647 		case TOKEN_FLOAT_MAT2X3:			return "mat2x3";
    648 		case TOKEN_FLOAT_MAT2X4:			return "mat2x4";
    649 		case TOKEN_FLOAT_MAT3X2:			return "mat3x2";
    650 		case TOKEN_FLOAT_MAT3:				return "mat3";
    651 		case TOKEN_FLOAT_MAT3X4:			return "mat3x4";
    652 		case TOKEN_FLOAT_MAT4X2:			return "mat4x2";
    653 		case TOKEN_FLOAT_MAT4X3:			return "mat4x3";
    654 		case TOKEN_FLOAT_MAT4:				return "mat4";
    655 		case TOKEN_INT:						return "int";
    656 		case TOKEN_INT_VEC2:				return "ivec2";
    657 		case TOKEN_INT_VEC3:				return "ivec3";
    658 		case TOKEN_INT_VEC4:				return "ivec4";
    659 		case TOKEN_UINT:					return "uint";
    660 		case TOKEN_UINT_VEC2:				return "uvec2";
    661 		case TOKEN_UINT_VEC3:				return "uvec3";
    662 		case TOKEN_UINT_VEC4:				return "uvec4";
    663 		case TOKEN_BOOL:					return "bool";
    664 		case TOKEN_BOOL_VEC2:				return "bvec2";
    665 		case TOKEN_BOOL_VEC3:				return "bvec3";
    666 		case TOKEN_BOOL_VEC4:				return "bvec4";
    667 		case TOKEN_IN:						return "in";
    668 		case TOKEN_IMPORT:					return "import";
    669 		case TOKEN_PIPELINE_PROGRAM:		return "pipeline_program";
    670 		case TOKEN_ACTIVE_STAGES:			return "active_stages";
    671 
    672 		case TOKEN_ASSIGN:					return "=";
    673 		case TOKEN_PLUS:					return "+";
    674 		case TOKEN_MINUS:					return "-";
    675 		case TOKEN_COMMA:					return ",";
    676 		case TOKEN_VERTICAL_BAR:			return "|";
    677 		case TOKEN_SEMI_COLON:				return ";";
    678 		case TOKEN_LEFT_PAREN:				return "(";
    679 		case TOKEN_RIGHT_PAREN:				return ")";
    680 		case TOKEN_LEFT_BRACKET:			return "[";
    681 		case TOKEN_RIGHT_BRACKET:			return "]";
    682 		case TOKEN_LEFT_BRACE:				return "{";
    683 		case TOKEN_RIGHT_BRACE:				return "}";
    684 		case TOKEN_GREATER:					return ">";
    685 
    686 		default:							return "<unknown>";
    687 	}
    688 }
    689 
    690 deUint32 ShaderParser::getShaderStageLiteralFlag (void)
    691 {
    692 	switch (m_curToken)
    693 	{
    694 		case TOKEN_VERTEX:					return (1 << glu::SHADERTYPE_VERTEX);
    695 		case TOKEN_FRAGMENT:				return (1 << glu::SHADERTYPE_FRAGMENT);
    696 		case TOKEN_GEOMETRY:				return (1 << glu::SHADERTYPE_GEOMETRY);
    697 		case TOKEN_TESSELLATION_CONTROL:	return (1 << glu::SHADERTYPE_TESSELLATION_CONTROL);
    698 		case TOKEN_TESSELLATION_EVALUATION:	return (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION);
    699 
    700 		default:
    701 			parseError(std::string() + "invalid shader stage name, got " + m_curTokenStr);
    702 			return 0;
    703 	}
    704 }
    705 
    706 deUint32 ShaderParser::getGLEnumFromName (const std::string& enumName)
    707 {
    708 	static const struct
    709 	{
    710 		const char*	name;
    711 		deUint32	value;
    712 	} names[] =
    713 	{
    714 		{ "GL_MAX_VERTEX_IMAGE_UNIFORMS",			GL_MAX_VERTEX_IMAGE_UNIFORMS			},
    715 		{ "GL_MAX_VERTEX_ATOMIC_COUNTERS",			GL_MAX_VERTEX_ATOMIC_COUNTERS			},
    716 		{ "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",	GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS		},
    717 		{ "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",	GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS	},
    718 	};
    719 
    720 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(names); ++ndx)
    721 		if (names[ndx].name == enumName)
    722 			return names[ndx].value;
    723 
    724 	parseError(std::string() + "unknown enum name, got " + enumName);
    725 	return 0;
    726 }
    727 
    728 void ShaderParser::parseValueElement (DataType expectedDataType, ShaderCase::Value& result)
    729 {
    730 	DataType	scalarType	= getDataTypeScalarType(expectedDataType);
    731 	int			scalarSize	= getDataTypeScalarSize(expectedDataType);
    732 
    733 	/* \todo [2010-04-19 petri] Support arrays. */
    734 	ShaderCase::Value::Element elems[16];
    735 
    736 	if (scalarSize > 1)
    737 	{
    738 		DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
    739 		advanceToken(); // data type (float, vec2, etc.)
    740 		advanceToken(TOKEN_LEFT_PAREN);
    741 	}
    742 
    743 	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
    744 	{
    745 		if (scalarType == TYPE_FLOAT)
    746 		{
    747 			float signMult = 1.0f;
    748 			if (m_curToken == TOKEN_MINUS)
    749 			{
    750 				signMult = -1.0f;
    751 				advanceToken();
    752 			}
    753 
    754 			assumeToken(TOKEN_FLOAT_LITERAL);
    755 			elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
    756 			advanceToken(TOKEN_FLOAT_LITERAL);
    757 		}
    758 		else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
    759 		{
    760 			int signMult = 1;
    761 			if (m_curToken == TOKEN_MINUS)
    762 			{
    763 				signMult = -1;
    764 				advanceToken();
    765 			}
    766 
    767 			assumeToken(TOKEN_INT_LITERAL);
    768 			elems[scalarNdx].int32 = signMult * parseIntLiteral(m_curTokenStr.c_str());
    769 			advanceToken(TOKEN_INT_LITERAL);
    770 		}
    771 		else
    772 		{
    773 			DE_ASSERT(scalarType == TYPE_BOOL);
    774 			elems[scalarNdx].bool32 = (m_curToken == TOKEN_TRUE);
    775 			if (m_curToken != TOKEN_TRUE && m_curToken != TOKEN_FALSE)
    776 				parseError(string("unexpected token, expecting bool: " + m_curTokenStr));
    777 			advanceToken(); // true/false
    778 		}
    779 
    780 		if (scalarNdx != (scalarSize - 1))
    781 			advanceToken(TOKEN_COMMA);
    782 	}
    783 
    784 	if (scalarSize > 1)
    785 		advanceToken(TOKEN_RIGHT_PAREN);
    786 
    787 	// Store results.
    788 	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
    789 		result.elements.push_back(elems[scalarNdx]);
    790 }
    791 
    792 void ShaderParser::parseValue (ShaderCase::ValueBlock& valueBlock)
    793 {
    794 	PARSE_DBG(("      parseValue()\n"));
    795 
    796 	// Parsed results.
    797 	ShaderCase::Value result;
    798 
    799 	// Parse storage.
    800 	if (m_curToken == TOKEN_UNIFORM)
    801 		result.storageType = ShaderCase::Value::STORAGE_UNIFORM;
    802 	else if (m_curToken == TOKEN_INPUT)
    803 		result.storageType = ShaderCase::Value::STORAGE_INPUT;
    804 	else if (m_curToken == TOKEN_OUTPUT)
    805 		result.storageType = ShaderCase::Value::STORAGE_OUTPUT;
    806 	else
    807 		parseError(string("unexpected token encountered when parsing value classifier"));
    808 	advanceToken();
    809 
    810 	// Parse data type.
    811 	result.dataType = mapDataTypeToken(m_curToken);
    812 	if (result.dataType == TYPE_INVALID)
    813 		parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
    814 	advanceToken();
    815 
    816 	// Parse value name.
    817 	if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
    818 	{
    819 		if (m_curToken == TOKEN_IDENTIFIER)
    820 			result.valueName = m_curTokenStr;
    821 		else
    822 			result.valueName = parseStringLiteral(m_curTokenStr.c_str());
    823 	}
    824 	else
    825 		parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
    826 	advanceToken();
    827 
    828 	// Parse assignment operator.
    829 	advanceToken(TOKEN_ASSIGN);
    830 
    831 	// Parse actual value.
    832 	if (m_curToken == TOKEN_LEFT_BRACKET) // value list
    833 	{
    834 		advanceToken(TOKEN_LEFT_BRACKET);
    835 		result.arrayLength = 0;
    836 
    837 		for (;;)
    838 		{
    839 			parseValueElement(result.dataType, result);
    840 			result.arrayLength++;
    841 
    842 			if (m_curToken == TOKEN_RIGHT_BRACKET)
    843 				break;
    844 			else if (m_curToken == TOKEN_VERTICAL_BAR)
    845 			{
    846 				advanceToken();
    847 				continue;
    848 			}
    849 			else
    850 				parseError(string("unexpected token in value element array: " + m_curTokenStr));
    851 		}
    852 
    853 		advanceToken(TOKEN_RIGHT_BRACKET);
    854 	}
    855 	else // arrays, single elements
    856 	{
    857 		parseValueElement(result.dataType, result);
    858 		result.arrayLength = 1;
    859 	}
    860 
    861 	advanceToken(TOKEN_SEMI_COLON); // end of declaration
    862 
    863 	valueBlock.values.push_back(result);
    864 }
    865 
    866 void ShaderParser::parseValueBlock (ShaderCase::ValueBlock& valueBlock)
    867 {
    868 	PARSE_DBG(("    parseValueBlock()\n"));
    869 	advanceToken(TOKEN_VALUES);
    870 	advanceToken(TOKEN_LEFT_BRACE);
    871 
    872 	for (;;)
    873 	{
    874 		if (m_curToken == TOKEN_UNIFORM || m_curToken == TOKEN_INPUT || m_curToken == TOKEN_OUTPUT)
    875 			parseValue(valueBlock);
    876 		else if (m_curToken == TOKEN_RIGHT_BRACE)
    877 			break;
    878 		else
    879 			parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
    880 	}
    881 
    882 	advanceToken(TOKEN_RIGHT_BRACE);
    883 
    884 	// Compute combined array length of value block.
    885 	int arrayLength = 1;
    886 	for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
    887 	{
    888 		const ShaderCase::Value& val = valueBlock.values[valueNdx];
    889 		if (val.arrayLength > 1)
    890 		{
    891 			DE_ASSERT(arrayLength == 1 || arrayLength == val.arrayLength);
    892 			arrayLength = val.arrayLength;
    893 		}
    894 	}
    895 	valueBlock.arrayLength = arrayLength;
    896 }
    897 
    898 deUint32 ShaderParser::parseShaderStageList (void)
    899 {
    900 	deUint32 mask = 0;
    901 
    902 	assumeToken(TOKEN_LEFT_BRACE);
    903 
    904 	// don't allow 0-sized lists
    905 	advanceToken();
    906 	mask |= getShaderStageLiteralFlag();
    907 	advanceToken();
    908 
    909 	for (;;)
    910 	{
    911 		if (m_curToken == TOKEN_RIGHT_BRACE)
    912 			break;
    913 		else if (m_curToken == TOKEN_COMMA)
    914 		{
    915 			deUint32 stageFlag;
    916 			advanceToken();
    917 
    918 			stageFlag = getShaderStageLiteralFlag();
    919 			if (stageFlag & mask)
    920 				parseError(string("stage already set in the shader stage set: " + m_curTokenStr));
    921 
    922 			mask |= stageFlag;
    923 			advanceToken();
    924 		}
    925 		else
    926 			parseError(string("invalid shader stage set token: " + m_curTokenStr));
    927 	}
    928 	advanceToken(TOKEN_RIGHT_BRACE);
    929 
    930 	return mask;
    931 }
    932 
    933 void ShaderParser::parseRequirement (ShaderCase::CaseRequirement& valueBlock)
    934 {
    935 	PARSE_DBG(("    parseRequirement()\n"));
    936 
    937 	advanceToken();
    938 	assumeToken(TOKEN_IDENTIFIER);
    939 
    940 	if (m_curTokenStr == "extension")
    941 	{
    942 		std::vector<std::string>	anyExtensionStringList;
    943 		deUint32					affectedCasesFlags		= -1; // by default all stages
    944 
    945 		advanceToken();
    946 		assumeToken(TOKEN_LEFT_BRACE);
    947 
    948 		advanceToken();
    949 		assumeToken(TOKEN_STRING);
    950 
    951 		anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
    952 		advanceToken();
    953 
    954 		for (;;)
    955 		{
    956 			if (m_curToken == TOKEN_RIGHT_BRACE)
    957 				break;
    958 			else if (m_curToken == TOKEN_VERTICAL_BAR)
    959 			{
    960 				advanceToken();
    961 				assumeToken(TOKEN_STRING);
    962 
    963 				anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
    964 				advanceToken();
    965 			}
    966 			else
    967 				parseError(string("invalid extension list token: " + m_curTokenStr));
    968 		}
    969 		advanceToken(TOKEN_RIGHT_BRACE);
    970 
    971 		if (m_curToken == TOKEN_IN)
    972 		{
    973 			advanceToken();
    974 			affectedCasesFlags = parseShaderStageList();
    975 		}
    976 
    977 		valueBlock = ShaderCase::CaseRequirement::createAnyExtensionRequirement(anyExtensionStringList, affectedCasesFlags);
    978 	}
    979 	else if (m_curTokenStr == "limit")
    980 	{
    981 		deUint32	limitEnum;
    982 		int			limitValue;
    983 
    984 		advanceToken();
    985 
    986 		assumeToken(TOKEN_STRING);
    987 		limitEnum = getGLEnumFromName(parseStringLiteral(m_curTokenStr.c_str()));
    988 		advanceToken();
    989 
    990 		assumeToken(TOKEN_GREATER);
    991 		advanceToken();
    992 
    993 		assumeToken(TOKEN_INT_LITERAL);
    994 		limitValue = parseIntLiteral(m_curTokenStr.c_str());
    995 		advanceToken();
    996 
    997 		valueBlock = ShaderCase::CaseRequirement::createLimitRequirement(limitEnum, limitValue);
    998 	}
    999 	else
   1000 		parseError(string("invalid requirement value: " + m_curTokenStr));
   1001 }
   1002 
   1003 void ShaderParser::parseExpectResult (ShaderCase::ExpectResult& expectResult)
   1004 {
   1005 	assumeToken(TOKEN_IDENTIFIER);
   1006 
   1007 	if (m_curTokenStr == "pass")
   1008 		expectResult = ShaderCase::EXPECT_PASS;
   1009 	else if (m_curTokenStr == "compile_fail")
   1010 		expectResult = ShaderCase::EXPECT_COMPILE_FAIL;
   1011 	else if (m_curTokenStr == "link_fail")
   1012 		expectResult = ShaderCase::EXPECT_LINK_FAIL;
   1013 	else if (m_curTokenStr == "compile_or_link_fail")
   1014 		expectResult = ShaderCase::EXPECT_COMPILE_LINK_FAIL;
   1015 	else if (m_curTokenStr == "validation_fail")
   1016 		expectResult = ShaderCase::EXPECT_VALIDATION_FAIL;
   1017 	else
   1018 		parseError(string("invalid expected result value: " + m_curTokenStr));
   1019 
   1020 	advanceToken();
   1021 }
   1022 
   1023 void ShaderParser::parseGLSLVersion (glu::GLSLVersion& version)
   1024 {
   1025 	int			versionNum		= 0;
   1026 	std::string	postfix			= "";
   1027 
   1028 	assumeToken(TOKEN_INT_LITERAL);
   1029 	versionNum = parseIntLiteral(m_curTokenStr.c_str());
   1030 	advanceToken();
   1031 
   1032 	if (m_curToken == TOKEN_IDENTIFIER)
   1033 	{
   1034 		postfix = m_curTokenStr;
   1035 		advanceToken();
   1036 	}
   1037 
   1038 	if		(versionNum == 100 && postfix == "es")	version = glu::GLSL_VERSION_100_ES;
   1039 	else if (versionNum == 300 && postfix == "es")	version = glu::GLSL_VERSION_300_ES;
   1040 	else if (versionNum == 310 && postfix == "es")	version = glu::GLSL_VERSION_310_ES;
   1041 	else if (versionNum == 130)						version = glu::GLSL_VERSION_130;
   1042 	else if (versionNum == 140)						version = glu::GLSL_VERSION_140;
   1043 	else if (versionNum == 150)						version = glu::GLSL_VERSION_150;
   1044 	else if (versionNum == 330)						version = glu::GLSL_VERSION_330;
   1045 	else if (versionNum == 400)						version = glu::GLSL_VERSION_400;
   1046 	else if (versionNum == 410)						version = glu::GLSL_VERSION_410;
   1047 	else if (versionNum == 420)						version = glu::GLSL_VERSION_420;
   1048 	else if (versionNum == 430)						version = glu::GLSL_VERSION_430;
   1049 	else
   1050 		parseError("Unknown GLSL version");
   1051 }
   1052 
   1053 void ShaderParser::parsePipelineProgram (ShaderCase::PipelineProgram& program)
   1054 {
   1055 	deUint32							activeStages			= 0;
   1056 	vector<string>						vertexSources;
   1057 	vector<string>						fragmentSources;
   1058 	vector<string>						tessellationCtrlSources;
   1059 	vector<string>						tessellationEvalSources;
   1060 	vector<string>						geometrySources;
   1061 	vector<ShaderCase::CaseRequirement>	requirements;
   1062 
   1063 	advanceToken(TOKEN_PIPELINE_PROGRAM);
   1064 
   1065 	for (;;)
   1066 	{
   1067 		if (m_curToken == TOKEN_END)
   1068 			break;
   1069 		else if (m_curToken == TOKEN_ACTIVE_STAGES)
   1070 		{
   1071 			advanceToken();
   1072 			activeStages = parseShaderStageList();
   1073 		}
   1074 		else if (m_curToken == TOKEN_REQUIRE)
   1075 		{
   1076 			ShaderCase::CaseRequirement requirement;
   1077 			parseRequirement(requirement);
   1078 			requirements.push_back(requirement);
   1079 		}
   1080 		else if (m_curToken == TOKEN_VERTEX						||
   1081 				 m_curToken == TOKEN_FRAGMENT					||
   1082 				 m_curToken == TOKEN_TESSELLATION_CONTROL		||
   1083 				 m_curToken == TOKEN_TESSELLATION_EVALUATION	||
   1084 				 m_curToken == TOKEN_GEOMETRY)
   1085 		{
   1086 			const Token	token = m_curToken;
   1087 			string		source;
   1088 
   1089 			advanceToken();
   1090 			assumeToken(TOKEN_SHADER_SOURCE);
   1091 			source = parseShaderSource(m_curTokenStr.c_str());
   1092 			advanceToken();
   1093 
   1094 			switch (token)
   1095 			{
   1096 				case TOKEN_VERTEX:					vertexSources.push_back(source);			break;
   1097 				case TOKEN_FRAGMENT:				fragmentSources.push_back(source);			break;
   1098 				case TOKEN_TESSELLATION_CONTROL:	tessellationCtrlSources.push_back(source);	break;
   1099 				case TOKEN_TESSELLATION_EVALUATION:	tessellationEvalSources.push_back(source);	break;
   1100 				case TOKEN_GEOMETRY:				geometrySources.push_back(source);			break;
   1101 				default:
   1102 					parseError(DE_FALSE);
   1103 			}
   1104 		}
   1105 		else
   1106 			parseError(string("invalid pipeline program value: " + m_curTokenStr));
   1107 	}
   1108 	advanceToken(TOKEN_END);
   1109 
   1110 	if (activeStages == 0)
   1111 		parseError("program pipeline object must have active stages");
   1112 
   1113 	// return pipeline part
   1114 	program.activeStageBits = activeStages;
   1115 	program.requirements.swap(requirements);
   1116 	program.vertexSources.swap(vertexSources);
   1117 	program.fragmentSources.swap(fragmentSources);
   1118 	program.tessCtrlSources.swap(tessellationCtrlSources);
   1119 	program.tessEvalSources.swap(tessellationEvalSources);
   1120 	program.geometrySources.swap(geometrySources);
   1121 }
   1122 
   1123 void ShaderParser::parseShaderCase (vector<tcu::TestNode*>& shaderNodeList)
   1124 {
   1125 	// Parse 'case'.
   1126 	PARSE_DBG(("  parseShaderCase()\n"));
   1127 	advanceToken(TOKEN_CASE);
   1128 
   1129 	// Parse case name.
   1130 	string caseName = m_curTokenStr;
   1131 	advanceToken(); // \note [pyry] All token types are allowed here.
   1132 
   1133 	// Setup case.
   1134 	GLSLVersion							version			= DEFAULT_GLSL_VERSION;
   1135 	ShaderCase::ExpectResult			expectResult	= ShaderCase::EXPECT_PASS;
   1136 	string								description;
   1137 	string								bothSource;
   1138 	vector<string>						vertexSources;
   1139 	vector<string>						fragmentSources;
   1140 	vector<string>						tessellationCtrlSources;
   1141 	vector<string>						tessellationEvalSources;
   1142 	vector<string>						geometrySources;
   1143 	vector<ShaderCase::ValueBlock>		valueBlockList;
   1144 	vector<ShaderCase::CaseRequirement>	requirements;
   1145 	vector<ShaderCase::PipelineProgram>	pipelinePrograms;
   1146 
   1147 	for (;;)
   1148 	{
   1149 		if (m_curToken == TOKEN_END)
   1150 			break;
   1151 		else if (m_curToken == TOKEN_DESC)
   1152 		{
   1153 			advanceToken();
   1154 			assumeToken(TOKEN_STRING);
   1155 			description = parseStringLiteral(m_curTokenStr.c_str());
   1156 			advanceToken();
   1157 		}
   1158 		else if (m_curToken == TOKEN_EXPECT)
   1159 		{
   1160 			advanceToken();
   1161 			parseExpectResult(expectResult);
   1162 		}
   1163 		else if (m_curToken == TOKEN_VALUES)
   1164 		{
   1165 			ShaderCase::ValueBlock block;
   1166 			parseValueBlock(block);
   1167 			valueBlockList.push_back(block);
   1168 		}
   1169 		else if (m_curToken == TOKEN_BOTH						||
   1170 				 m_curToken == TOKEN_VERTEX						||
   1171 				 m_curToken == TOKEN_FRAGMENT					||
   1172 				 m_curToken == TOKEN_TESSELLATION_CONTROL		||
   1173 				 m_curToken == TOKEN_TESSELLATION_EVALUATION	||
   1174 				 m_curToken == TOKEN_GEOMETRY)
   1175 		{
   1176 			const Token	token = m_curToken;
   1177 			string		source;
   1178 
   1179 			advanceToken();
   1180 			assumeToken(TOKEN_SHADER_SOURCE);
   1181 			source = parseShaderSource(m_curTokenStr.c_str());
   1182 			advanceToken();
   1183 
   1184 			switch (token)
   1185 			{
   1186 				case TOKEN_VERTEX:					vertexSources.push_back(source);			break;
   1187 				case TOKEN_FRAGMENT:				fragmentSources.push_back(source);			break;
   1188 				case TOKEN_TESSELLATION_CONTROL:	tessellationCtrlSources.push_back(source);	break;
   1189 				case TOKEN_TESSELLATION_EVALUATION:	tessellationEvalSources.push_back(source);	break;
   1190 				case TOKEN_GEOMETRY:				geometrySources.push_back(source);			break;
   1191 				case TOKEN_BOTH:
   1192 				{
   1193 					if (!bothSource.empty())
   1194 						parseError("multiple 'both' blocks");
   1195 					bothSource = source;
   1196 					break;
   1197 				}
   1198 
   1199 				default:
   1200 					parseError(DE_FALSE);
   1201 			}
   1202 		}
   1203 		else if (m_curToken == TOKEN_VERSION)
   1204 		{
   1205 			advanceToken();
   1206 			parseGLSLVersion(version);
   1207 		}
   1208 		else if (m_curToken == TOKEN_REQUIRE)
   1209 		{
   1210 			ShaderCase::CaseRequirement requirement;
   1211 			parseRequirement(requirement);
   1212 			requirements.push_back(requirement);
   1213 		}
   1214 		else if (m_curToken == TOKEN_PIPELINE_PROGRAM)
   1215 		{
   1216 			ShaderCase::PipelineProgram pipelineProgram;
   1217 			parsePipelineProgram(pipelineProgram);
   1218 			pipelinePrograms.push_back(pipelineProgram);
   1219 		}
   1220 		else
   1221 			parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
   1222 	}
   1223 
   1224 	advanceToken(TOKEN_END); // case end
   1225 
   1226 	if (!bothSource.empty())
   1227 	{
   1228 		if (!vertexSources.empty()				||
   1229 			!fragmentSources.empty()			||
   1230 			!tessellationCtrlSources.empty()	||
   1231 			!tessellationEvalSources.empty()	||
   1232 			!geometrySources.empty()			||
   1233 			!pipelinePrograms.empty())
   1234 		{
   1235 			parseError("'both' cannot be mixed with other shader stages");
   1236 		}
   1237 
   1238 		// vertex
   1239 		{
   1240 			ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase(expectResult, version, valueBlockList, bothSource);
   1241 			spec.requirements = requirements;
   1242 
   1243 			shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_vertex").c_str(), description.c_str(), spec));
   1244 		}
   1245 
   1246 		// fragment
   1247 		{
   1248 			ShaderCase::ShaderCaseSpecification spec = ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase(expectResult, version, valueBlockList, bothSource);
   1249 			spec.requirements = requirements;
   1250 
   1251 			shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, (caseName + "_fragment").c_str(), description.c_str(), spec));
   1252 		}
   1253 	}
   1254 	else if (pipelinePrograms.empty())
   1255 	{
   1256 		ShaderCase::ShaderCaseSpecification spec;
   1257 
   1258 		spec.expectResult	= expectResult;
   1259 		spec.caseType		= ShaderCase::CASETYPE_COMPLETE;
   1260 		spec.targetVersion	= version;
   1261 		spec.requirements.swap(requirements);
   1262 		spec.valueBlocks.swap(valueBlockList);
   1263 		spec.vertexSources.swap(vertexSources);
   1264 		spec.fragmentSources.swap(fragmentSources);
   1265 		spec.tessCtrlSources.swap(tessellationCtrlSources);
   1266 		spec.tessEvalSources.swap(tessellationEvalSources);
   1267 		spec.geometrySources.swap(geometrySources);
   1268 
   1269 		shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
   1270 	}
   1271 	else
   1272 	{
   1273 		if (!vertexSources.empty()				||
   1274 			!fragmentSources.empty()			||
   1275 			!tessellationCtrlSources.empty()	||
   1276 			!tessellationEvalSources.empty()	||
   1277 			!geometrySources.empty())
   1278 		{
   1279 			parseError("pipeline programs cannot be mixed with complete programs");
   1280 		}
   1281 
   1282 		// Pipeline case, multiple programs
   1283 		{
   1284 			ShaderCase::PipelineCaseSpecification spec;
   1285 
   1286 			spec.expectResult	= expectResult;
   1287 			spec.caseType		= ShaderCase::CASETYPE_COMPLETE;
   1288 			spec.targetVersion	= version;
   1289 			spec.valueBlocks.swap(valueBlockList);
   1290 			spec.programs.swap(pipelinePrograms);
   1291 
   1292 			shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, m_contextInfo, caseName.c_str(), description.c_str(), spec));
   1293 		}
   1294 	}
   1295 }
   1296 
   1297 void ShaderParser::parseShaderGroup (vector<tcu::TestNode*>& shaderNodeList)
   1298 {
   1299 	// Parse 'case'.
   1300 	PARSE_DBG(("  parseShaderGroup()\n"));
   1301 	advanceToken(TOKEN_GROUP);
   1302 
   1303 	// Parse case name.
   1304 	string name = m_curTokenStr;
   1305 	advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
   1306 
   1307 	// Parse description.
   1308 	assumeToken(TOKEN_STRING);
   1309 	string description = parseStringLiteral(m_curTokenStr.c_str());
   1310 	advanceToken(TOKEN_STRING);
   1311 
   1312 	std::vector<tcu::TestNode*> children;
   1313 
   1314 	// Parse group children.
   1315 	for (;;)
   1316 	{
   1317 		if (m_curToken == TOKEN_END)
   1318 			break;
   1319 		else if (m_curToken == TOKEN_GROUP)
   1320 			parseShaderGroup(children);
   1321 		else if (m_curToken == TOKEN_CASE)
   1322 			parseShaderCase(children);
   1323 		else if (m_curToken == TOKEN_IMPORT)
   1324 			parseImport(children);
   1325 		else
   1326 			parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
   1327 	}
   1328 
   1329 	advanceToken(TOKEN_END); // group end
   1330 
   1331 	// Create group node.
   1332 	tcu::TestCaseGroup* groupNode = new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
   1333 	shaderNodeList.push_back(groupNode);
   1334 }
   1335 
   1336 void ShaderParser::parseImport (vector<tcu::TestNode*>& shaderNodeList)
   1337 {
   1338 	ShaderLibrary			subLibrary		(m_testCtx, m_renderCtx, m_contextInfo);
   1339 	vector<tcu::TestNode*>	importedCases;
   1340 	std::string				filename;
   1341 
   1342 	if (!m_currentDir)
   1343 		parseError(string("cannot use import in inline shader source"));
   1344 
   1345 	advanceToken(TOKEN_IMPORT);
   1346 
   1347 	assumeToken(TOKEN_STRING);
   1348 	filename = m_currentDir + parseStringLiteral(m_curTokenStr.c_str());
   1349 	advanceToken(TOKEN_STRING);
   1350 
   1351 	importedCases = subLibrary.loadShaderFile(filename.c_str());
   1352 	shaderNodeList.insert(shaderNodeList.end(), importedCases.begin(), importedCases.end());
   1353 }
   1354 
   1355 vector<tcu::TestNode*> ShaderParser::parse (const char* input)
   1356 {
   1357 	// Initialize parser.
   1358 	m_input			= input;
   1359 	m_curPtr		= m_input.c_str();
   1360 	m_curToken		= TOKEN_INVALID;
   1361 	m_curTokenStr	= "";
   1362 	advanceToken();
   1363 
   1364 	vector<tcu::TestNode*> nodeList;
   1365 
   1366 	// Parse all cases.
   1367 	PARSE_DBG(("parse()\n"));
   1368 	for (;;)
   1369 	{
   1370 		if (m_curToken == TOKEN_CASE)
   1371 			parseShaderCase(nodeList);
   1372 		else if (m_curToken == TOKEN_GROUP)
   1373 			parseShaderGroup(nodeList);
   1374 		else if (m_curToken == TOKEN_IMPORT)
   1375 			parseImport(nodeList);
   1376 		else if (m_curToken == TOKEN_EOF)
   1377 			break;
   1378 		else
   1379 			parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
   1380 	}
   1381 
   1382 	assumeToken(TOKEN_EOF);
   1383 //	printf("  parsed %d test cases.\n", caseList.size());
   1384 	return nodeList;
   1385 }
   1386 
   1387 } // sl
   1388 
   1389 static std::string getFileDirectory (const std::string& filePath)
   1390 {
   1391 	const std::string::size_type lastDelim = filePath.find_last_of('/');
   1392 
   1393 	if (lastDelim == std::string::npos)
   1394 		return "";
   1395 	else
   1396 		return filePath.substr(0, lastDelim+1);
   1397 }
   1398 
   1399 ShaderLibrary::ShaderLibrary (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo)
   1400 	: m_testCtx			(testCtx)
   1401 	, m_renderCtx		(renderCtx)
   1402 	, m_contextInfo		(contextInfo)
   1403 {
   1404 }
   1405 
   1406 ShaderLibrary::~ShaderLibrary (void)
   1407 {
   1408 }
   1409 
   1410 vector<tcu::TestNode*> ShaderLibrary::loadShaderFile (const char* fileName)
   1411 {
   1412 	tcu::Resource*		resource		= m_testCtx.getArchive().getResource(fileName);
   1413 	std::string			fileDirectory	= getFileDirectory(fileName);
   1414 	std::vector<char>	buf;
   1415 
   1416 /*	printf("  loading '%s'\n", fileName);*/
   1417 
   1418 	try
   1419 	{
   1420 		int size = resource->getSize();
   1421 		buf.resize(size + 1);
   1422 		resource->read((deUint8*)&buf[0], size);
   1423 		buf[size] = '\0';
   1424 	}
   1425 	catch (const std::exception&)
   1426 	{
   1427 		delete resource;
   1428 		throw;
   1429 	}
   1430 
   1431 	delete resource;
   1432 
   1433 	sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo, fileDirectory.c_str());
   1434 	vector<tcu::TestNode*> nodes = parser.parse(&buf[0]);
   1435 
   1436 	return nodes;
   1437 }
   1438 
   1439 vector<tcu::TestNode*> ShaderLibrary::parseShader (const char* shaderSource)
   1440 {
   1441 	sl::ShaderParser parser(m_testCtx, m_renderCtx, m_contextInfo);
   1442 	vector<tcu::TestNode*> nodes = parser.parse(shaderSource);
   1443 
   1444 	return nodes;
   1445 }
   1446 
   1447 } // gls
   1448 } // deqp
   1449