1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2016 Google Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci */ /*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Compiler test case.
23e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "glcShaderLibrary.hpp"
26e5c31af7Sopenharmony_ci#include "glcShaderLibraryCase.hpp"
27e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
28e5c31af7Sopenharmony_ci#include "tcuResource.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "deInt32.h"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include <fstream>
33e5c31af7Sopenharmony_ci#include <sstream>
34e5c31af7Sopenharmony_ci#include <string>
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include <stdarg.h>
38e5c31af7Sopenharmony_ci#include <stdlib.h>
39e5c31af7Sopenharmony_ci#include <string.h>
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ciusing std::string;
42e5c31af7Sopenharmony_ciusing std::vector;
43e5c31af7Sopenharmony_ciusing std::ostringstream;
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ciusing namespace glu;
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci#if 0
48e5c31af7Sopenharmony_ci#define PARSE_DBG(X) printf X
49e5c31af7Sopenharmony_ci#else
50e5c31af7Sopenharmony_ci#define PARSE_DBG(X) DE_NULL_STATEMENT
51e5c31af7Sopenharmony_ci#endif
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cinamespace deqp
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_cinamespace sl
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_cistatic const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciDE_INLINE deBool isWhitespace(char c)
61e5c31af7Sopenharmony_ci{
62e5c31af7Sopenharmony_ci	return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
63e5c31af7Sopenharmony_ci}
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_ciDE_INLINE deBool isEOL(char c)
66e5c31af7Sopenharmony_ci{
67e5c31af7Sopenharmony_ci	return (c == '\r') || (c == '\n');
68e5c31af7Sopenharmony_ci}
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ciDE_INLINE deBool isNumeric(char c)
71e5c31af7Sopenharmony_ci{
72e5c31af7Sopenharmony_ci	return deInRange32(c, '0', '9');
73e5c31af7Sopenharmony_ci}
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ciDE_INLINE deBool isAlpha(char c)
76e5c31af7Sopenharmony_ci{
77e5c31af7Sopenharmony_ci	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
78e5c31af7Sopenharmony_ci}
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ciDE_INLINE deBool isCaseNameChar(char c)
81e5c31af7Sopenharmony_ci{
82e5c31af7Sopenharmony_ci	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') ||
83e5c31af7Sopenharmony_ci		   (c == '-') || (c == '.');
84e5c31af7Sopenharmony_ci}
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci// \todo [2011-02-11 pyry] Should not depend on Context or TestContext!
87e5c31af7Sopenharmony_ciclass ShaderParser
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_cipublic:
90e5c31af7Sopenharmony_ci	ShaderParser(tcu::TestContext& testCtx, RenderContext& renderCtx);
91e5c31af7Sopenharmony_ci	~ShaderParser(void);
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	vector<tcu::TestNode*> parse(const char* input);
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ciprivate:
96e5c31af7Sopenharmony_ci	enum Token
97e5c31af7Sopenharmony_ci	{
98e5c31af7Sopenharmony_ci		TOKEN_INVALID = 0,
99e5c31af7Sopenharmony_ci		TOKEN_EOF,
100e5c31af7Sopenharmony_ci		TOKEN_STRING,
101e5c31af7Sopenharmony_ci		TOKEN_SHADER_SOURCE,
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_ci		TOKEN_INT_LITERAL,
104e5c31af7Sopenharmony_ci		TOKEN_FLOAT_LITERAL,
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ci		// identifiers
107e5c31af7Sopenharmony_ci		TOKEN_IDENTIFIER,
108e5c31af7Sopenharmony_ci		TOKEN_TRUE,
109e5c31af7Sopenharmony_ci		TOKEN_FALSE,
110e5c31af7Sopenharmony_ci		TOKEN_DESC,
111e5c31af7Sopenharmony_ci		TOKEN_EXPECT,
112e5c31af7Sopenharmony_ci		TOKEN_GROUP,
113e5c31af7Sopenharmony_ci		TOKEN_CASE,
114e5c31af7Sopenharmony_ci		TOKEN_END,
115e5c31af7Sopenharmony_ci		TOKEN_VALUES,
116e5c31af7Sopenharmony_ci		TOKEN_BOTH,
117e5c31af7Sopenharmony_ci		TOKEN_VERTEX,
118e5c31af7Sopenharmony_ci		TOKEN_FRAGMENT,
119e5c31af7Sopenharmony_ci		TOKEN_UNIFORM,
120e5c31af7Sopenharmony_ci		TOKEN_INPUT,
121e5c31af7Sopenharmony_ci		TOKEN_OUTPUT,
122e5c31af7Sopenharmony_ci		TOKEN_FLOAT,
123e5c31af7Sopenharmony_ci		TOKEN_FLOAT_VEC2,
124e5c31af7Sopenharmony_ci		TOKEN_FLOAT_VEC3,
125e5c31af7Sopenharmony_ci		TOKEN_FLOAT_VEC4,
126e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT2,
127e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT2X3,
128e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT2X4,
129e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT3X2,
130e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT3,
131e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT3X4,
132e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT4X2,
133e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT4X3,
134e5c31af7Sopenharmony_ci		TOKEN_FLOAT_MAT4,
135e5c31af7Sopenharmony_ci		TOKEN_INT,
136e5c31af7Sopenharmony_ci		TOKEN_INT_VEC2,
137e5c31af7Sopenharmony_ci		TOKEN_INT_VEC3,
138e5c31af7Sopenharmony_ci		TOKEN_INT_VEC4,
139e5c31af7Sopenharmony_ci		TOKEN_UINT,
140e5c31af7Sopenharmony_ci		TOKEN_UINT_VEC2,
141e5c31af7Sopenharmony_ci		TOKEN_UINT_VEC3,
142e5c31af7Sopenharmony_ci		TOKEN_UINT_VEC4,
143e5c31af7Sopenharmony_ci		TOKEN_BOOL,
144e5c31af7Sopenharmony_ci		TOKEN_BOOL_VEC2,
145e5c31af7Sopenharmony_ci		TOKEN_BOOL_VEC3,
146e5c31af7Sopenharmony_ci		TOKEN_BOOL_VEC4,
147e5c31af7Sopenharmony_ci		TOKEN_VERSION,
148e5c31af7Sopenharmony_ci
149e5c31af7Sopenharmony_ci		// symbols
150e5c31af7Sopenharmony_ci		TOKEN_ASSIGN,
151e5c31af7Sopenharmony_ci		TOKEN_PLUS,
152e5c31af7Sopenharmony_ci		TOKEN_MINUS,
153e5c31af7Sopenharmony_ci		TOKEN_COMMA,
154e5c31af7Sopenharmony_ci		TOKEN_VERTICAL_BAR,
155e5c31af7Sopenharmony_ci		TOKEN_SEMI_COLON,
156e5c31af7Sopenharmony_ci		TOKEN_LEFT_PAREN,
157e5c31af7Sopenharmony_ci		TOKEN_RIGHT_PAREN,
158e5c31af7Sopenharmony_ci		TOKEN_LEFT_BRACKET,
159e5c31af7Sopenharmony_ci		TOKEN_RIGHT_BRACKET,
160e5c31af7Sopenharmony_ci		TOKEN_LEFT_BRACE,
161e5c31af7Sopenharmony_ci		TOKEN_RIGHT_BRACE,
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci		TOKEN_LAST
164e5c31af7Sopenharmony_ci	};
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci	void parseError(const std::string& errorStr);
167e5c31af7Sopenharmony_ci	float parseFloatLiteral(const char* str);
168e5c31af7Sopenharmony_ci	long long int parseIntLiteral(const char* str);
169e5c31af7Sopenharmony_ci	string parseStringLiteral(const char* str);
170e5c31af7Sopenharmony_ci	string parseShaderSource(const char* str);
171e5c31af7Sopenharmony_ci	void advanceToken(void);
172e5c31af7Sopenharmony_ci	void advanceToken(Token assumed);
173e5c31af7Sopenharmony_ci	void assumeToken(Token token);
174e5c31af7Sopenharmony_ci	DataType mapDataTypeToken(Token token);
175e5c31af7Sopenharmony_ci	const char* getTokenName(Token token);
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci	void parseValueElement(DataType dataType, ShaderCase::Value& result);
178e5c31af7Sopenharmony_ci	void parseValue(ShaderCase::ValueBlock& valueBlock);
179e5c31af7Sopenharmony_ci	void parseValueBlock(ShaderCase::ValueBlock& valueBlock);
180e5c31af7Sopenharmony_ci	void parseShaderCase(vector<tcu::TestNode*>& shaderNodeList);
181e5c31af7Sopenharmony_ci	void parseShaderGroup(vector<tcu::TestNode*>& shaderNodeList);
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ci	// Member variables.
184e5c31af7Sopenharmony_ci	tcu::TestContext& m_testCtx;
185e5c31af7Sopenharmony_ci	RenderContext&	m_renderCtx;
186e5c31af7Sopenharmony_ci	std::string		  m_input;
187e5c31af7Sopenharmony_ci	const char*		  m_curPtr;
188e5c31af7Sopenharmony_ci	Token			  m_curToken;
189e5c31af7Sopenharmony_ci	std::string		  m_curTokenStr;
190e5c31af7Sopenharmony_ci};
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ciShaderParser::ShaderParser(tcu::TestContext& testCtx, RenderContext& renderCtx)
193e5c31af7Sopenharmony_ci	: m_testCtx(testCtx), m_renderCtx(renderCtx), m_curPtr(DE_NULL), m_curToken(TOKEN_LAST)
194e5c31af7Sopenharmony_ci{
195e5c31af7Sopenharmony_ci}
196e5c31af7Sopenharmony_ci
197e5c31af7Sopenharmony_ciShaderParser::~ShaderParser(void)
198e5c31af7Sopenharmony_ci{
199e5c31af7Sopenharmony_ci	// nada
200e5c31af7Sopenharmony_ci}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_civoid ShaderParser::parseError(const std::string& errorStr)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	string atStr = string(m_curPtr, 80);
205e5c31af7Sopenharmony_ci	throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), "", __FILE__,
206e5c31af7Sopenharmony_ci							 __LINE__);
207e5c31af7Sopenharmony_ci}
208e5c31af7Sopenharmony_ci
209e5c31af7Sopenharmony_cifloat ShaderParser::parseFloatLiteral(const char* str)
210e5c31af7Sopenharmony_ci{
211e5c31af7Sopenharmony_ci	return (float)atof(str);
212e5c31af7Sopenharmony_ci}
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_cilong long int ShaderParser::parseIntLiteral(const char* str)
215e5c31af7Sopenharmony_ci{
216e5c31af7Sopenharmony_ci	return strtoll(str, NULL, 0);
217e5c31af7Sopenharmony_ci}
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_cistring ShaderParser::parseStringLiteral(const char* str)
220e5c31af7Sopenharmony_ci{
221e5c31af7Sopenharmony_ci	const char*   p		  = str;
222e5c31af7Sopenharmony_ci	char		  endChar = *p++;
223e5c31af7Sopenharmony_ci	ostringstream o;
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_ci	while (*p != endChar && *p)
226e5c31af7Sopenharmony_ci	{
227e5c31af7Sopenharmony_ci		if (*p == '\\')
228e5c31af7Sopenharmony_ci		{
229e5c31af7Sopenharmony_ci			switch (p[1])
230e5c31af7Sopenharmony_ci			{
231e5c31af7Sopenharmony_ci			case 0:
232e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
233e5c31af7Sopenharmony_ci				break;
234e5c31af7Sopenharmony_ci			case 'n':
235e5c31af7Sopenharmony_ci				o << '\n';
236e5c31af7Sopenharmony_ci				break;
237e5c31af7Sopenharmony_ci			case 't':
238e5c31af7Sopenharmony_ci				o << '\t';
239e5c31af7Sopenharmony_ci				break;
240e5c31af7Sopenharmony_ci			default:
241e5c31af7Sopenharmony_ci				o << p[1];
242e5c31af7Sopenharmony_ci				break;
243e5c31af7Sopenharmony_ci			}
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci			p += 2;
246e5c31af7Sopenharmony_ci		}
247e5c31af7Sopenharmony_ci		else
248e5c31af7Sopenharmony_ci			o << *p++;
249e5c31af7Sopenharmony_ci	}
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ci	return o.str();
252e5c31af7Sopenharmony_ci}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_cistatic string removeExtraIndentation(const string& source)
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_ci	// Detect indentation from first line.
257e5c31af7Sopenharmony_ci	int numIndentChars = 0;
258e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)source.length() && isWhitespace(source[ndx]); ndx++)
259e5c31af7Sopenharmony_ci		numIndentChars += source[ndx] == '\t' ? 4 : 1;
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ci	// Process all lines and remove preceding indentation.
262e5c31af7Sopenharmony_ci	ostringstream processed;
263e5c31af7Sopenharmony_ci	{
264e5c31af7Sopenharmony_ci		bool atLineStart		= true;
265e5c31af7Sopenharmony_ci		int  indentCharsOmitted = 0;
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci		for (int pos = 0; pos < (int)source.length(); pos++)
268e5c31af7Sopenharmony_ci		{
269e5c31af7Sopenharmony_ci			char c = source[pos];
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_ci			if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
272e5c31af7Sopenharmony_ci			{
273e5c31af7Sopenharmony_ci				indentCharsOmitted += c == '\t' ? 4 : 1;
274e5c31af7Sopenharmony_ci			}
275e5c31af7Sopenharmony_ci			else if (isEOL(c))
276e5c31af7Sopenharmony_ci			{
277e5c31af7Sopenharmony_ci				if (source[pos] == '\r' && source[pos + 1] == '\n')
278e5c31af7Sopenharmony_ci				{
279e5c31af7Sopenharmony_ci					pos += 1;
280e5c31af7Sopenharmony_ci					processed << '\n';
281e5c31af7Sopenharmony_ci				}
282e5c31af7Sopenharmony_ci				else
283e5c31af7Sopenharmony_ci					processed << c;
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci				atLineStart		   = true;
286e5c31af7Sopenharmony_ci				indentCharsOmitted = 0;
287e5c31af7Sopenharmony_ci			}
288e5c31af7Sopenharmony_ci			else
289e5c31af7Sopenharmony_ci			{
290e5c31af7Sopenharmony_ci				processed << c;
291e5c31af7Sopenharmony_ci				atLineStart = false;
292e5c31af7Sopenharmony_ci			}
293e5c31af7Sopenharmony_ci		}
294e5c31af7Sopenharmony_ci	}
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci	return processed.str();
297e5c31af7Sopenharmony_ci}
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_cistring ShaderParser::parseShaderSource(const char* str)
300e5c31af7Sopenharmony_ci{
301e5c31af7Sopenharmony_ci	const char*   p = str + 2;
302e5c31af7Sopenharmony_ci	ostringstream o;
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci	// Eat first empty line from beginning.
305e5c31af7Sopenharmony_ci	while (*p == ' ')
306e5c31af7Sopenharmony_ci		p++;
307e5c31af7Sopenharmony_ci	while (isEOL(*p))
308e5c31af7Sopenharmony_ci		p++;
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci	while ((p[0] != '"') || (p[1] != '"'))
311e5c31af7Sopenharmony_ci	{
312e5c31af7Sopenharmony_ci		if (*p == '\\')
313e5c31af7Sopenharmony_ci		{
314e5c31af7Sopenharmony_ci			switch (p[1])
315e5c31af7Sopenharmony_ci			{
316e5c31af7Sopenharmony_ci			case 0:
317e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
318e5c31af7Sopenharmony_ci				break;
319e5c31af7Sopenharmony_ci			case 'n':
320e5c31af7Sopenharmony_ci				o << '\n';
321e5c31af7Sopenharmony_ci				break;
322e5c31af7Sopenharmony_ci			case 't':
323e5c31af7Sopenharmony_ci				o << '\t';
324e5c31af7Sopenharmony_ci				break;
325e5c31af7Sopenharmony_ci			default:
326e5c31af7Sopenharmony_ci				o << p[1];
327e5c31af7Sopenharmony_ci				break;
328e5c31af7Sopenharmony_ci			}
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci			p += 2;
331e5c31af7Sopenharmony_ci		}
332e5c31af7Sopenharmony_ci		else
333e5c31af7Sopenharmony_ci			o << *p++;
334e5c31af7Sopenharmony_ci	}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	return removeExtraIndentation(o.str());
337e5c31af7Sopenharmony_ci}
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_civoid ShaderParser::advanceToken(void)
340e5c31af7Sopenharmony_ci{
341e5c31af7Sopenharmony_ci	// Skip old token.
342e5c31af7Sopenharmony_ci	m_curPtr += m_curTokenStr.length();
343e5c31af7Sopenharmony_ci
344e5c31af7Sopenharmony_ci	// Reset token (for safety).
345e5c31af7Sopenharmony_ci	m_curToken	= TOKEN_INVALID;
346e5c31af7Sopenharmony_ci	m_curTokenStr = "";
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_ci	// Eat whitespace & comments while they last.
349e5c31af7Sopenharmony_ci	for (;;)
350e5c31af7Sopenharmony_ci	{
351e5c31af7Sopenharmony_ci		while (isWhitespace(*m_curPtr))
352e5c31af7Sopenharmony_ci			m_curPtr++;
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ci		// Check for EOL comment.
355e5c31af7Sopenharmony_ci		if (*m_curPtr == '#')
356e5c31af7Sopenharmony_ci		{
357e5c31af7Sopenharmony_ci			while (*m_curPtr && !isEOL(*m_curPtr))
358e5c31af7Sopenharmony_ci				m_curPtr++;
359e5c31af7Sopenharmony_ci		}
360e5c31af7Sopenharmony_ci		else
361e5c31af7Sopenharmony_ci			break;
362e5c31af7Sopenharmony_ci	}
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci	if (!*m_curPtr)
365e5c31af7Sopenharmony_ci	{
366e5c31af7Sopenharmony_ci		m_curToken	= TOKEN_EOF;
367e5c31af7Sopenharmony_ci		m_curTokenStr = "<EOF>";
368e5c31af7Sopenharmony_ci	}
369e5c31af7Sopenharmony_ci	else if (isAlpha(*m_curPtr))
370e5c31af7Sopenharmony_ci	{
371e5c31af7Sopenharmony_ci		struct Named
372e5c31af7Sopenharmony_ci		{
373e5c31af7Sopenharmony_ci			const char* str;
374e5c31af7Sopenharmony_ci			Token		token;
375e5c31af7Sopenharmony_ci		};
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_ci		static const Named s_named[] = { { "true", TOKEN_TRUE },
378e5c31af7Sopenharmony_ci										 { "false", TOKEN_FALSE },
379e5c31af7Sopenharmony_ci										 { "desc", TOKEN_DESC },
380e5c31af7Sopenharmony_ci										 { "expect", TOKEN_EXPECT },
381e5c31af7Sopenharmony_ci										 { "group", TOKEN_GROUP },
382e5c31af7Sopenharmony_ci										 { "case", TOKEN_CASE },
383e5c31af7Sopenharmony_ci										 { "end", TOKEN_END },
384e5c31af7Sopenharmony_ci										 { "values", TOKEN_VALUES },
385e5c31af7Sopenharmony_ci										 { "both", TOKEN_BOTH },
386e5c31af7Sopenharmony_ci										 { "vertex", TOKEN_VERTEX },
387e5c31af7Sopenharmony_ci										 { "fragment", TOKEN_FRAGMENT },
388e5c31af7Sopenharmony_ci										 { "uniform", TOKEN_UNIFORM },
389e5c31af7Sopenharmony_ci										 { "input", TOKEN_INPUT },
390e5c31af7Sopenharmony_ci										 { "output", TOKEN_OUTPUT },
391e5c31af7Sopenharmony_ci										 { "float", TOKEN_FLOAT },
392e5c31af7Sopenharmony_ci										 { "vec2", TOKEN_FLOAT_VEC2 },
393e5c31af7Sopenharmony_ci										 { "vec3", TOKEN_FLOAT_VEC3 },
394e5c31af7Sopenharmony_ci										 { "vec4", TOKEN_FLOAT_VEC4 },
395e5c31af7Sopenharmony_ci										 { "mat2", TOKEN_FLOAT_MAT2 },
396e5c31af7Sopenharmony_ci										 { "mat2x3", TOKEN_FLOAT_MAT2X3 },
397e5c31af7Sopenharmony_ci										 { "mat2x4", TOKEN_FLOAT_MAT2X4 },
398e5c31af7Sopenharmony_ci										 { "mat3x2", TOKEN_FLOAT_MAT3X2 },
399e5c31af7Sopenharmony_ci										 { "mat3", TOKEN_FLOAT_MAT3 },
400e5c31af7Sopenharmony_ci										 { "mat3x4", TOKEN_FLOAT_MAT3X4 },
401e5c31af7Sopenharmony_ci										 { "mat4x2", TOKEN_FLOAT_MAT4X2 },
402e5c31af7Sopenharmony_ci										 { "mat4x3", TOKEN_FLOAT_MAT4X3 },
403e5c31af7Sopenharmony_ci										 { "mat4", TOKEN_FLOAT_MAT4 },
404e5c31af7Sopenharmony_ci										 { "int", TOKEN_INT },
405e5c31af7Sopenharmony_ci										 { "ivec2", TOKEN_INT_VEC2 },
406e5c31af7Sopenharmony_ci										 { "ivec3", TOKEN_INT_VEC3 },
407e5c31af7Sopenharmony_ci										 { "ivec4", TOKEN_INT_VEC4 },
408e5c31af7Sopenharmony_ci										 { "uint", TOKEN_UINT },
409e5c31af7Sopenharmony_ci										 { "uvec2", TOKEN_UINT_VEC2 },
410e5c31af7Sopenharmony_ci										 { "uvec3", TOKEN_UINT_VEC3 },
411e5c31af7Sopenharmony_ci										 { "uvec4", TOKEN_UINT_VEC4 },
412e5c31af7Sopenharmony_ci										 { "bool", TOKEN_BOOL },
413e5c31af7Sopenharmony_ci										 { "bvec2", TOKEN_BOOL_VEC2 },
414e5c31af7Sopenharmony_ci										 { "bvec3", TOKEN_BOOL_VEC3 },
415e5c31af7Sopenharmony_ci										 { "bvec4", TOKEN_BOOL_VEC4 },
416e5c31af7Sopenharmony_ci										 { "version", TOKEN_VERSION } };
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ci		const char* end = m_curPtr + 1;
419e5c31af7Sopenharmony_ci		while (isCaseNameChar(*end))
420e5c31af7Sopenharmony_ci			end++;
421e5c31af7Sopenharmony_ci		m_curTokenStr = string(m_curPtr, end - m_curPtr);
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci		m_curToken = TOKEN_IDENTIFIER;
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
426e5c31af7Sopenharmony_ci		{
427e5c31af7Sopenharmony_ci			if (m_curTokenStr == s_named[ndx].str)
428e5c31af7Sopenharmony_ci			{
429e5c31af7Sopenharmony_ci				m_curToken = s_named[ndx].token;
430e5c31af7Sopenharmony_ci				break;
431e5c31af7Sopenharmony_ci			}
432e5c31af7Sopenharmony_ci		}
433e5c31af7Sopenharmony_ci	}
434e5c31af7Sopenharmony_ci	else if (isNumeric(*m_curPtr))
435e5c31af7Sopenharmony_ci	{
436e5c31af7Sopenharmony_ci		/* \todo [2010-03-31 petri] Hex? */
437e5c31af7Sopenharmony_ci		const char* p = m_curPtr;
438e5c31af7Sopenharmony_ci		while (isNumeric(*p))
439e5c31af7Sopenharmony_ci			p++;
440e5c31af7Sopenharmony_ci		if (*p == '.')
441e5c31af7Sopenharmony_ci		{
442e5c31af7Sopenharmony_ci			p++;
443e5c31af7Sopenharmony_ci			while (isNumeric(*p))
444e5c31af7Sopenharmony_ci				p++;
445e5c31af7Sopenharmony_ci
446e5c31af7Sopenharmony_ci			if (*p == 'e' || *p == 'E')
447e5c31af7Sopenharmony_ci			{
448e5c31af7Sopenharmony_ci				p++;
449e5c31af7Sopenharmony_ci				if (*p == '+' || *p == '-')
450e5c31af7Sopenharmony_ci					p++;
451e5c31af7Sopenharmony_ci				DE_ASSERT(isNumeric(*p));
452e5c31af7Sopenharmony_ci				while (isNumeric(*p))
453e5c31af7Sopenharmony_ci					p++;
454e5c31af7Sopenharmony_ci			}
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_ci			m_curToken	= TOKEN_FLOAT_LITERAL;
457e5c31af7Sopenharmony_ci			m_curTokenStr = string(m_curPtr, p - m_curPtr);
458e5c31af7Sopenharmony_ci		}
459e5c31af7Sopenharmony_ci		else
460e5c31af7Sopenharmony_ci		{
461e5c31af7Sopenharmony_ci			m_curToken	= TOKEN_INT_LITERAL;
462e5c31af7Sopenharmony_ci			m_curTokenStr = string(m_curPtr, p - m_curPtr);
463e5c31af7Sopenharmony_ci		}
464e5c31af7Sopenharmony_ci	}
465e5c31af7Sopenharmony_ci	else if (*m_curPtr == '"' && m_curPtr[1] == '"')
466e5c31af7Sopenharmony_ci	{
467e5c31af7Sopenharmony_ci		const char* p = m_curPtr + 2;
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_ci		while ((p[0] != '"') || (p[1] != '"'))
470e5c31af7Sopenharmony_ci		{
471e5c31af7Sopenharmony_ci			DE_ASSERT(*p);
472e5c31af7Sopenharmony_ci			if (*p == '\\')
473e5c31af7Sopenharmony_ci			{
474e5c31af7Sopenharmony_ci				DE_ASSERT(p[1] != 0);
475e5c31af7Sopenharmony_ci				p += 2;
476e5c31af7Sopenharmony_ci			}
477e5c31af7Sopenharmony_ci			else
478e5c31af7Sopenharmony_ci				p++;
479e5c31af7Sopenharmony_ci		}
480e5c31af7Sopenharmony_ci		p += 2;
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ci		m_curToken	= TOKEN_SHADER_SOURCE;
483e5c31af7Sopenharmony_ci		m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
484e5c31af7Sopenharmony_ci	}
485e5c31af7Sopenharmony_ci	else if (*m_curPtr == '"' || *m_curPtr == '\'')
486e5c31af7Sopenharmony_ci	{
487e5c31af7Sopenharmony_ci		char		endChar = *m_curPtr;
488e5c31af7Sopenharmony_ci		const char* p		= m_curPtr + 1;
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci		while (*p != endChar)
491e5c31af7Sopenharmony_ci		{
492e5c31af7Sopenharmony_ci			DE_ASSERT(*p);
493e5c31af7Sopenharmony_ci			if (*p == '\\')
494e5c31af7Sopenharmony_ci			{
495e5c31af7Sopenharmony_ci				DE_ASSERT(p[1] != 0);
496e5c31af7Sopenharmony_ci				p += 2;
497e5c31af7Sopenharmony_ci			}
498e5c31af7Sopenharmony_ci			else
499e5c31af7Sopenharmony_ci				p++;
500e5c31af7Sopenharmony_ci		}
501e5c31af7Sopenharmony_ci		p++;
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci		m_curToken	= TOKEN_STRING;
504e5c31af7Sopenharmony_ci		m_curTokenStr = string(m_curPtr, (int)(p - m_curPtr));
505e5c31af7Sopenharmony_ci	}
506e5c31af7Sopenharmony_ci	else
507e5c31af7Sopenharmony_ci	{
508e5c31af7Sopenharmony_ci		struct SimpleToken
509e5c31af7Sopenharmony_ci		{
510e5c31af7Sopenharmony_ci			const char* str;
511e5c31af7Sopenharmony_ci			Token		token;
512e5c31af7Sopenharmony_ci		};
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_ci		static const SimpleToken s_simple[] = { { "=", TOKEN_ASSIGN },		 { "+", TOKEN_PLUS },
515e5c31af7Sopenharmony_ci												{ "-", TOKEN_MINUS },		 { ",", TOKEN_COMMA },
516e5c31af7Sopenharmony_ci												{ "|", TOKEN_VERTICAL_BAR }, { ";", TOKEN_SEMI_COLON },
517e5c31af7Sopenharmony_ci												{ "(", TOKEN_LEFT_PAREN },   { ")", TOKEN_RIGHT_PAREN },
518e5c31af7Sopenharmony_ci												{ "[", TOKEN_LEFT_BRACKET }, { "]", TOKEN_RIGHT_BRACKET },
519e5c31af7Sopenharmony_ci												{ "{", TOKEN_LEFT_BRACE },   { "}", TOKEN_RIGHT_BRACE } };
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
522e5c31af7Sopenharmony_ci		{
523e5c31af7Sopenharmony_ci			if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
524e5c31af7Sopenharmony_ci			{
525e5c31af7Sopenharmony_ci				m_curToken	= s_simple[ndx].token;
526e5c31af7Sopenharmony_ci				m_curTokenStr = s_simple[ndx].str;
527e5c31af7Sopenharmony_ci				return;
528e5c31af7Sopenharmony_ci			}
529e5c31af7Sopenharmony_ci		}
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci		// Otherwise invalid token.
532e5c31af7Sopenharmony_ci		m_curToken	= TOKEN_INVALID;
533e5c31af7Sopenharmony_ci		m_curTokenStr = *m_curPtr;
534e5c31af7Sopenharmony_ci	}
535e5c31af7Sopenharmony_ci}
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_civoid ShaderParser::advanceToken(Token assumed)
538e5c31af7Sopenharmony_ci{
539e5c31af7Sopenharmony_ci	assumeToken(assumed);
540e5c31af7Sopenharmony_ci	advanceToken();
541e5c31af7Sopenharmony_ci}
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_civoid ShaderParser::assumeToken(Token token)
544e5c31af7Sopenharmony_ci{
545e5c31af7Sopenharmony_ci	if (m_curToken != token)
546e5c31af7Sopenharmony_ci		parseError(
547e5c31af7Sopenharmony_ci			(string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
548e5c31af7Sopenharmony_ci	DE_TEST_ASSERT(m_curToken == token);
549e5c31af7Sopenharmony_ci}
550e5c31af7Sopenharmony_ci
551e5c31af7Sopenharmony_ciDataType ShaderParser::mapDataTypeToken(Token token)
552e5c31af7Sopenharmony_ci{
553e5c31af7Sopenharmony_ci	switch (token)
554e5c31af7Sopenharmony_ci	{
555e5c31af7Sopenharmony_ci	case TOKEN_FLOAT:
556e5c31af7Sopenharmony_ci		return TYPE_FLOAT;
557e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC2:
558e5c31af7Sopenharmony_ci		return TYPE_FLOAT_VEC2;
559e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC3:
560e5c31af7Sopenharmony_ci		return TYPE_FLOAT_VEC3;
561e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC4:
562e5c31af7Sopenharmony_ci		return TYPE_FLOAT_VEC4;
563e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2:
564e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT2;
565e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2X3:
566e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT2X3;
567e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2X4:
568e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT2X4;
569e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3X2:
570e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT3X2;
571e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3:
572e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT3;
573e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3X4:
574e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT3X4;
575e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4X2:
576e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT4X2;
577e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4X3:
578e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT4X3;
579e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4:
580e5c31af7Sopenharmony_ci		return TYPE_FLOAT_MAT4;
581e5c31af7Sopenharmony_ci	case TOKEN_INT:
582e5c31af7Sopenharmony_ci		return TYPE_INT;
583e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC2:
584e5c31af7Sopenharmony_ci		return TYPE_INT_VEC2;
585e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC3:
586e5c31af7Sopenharmony_ci		return TYPE_INT_VEC3;
587e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC4:
588e5c31af7Sopenharmony_ci		return TYPE_INT_VEC4;
589e5c31af7Sopenharmony_ci	case TOKEN_UINT:
590e5c31af7Sopenharmony_ci		return TYPE_UINT;
591e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC2:
592e5c31af7Sopenharmony_ci		return TYPE_UINT_VEC2;
593e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC3:
594e5c31af7Sopenharmony_ci		return TYPE_UINT_VEC3;
595e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC4:
596e5c31af7Sopenharmony_ci		return TYPE_UINT_VEC4;
597e5c31af7Sopenharmony_ci	case TOKEN_BOOL:
598e5c31af7Sopenharmony_ci		return TYPE_BOOL;
599e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC2:
600e5c31af7Sopenharmony_ci		return TYPE_BOOL_VEC2;
601e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC3:
602e5c31af7Sopenharmony_ci		return TYPE_BOOL_VEC3;
603e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC4:
604e5c31af7Sopenharmony_ci		return TYPE_BOOL_VEC4;
605e5c31af7Sopenharmony_ci	default:
606e5c31af7Sopenharmony_ci		return TYPE_INVALID;
607e5c31af7Sopenharmony_ci	}
608e5c31af7Sopenharmony_ci}
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ciconst char* ShaderParser::getTokenName(Token token)
611e5c31af7Sopenharmony_ci{
612e5c31af7Sopenharmony_ci	switch (token)
613e5c31af7Sopenharmony_ci	{
614e5c31af7Sopenharmony_ci	case TOKEN_INVALID:
615e5c31af7Sopenharmony_ci		return "<invalid>";
616e5c31af7Sopenharmony_ci	case TOKEN_EOF:
617e5c31af7Sopenharmony_ci		return "<eof>";
618e5c31af7Sopenharmony_ci	case TOKEN_STRING:
619e5c31af7Sopenharmony_ci		return "<string>";
620e5c31af7Sopenharmony_ci	case TOKEN_SHADER_SOURCE:
621e5c31af7Sopenharmony_ci		return "source";
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci	case TOKEN_INT_LITERAL:
624e5c31af7Sopenharmony_ci		return "<int>";
625e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_LITERAL:
626e5c31af7Sopenharmony_ci		return "<float>";
627e5c31af7Sopenharmony_ci
628e5c31af7Sopenharmony_ci	// identifiers
629e5c31af7Sopenharmony_ci	case TOKEN_IDENTIFIER:
630e5c31af7Sopenharmony_ci		return "<identifier>";
631e5c31af7Sopenharmony_ci	case TOKEN_TRUE:
632e5c31af7Sopenharmony_ci		return "true";
633e5c31af7Sopenharmony_ci	case TOKEN_FALSE:
634e5c31af7Sopenharmony_ci		return "false";
635e5c31af7Sopenharmony_ci	case TOKEN_DESC:
636e5c31af7Sopenharmony_ci		return "desc";
637e5c31af7Sopenharmony_ci	case TOKEN_EXPECT:
638e5c31af7Sopenharmony_ci		return "expect";
639e5c31af7Sopenharmony_ci	case TOKEN_GROUP:
640e5c31af7Sopenharmony_ci		return "group";
641e5c31af7Sopenharmony_ci	case TOKEN_CASE:
642e5c31af7Sopenharmony_ci		return "case";
643e5c31af7Sopenharmony_ci	case TOKEN_END:
644e5c31af7Sopenharmony_ci		return "end";
645e5c31af7Sopenharmony_ci	case TOKEN_VALUES:
646e5c31af7Sopenharmony_ci		return "values";
647e5c31af7Sopenharmony_ci	case TOKEN_BOTH:
648e5c31af7Sopenharmony_ci		return "both";
649e5c31af7Sopenharmony_ci	case TOKEN_VERTEX:
650e5c31af7Sopenharmony_ci		return "vertex";
651e5c31af7Sopenharmony_ci	case TOKEN_FRAGMENT:
652e5c31af7Sopenharmony_ci		return "fragment";
653e5c31af7Sopenharmony_ci	case TOKEN_UNIFORM:
654e5c31af7Sopenharmony_ci		return "uniform";
655e5c31af7Sopenharmony_ci	case TOKEN_INPUT:
656e5c31af7Sopenharmony_ci		return "input";
657e5c31af7Sopenharmony_ci	case TOKEN_OUTPUT:
658e5c31af7Sopenharmony_ci		return "output";
659e5c31af7Sopenharmony_ci	case TOKEN_FLOAT:
660e5c31af7Sopenharmony_ci		return "float";
661e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC2:
662e5c31af7Sopenharmony_ci		return "vec2";
663e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC3:
664e5c31af7Sopenharmony_ci		return "vec3";
665e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_VEC4:
666e5c31af7Sopenharmony_ci		return "vec4";
667e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2:
668e5c31af7Sopenharmony_ci		return "mat2";
669e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2X3:
670e5c31af7Sopenharmony_ci		return "mat2x3";
671e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT2X4:
672e5c31af7Sopenharmony_ci		return "mat2x4";
673e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3X2:
674e5c31af7Sopenharmony_ci		return "mat3x2";
675e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3:
676e5c31af7Sopenharmony_ci		return "mat3";
677e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT3X4:
678e5c31af7Sopenharmony_ci		return "mat3x4";
679e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4X2:
680e5c31af7Sopenharmony_ci		return "mat4x2";
681e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4X3:
682e5c31af7Sopenharmony_ci		return "mat4x3";
683e5c31af7Sopenharmony_ci	case TOKEN_FLOAT_MAT4:
684e5c31af7Sopenharmony_ci		return "mat4";
685e5c31af7Sopenharmony_ci	case TOKEN_INT:
686e5c31af7Sopenharmony_ci		return "int";
687e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC2:
688e5c31af7Sopenharmony_ci		return "ivec2";
689e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC3:
690e5c31af7Sopenharmony_ci		return "ivec3";
691e5c31af7Sopenharmony_ci	case TOKEN_INT_VEC4:
692e5c31af7Sopenharmony_ci		return "ivec4";
693e5c31af7Sopenharmony_ci	case TOKEN_UINT:
694e5c31af7Sopenharmony_ci		return "uint";
695e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC2:
696e5c31af7Sopenharmony_ci		return "uvec2";
697e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC3:
698e5c31af7Sopenharmony_ci		return "uvec3";
699e5c31af7Sopenharmony_ci	case TOKEN_UINT_VEC4:
700e5c31af7Sopenharmony_ci		return "uvec4";
701e5c31af7Sopenharmony_ci	case TOKEN_BOOL:
702e5c31af7Sopenharmony_ci		return "bool";
703e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC2:
704e5c31af7Sopenharmony_ci		return "bvec2";
705e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC3:
706e5c31af7Sopenharmony_ci		return "bvec3";
707e5c31af7Sopenharmony_ci	case TOKEN_BOOL_VEC4:
708e5c31af7Sopenharmony_ci		return "bvec4";
709e5c31af7Sopenharmony_ci
710e5c31af7Sopenharmony_ci	case TOKEN_ASSIGN:
711e5c31af7Sopenharmony_ci		return "=";
712e5c31af7Sopenharmony_ci	case TOKEN_PLUS:
713e5c31af7Sopenharmony_ci		return "+";
714e5c31af7Sopenharmony_ci	case TOKEN_MINUS:
715e5c31af7Sopenharmony_ci		return "-";
716e5c31af7Sopenharmony_ci	case TOKEN_COMMA:
717e5c31af7Sopenharmony_ci		return ",";
718e5c31af7Sopenharmony_ci	case TOKEN_VERTICAL_BAR:
719e5c31af7Sopenharmony_ci		return "|";
720e5c31af7Sopenharmony_ci	case TOKEN_SEMI_COLON:
721e5c31af7Sopenharmony_ci		return ";";
722e5c31af7Sopenharmony_ci	case TOKEN_LEFT_PAREN:
723e5c31af7Sopenharmony_ci		return "(";
724e5c31af7Sopenharmony_ci	case TOKEN_RIGHT_PAREN:
725e5c31af7Sopenharmony_ci		return ")";
726e5c31af7Sopenharmony_ci	case TOKEN_LEFT_BRACKET:
727e5c31af7Sopenharmony_ci		return "[";
728e5c31af7Sopenharmony_ci	case TOKEN_RIGHT_BRACKET:
729e5c31af7Sopenharmony_ci		return "]";
730e5c31af7Sopenharmony_ci	case TOKEN_LEFT_BRACE:
731e5c31af7Sopenharmony_ci		return "{";
732e5c31af7Sopenharmony_ci	case TOKEN_RIGHT_BRACE:
733e5c31af7Sopenharmony_ci		return "}";
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci	default:
736e5c31af7Sopenharmony_ci		return "<unknown>";
737e5c31af7Sopenharmony_ci	}
738e5c31af7Sopenharmony_ci}
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_civoid ShaderParser::parseValueElement(DataType expectedDataType, ShaderCase::Value& result)
741e5c31af7Sopenharmony_ci{
742e5c31af7Sopenharmony_ci	DataType scalarType = getDataTypeScalarType(expectedDataType);
743e5c31af7Sopenharmony_ci	int		 scalarSize = getDataTypeScalarSize(expectedDataType);
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	/* \todo [2010-04-19 petri] Support arrays. */
746e5c31af7Sopenharmony_ci	ShaderCase::Value::Element elems[16];
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci	if (scalarSize > 1)
749e5c31af7Sopenharmony_ci	{
750e5c31af7Sopenharmony_ci		DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
751e5c31af7Sopenharmony_ci		advanceToken(); // data type (float, vec2, etc.)
752e5c31af7Sopenharmony_ci		advanceToken(TOKEN_LEFT_PAREN);
753e5c31af7Sopenharmony_ci	}
754e5c31af7Sopenharmony_ci
755e5c31af7Sopenharmony_ci	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
756e5c31af7Sopenharmony_ci	{
757e5c31af7Sopenharmony_ci		if (scalarType == TYPE_FLOAT)
758e5c31af7Sopenharmony_ci		{
759e5c31af7Sopenharmony_ci			float signMult = 1.0f;
760e5c31af7Sopenharmony_ci			if (m_curToken == TOKEN_MINUS)
761e5c31af7Sopenharmony_ci			{
762e5c31af7Sopenharmony_ci				signMult = -1.0f;
763e5c31af7Sopenharmony_ci				advanceToken();
764e5c31af7Sopenharmony_ci			}
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ci			assumeToken(TOKEN_FLOAT_LITERAL);
767e5c31af7Sopenharmony_ci			elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
768e5c31af7Sopenharmony_ci			advanceToken(TOKEN_FLOAT_LITERAL);
769e5c31af7Sopenharmony_ci		}
770e5c31af7Sopenharmony_ci		else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
771e5c31af7Sopenharmony_ci		{
772e5c31af7Sopenharmony_ci			int signMult = 1;
773e5c31af7Sopenharmony_ci			if (m_curToken == TOKEN_MINUS)
774e5c31af7Sopenharmony_ci			{
775e5c31af7Sopenharmony_ci				signMult = -1;
776e5c31af7Sopenharmony_ci				advanceToken();
777e5c31af7Sopenharmony_ci			}
778e5c31af7Sopenharmony_ci
779e5c31af7Sopenharmony_ci			assumeToken(TOKEN_INT_LITERAL);
780e5c31af7Sopenharmony_ci			elems[scalarNdx].int32 = (deInt32)(signMult * parseIntLiteral(m_curTokenStr.c_str()));
781e5c31af7Sopenharmony_ci			advanceToken(TOKEN_INT_LITERAL);
782e5c31af7Sopenharmony_ci		}
783e5c31af7Sopenharmony_ci		else
784e5c31af7Sopenharmony_ci		{
785e5c31af7Sopenharmony_ci			DE_ASSERT(scalarType == TYPE_BOOL);
786e5c31af7Sopenharmony_ci			elems[scalarNdx].bool32 = (m_curToken == TOKEN_TRUE);
787e5c31af7Sopenharmony_ci			if (m_curToken != TOKEN_TRUE && m_curToken != TOKEN_FALSE)
788e5c31af7Sopenharmony_ci				parseError(string("unexpected token, expecting bool: " + m_curTokenStr));
789e5c31af7Sopenharmony_ci			advanceToken(); // true/false
790e5c31af7Sopenharmony_ci		}
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci		if (scalarNdx != (scalarSize - 1))
793e5c31af7Sopenharmony_ci			advanceToken(TOKEN_COMMA);
794e5c31af7Sopenharmony_ci	}
795e5c31af7Sopenharmony_ci
796e5c31af7Sopenharmony_ci	if (scalarSize > 1)
797e5c31af7Sopenharmony_ci		advanceToken(TOKEN_RIGHT_PAREN);
798e5c31af7Sopenharmony_ci
799e5c31af7Sopenharmony_ci	// Store results.
800e5c31af7Sopenharmony_ci	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
801e5c31af7Sopenharmony_ci		result.elements.push_back(elems[scalarNdx]);
802e5c31af7Sopenharmony_ci}
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_civoid ShaderParser::parseValue(ShaderCase::ValueBlock& valueBlock)
805e5c31af7Sopenharmony_ci{
806e5c31af7Sopenharmony_ci	PARSE_DBG(("      parseValue()\n"));
807e5c31af7Sopenharmony_ci
808e5c31af7Sopenharmony_ci	// Parsed results.
809e5c31af7Sopenharmony_ci	ShaderCase::Value result;
810e5c31af7Sopenharmony_ci
811e5c31af7Sopenharmony_ci	// Parse storage.
812e5c31af7Sopenharmony_ci	if (m_curToken == TOKEN_UNIFORM)
813e5c31af7Sopenharmony_ci		result.storageType = ShaderCase::Value::STORAGE_UNIFORM;
814e5c31af7Sopenharmony_ci	else if (m_curToken == TOKEN_INPUT)
815e5c31af7Sopenharmony_ci		result.storageType = ShaderCase::Value::STORAGE_INPUT;
816e5c31af7Sopenharmony_ci	else if (m_curToken == TOKEN_OUTPUT)
817e5c31af7Sopenharmony_ci		result.storageType = ShaderCase::Value::STORAGE_OUTPUT;
818e5c31af7Sopenharmony_ci	else
819e5c31af7Sopenharmony_ci		parseError(string("unexpected token encountered when parsing value classifier"));
820e5c31af7Sopenharmony_ci	advanceToken();
821e5c31af7Sopenharmony_ci
822e5c31af7Sopenharmony_ci	// Parse data type.
823e5c31af7Sopenharmony_ci	result.dataType = mapDataTypeToken(m_curToken);
824e5c31af7Sopenharmony_ci	if (result.dataType == TYPE_INVALID)
825e5c31af7Sopenharmony_ci		parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
826e5c31af7Sopenharmony_ci	advanceToken();
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci	// Parse value name.
829e5c31af7Sopenharmony_ci	if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
830e5c31af7Sopenharmony_ci	{
831e5c31af7Sopenharmony_ci		if (m_curToken == TOKEN_IDENTIFIER)
832e5c31af7Sopenharmony_ci			result.valueName = m_curTokenStr;
833e5c31af7Sopenharmony_ci		else
834e5c31af7Sopenharmony_ci			result.valueName = parseStringLiteral(m_curTokenStr.c_str());
835e5c31af7Sopenharmony_ci	}
836e5c31af7Sopenharmony_ci	else
837e5c31af7Sopenharmony_ci		parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
838e5c31af7Sopenharmony_ci	advanceToken();
839e5c31af7Sopenharmony_ci
840e5c31af7Sopenharmony_ci	// Parse assignment operator.
841e5c31af7Sopenharmony_ci	advanceToken(TOKEN_ASSIGN);
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_ci	// Parse actual value.
844e5c31af7Sopenharmony_ci	if (m_curToken == TOKEN_LEFT_BRACKET) // value list
845e5c31af7Sopenharmony_ci	{
846e5c31af7Sopenharmony_ci		advanceToken(TOKEN_LEFT_BRACKET);
847e5c31af7Sopenharmony_ci		result.arrayLength = 0;
848e5c31af7Sopenharmony_ci
849e5c31af7Sopenharmony_ci		for (;;)
850e5c31af7Sopenharmony_ci		{
851e5c31af7Sopenharmony_ci			parseValueElement(result.dataType, result);
852e5c31af7Sopenharmony_ci			result.arrayLength++;
853e5c31af7Sopenharmony_ci
854e5c31af7Sopenharmony_ci			if (m_curToken == TOKEN_RIGHT_BRACKET)
855e5c31af7Sopenharmony_ci				break;
856e5c31af7Sopenharmony_ci			else if (m_curToken == TOKEN_VERTICAL_BAR)
857e5c31af7Sopenharmony_ci			{
858e5c31af7Sopenharmony_ci				advanceToken();
859e5c31af7Sopenharmony_ci				continue;
860e5c31af7Sopenharmony_ci			}
861e5c31af7Sopenharmony_ci			else
862e5c31af7Sopenharmony_ci				parseError(string("unexpected token in value element array: " + m_curTokenStr));
863e5c31af7Sopenharmony_ci		}
864e5c31af7Sopenharmony_ci
865e5c31af7Sopenharmony_ci		advanceToken(TOKEN_RIGHT_BRACKET);
866e5c31af7Sopenharmony_ci	}
867e5c31af7Sopenharmony_ci	else // arrays, single elements
868e5c31af7Sopenharmony_ci	{
869e5c31af7Sopenharmony_ci		parseValueElement(result.dataType, result);
870e5c31af7Sopenharmony_ci		result.arrayLength = 1;
871e5c31af7Sopenharmony_ci	}
872e5c31af7Sopenharmony_ci
873e5c31af7Sopenharmony_ci	advanceToken(TOKEN_SEMI_COLON); // end of declaration
874e5c31af7Sopenharmony_ci
875e5c31af7Sopenharmony_ci	valueBlock.values.push_back(result);
876e5c31af7Sopenharmony_ci}
877e5c31af7Sopenharmony_ci
878e5c31af7Sopenharmony_civoid ShaderParser::parseValueBlock(ShaderCase::ValueBlock& valueBlock)
879e5c31af7Sopenharmony_ci{
880e5c31af7Sopenharmony_ci	PARSE_DBG(("    parseValueBlock()\n"));
881e5c31af7Sopenharmony_ci	advanceToken(TOKEN_VALUES);
882e5c31af7Sopenharmony_ci	advanceToken(TOKEN_LEFT_BRACE);
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_ci	for (;;)
885e5c31af7Sopenharmony_ci	{
886e5c31af7Sopenharmony_ci		if (m_curToken == TOKEN_UNIFORM || m_curToken == TOKEN_INPUT || m_curToken == TOKEN_OUTPUT)
887e5c31af7Sopenharmony_ci			parseValue(valueBlock);
888e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_RIGHT_BRACE)
889e5c31af7Sopenharmony_ci			break;
890e5c31af7Sopenharmony_ci		else
891e5c31af7Sopenharmony_ci			parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
892e5c31af7Sopenharmony_ci	}
893e5c31af7Sopenharmony_ci
894e5c31af7Sopenharmony_ci	advanceToken(TOKEN_RIGHT_BRACE);
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_ci	// Compute combined array length of value block.
897e5c31af7Sopenharmony_ci	int arrayLength = 1;
898e5c31af7Sopenharmony_ci	for (int valueNdx = 0; valueNdx < (int)valueBlock.values.size(); valueNdx++)
899e5c31af7Sopenharmony_ci	{
900e5c31af7Sopenharmony_ci		const ShaderCase::Value& val = valueBlock.values[valueNdx];
901e5c31af7Sopenharmony_ci		if (val.arrayLength > 1)
902e5c31af7Sopenharmony_ci		{
903e5c31af7Sopenharmony_ci			DE_ASSERT(arrayLength == 1 || arrayLength == val.arrayLength);
904e5c31af7Sopenharmony_ci			arrayLength = val.arrayLength;
905e5c31af7Sopenharmony_ci		}
906e5c31af7Sopenharmony_ci	}
907e5c31af7Sopenharmony_ci	valueBlock.arrayLength = arrayLength;
908e5c31af7Sopenharmony_ci}
909e5c31af7Sopenharmony_ci
910e5c31af7Sopenharmony_civoid ShaderParser::parseShaderCase(vector<tcu::TestNode*>& shaderNodeList)
911e5c31af7Sopenharmony_ci{
912e5c31af7Sopenharmony_ci	// Parse 'case'.
913e5c31af7Sopenharmony_ci	PARSE_DBG(("  parseShaderCase()\n"));
914e5c31af7Sopenharmony_ci	advanceToken(TOKEN_CASE);
915e5c31af7Sopenharmony_ci
916e5c31af7Sopenharmony_ci	// Parse case name.
917e5c31af7Sopenharmony_ci	string caseName = m_curTokenStr;
918e5c31af7Sopenharmony_ci	advanceToken(); // \note [pyry] All token types are allowed here.
919e5c31af7Sopenharmony_ci
920e5c31af7Sopenharmony_ci	// Setup case.
921e5c31af7Sopenharmony_ci	vector<ShaderCase::ValueBlock> valueBlockList;
922e5c31af7Sopenharmony_ci
923e5c31af7Sopenharmony_ci	GLSLVersion				 version	  = DEFAULT_GLSL_VERSION;
924e5c31af7Sopenharmony_ci	ShaderCase::ExpectResult expectResult = ShaderCase::EXPECT_PASS;
925e5c31af7Sopenharmony_ci	string					 description;
926e5c31af7Sopenharmony_ci	string					 bothSource;
927e5c31af7Sopenharmony_ci	string					 vertexSource;
928e5c31af7Sopenharmony_ci	string					 fragmentSource;
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_ci	for (;;)
931e5c31af7Sopenharmony_ci	{
932e5c31af7Sopenharmony_ci		if (m_curToken == TOKEN_END)
933e5c31af7Sopenharmony_ci			break;
934e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_DESC)
935e5c31af7Sopenharmony_ci		{
936e5c31af7Sopenharmony_ci			advanceToken();
937e5c31af7Sopenharmony_ci			assumeToken(TOKEN_STRING);
938e5c31af7Sopenharmony_ci
939e5c31af7Sopenharmony_ci			description = parseStringLiteral(m_curTokenStr.c_str());
940e5c31af7Sopenharmony_ci			advanceToken();
941e5c31af7Sopenharmony_ci		}
942e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_EXPECT)
943e5c31af7Sopenharmony_ci		{
944e5c31af7Sopenharmony_ci			advanceToken();
945e5c31af7Sopenharmony_ci			assumeToken(TOKEN_IDENTIFIER);
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_ci			if (m_curTokenStr == "pass")
948e5c31af7Sopenharmony_ci				expectResult = ShaderCase::EXPECT_PASS;
949e5c31af7Sopenharmony_ci			else if (m_curTokenStr == "compile_fail")
950e5c31af7Sopenharmony_ci				expectResult = ShaderCase::EXPECT_COMPILE_FAIL;
951e5c31af7Sopenharmony_ci			else if (m_curTokenStr == "link_fail")
952e5c31af7Sopenharmony_ci				expectResult = ShaderCase::EXPECT_LINK_FAIL;
953e5c31af7Sopenharmony_ci			else
954e5c31af7Sopenharmony_ci				parseError(string("invalid expected result value: " + m_curTokenStr));
955e5c31af7Sopenharmony_ci
956e5c31af7Sopenharmony_ci			advanceToken();
957e5c31af7Sopenharmony_ci		}
958e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_VALUES)
959e5c31af7Sopenharmony_ci		{
960e5c31af7Sopenharmony_ci			ShaderCase::ValueBlock block;
961e5c31af7Sopenharmony_ci			parseValueBlock(block);
962e5c31af7Sopenharmony_ci			valueBlockList.push_back(block);
963e5c31af7Sopenharmony_ci		}
964e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_BOTH || m_curToken == TOKEN_VERTEX || m_curToken == TOKEN_FRAGMENT)
965e5c31af7Sopenharmony_ci		{
966e5c31af7Sopenharmony_ci			Token token = m_curToken;
967e5c31af7Sopenharmony_ci			advanceToken();
968e5c31af7Sopenharmony_ci			assumeToken(TOKEN_SHADER_SOURCE);
969e5c31af7Sopenharmony_ci			string source = parseShaderSource(m_curTokenStr.c_str());
970e5c31af7Sopenharmony_ci			advanceToken();
971e5c31af7Sopenharmony_ci			switch (token)
972e5c31af7Sopenharmony_ci			{
973e5c31af7Sopenharmony_ci			case TOKEN_BOTH:
974e5c31af7Sopenharmony_ci				bothSource = source;
975e5c31af7Sopenharmony_ci				break;
976e5c31af7Sopenharmony_ci			case TOKEN_VERTEX:
977e5c31af7Sopenharmony_ci				vertexSource = source;
978e5c31af7Sopenharmony_ci				break;
979e5c31af7Sopenharmony_ci			case TOKEN_FRAGMENT:
980e5c31af7Sopenharmony_ci				fragmentSource = source;
981e5c31af7Sopenharmony_ci				break;
982e5c31af7Sopenharmony_ci			default:
983e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
984e5c31af7Sopenharmony_ci			}
985e5c31af7Sopenharmony_ci		}
986e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_VERSION)
987e5c31af7Sopenharmony_ci		{
988e5c31af7Sopenharmony_ci			advanceToken();
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_ci			int			versionNum = 0;
991e5c31af7Sopenharmony_ci			std::string postfix	= "";
992e5c31af7Sopenharmony_ci
993e5c31af7Sopenharmony_ci			assumeToken(TOKEN_INT_LITERAL);
994e5c31af7Sopenharmony_ci			versionNum = (int)parseIntLiteral(m_curTokenStr.c_str());
995e5c31af7Sopenharmony_ci			advanceToken();
996e5c31af7Sopenharmony_ci
997e5c31af7Sopenharmony_ci			if (m_curToken == TOKEN_IDENTIFIER)
998e5c31af7Sopenharmony_ci			{
999e5c31af7Sopenharmony_ci				postfix = m_curTokenStr;
1000e5c31af7Sopenharmony_ci				advanceToken();
1001e5c31af7Sopenharmony_ci			}
1002e5c31af7Sopenharmony_ci
1003e5c31af7Sopenharmony_ci			if (versionNum == 100 && postfix == "es")
1004e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_100_ES;
1005e5c31af7Sopenharmony_ci			else if (versionNum == 300 && postfix == "es")
1006e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_300_ES;
1007e5c31af7Sopenharmony_ci			else if (versionNum == 310 && postfix == "es")
1008e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_310_ES;
1009e5c31af7Sopenharmony_ci			else if (versionNum == 130)
1010e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_130;
1011e5c31af7Sopenharmony_ci			else if (versionNum == 140)
1012e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_140;
1013e5c31af7Sopenharmony_ci			else if (versionNum == 150)
1014e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_150;
1015e5c31af7Sopenharmony_ci			else if (versionNum == 330)
1016e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_330;
1017e5c31af7Sopenharmony_ci			else if (versionNum == 400)
1018e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_400;
1019e5c31af7Sopenharmony_ci			else if (versionNum == 410)
1020e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_410;
1021e5c31af7Sopenharmony_ci			else if (versionNum == 420)
1022e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_420;
1023e5c31af7Sopenharmony_ci			else if (versionNum == 430)
1024e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_430;
1025e5c31af7Sopenharmony_ci			else if (versionNum == 440)
1026e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_440;
1027e5c31af7Sopenharmony_ci			else if (versionNum == 450)
1028e5c31af7Sopenharmony_ci				version = glu::GLSL_VERSION_450;
1029e5c31af7Sopenharmony_ci			else
1030e5c31af7Sopenharmony_ci				parseError("Unknown GLSL version");
1031e5c31af7Sopenharmony_ci		}
1032e5c31af7Sopenharmony_ci		else
1033e5c31af7Sopenharmony_ci			parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
1034e5c31af7Sopenharmony_ci	}
1035e5c31af7Sopenharmony_ci
1036e5c31af7Sopenharmony_ci	advanceToken(TOKEN_END); // case end
1037e5c31af7Sopenharmony_ci
1038e5c31af7Sopenharmony_ci	if (bothSource.length() > 0)
1039e5c31af7Sopenharmony_ci	{
1040e5c31af7Sopenharmony_ci		DE_ASSERT(vertexSource.length() == 0);
1041e5c31af7Sopenharmony_ci		DE_ASSERT(fragmentSource.length() == 0);
1042e5c31af7Sopenharmony_ci
1043e5c31af7Sopenharmony_ci		string vertName = caseName + "_vertex";
1044e5c31af7Sopenharmony_ci		string fragName = caseName + "_fragment";
1045e5c31af7Sopenharmony_ci		shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, vertName.c_str(), description.c_str(),
1046e5c31af7Sopenharmony_ci												expectResult, valueBlockList, version, bothSource.c_str(), DE_NULL));
1047e5c31af7Sopenharmony_ci		shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, fragName.c_str(), description.c_str(),
1048e5c31af7Sopenharmony_ci												expectResult, valueBlockList, version, DE_NULL, bothSource.c_str()));
1049e5c31af7Sopenharmony_ci	}
1050e5c31af7Sopenharmony_ci	else
1051e5c31af7Sopenharmony_ci	{
1052e5c31af7Sopenharmony_ci		shaderNodeList.push_back(new ShaderCase(m_testCtx, m_renderCtx, caseName.c_str(), description.c_str(),
1053e5c31af7Sopenharmony_ci												expectResult, valueBlockList, version, vertexSource.c_str(),
1054e5c31af7Sopenharmony_ci												fragmentSource.c_str()));
1055e5c31af7Sopenharmony_ci	}
1056e5c31af7Sopenharmony_ci}
1057e5c31af7Sopenharmony_ci
1058e5c31af7Sopenharmony_civoid ShaderParser::parseShaderGroup(vector<tcu::TestNode*>& shaderNodeList)
1059e5c31af7Sopenharmony_ci{
1060e5c31af7Sopenharmony_ci	// Parse 'case'.
1061e5c31af7Sopenharmony_ci	PARSE_DBG(("  parseShaderGroup()\n"));
1062e5c31af7Sopenharmony_ci	advanceToken(TOKEN_GROUP);
1063e5c31af7Sopenharmony_ci
1064e5c31af7Sopenharmony_ci	// Parse case name.
1065e5c31af7Sopenharmony_ci	string name = m_curTokenStr;
1066e5c31af7Sopenharmony_ci	advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
1067e5c31af7Sopenharmony_ci
1068e5c31af7Sopenharmony_ci	// Parse description.
1069e5c31af7Sopenharmony_ci	assumeToken(TOKEN_STRING);
1070e5c31af7Sopenharmony_ci	string description = parseStringLiteral(m_curTokenStr.c_str());
1071e5c31af7Sopenharmony_ci	advanceToken(TOKEN_STRING);
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ci	std::vector<tcu::TestNode*> children;
1074e5c31af7Sopenharmony_ci
1075e5c31af7Sopenharmony_ci	// Parse group children.
1076e5c31af7Sopenharmony_ci	for (;;)
1077e5c31af7Sopenharmony_ci	{
1078e5c31af7Sopenharmony_ci		if (m_curToken == TOKEN_END)
1079e5c31af7Sopenharmony_ci			break;
1080e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_GROUP)
1081e5c31af7Sopenharmony_ci			parseShaderGroup(children);
1082e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_CASE)
1083e5c31af7Sopenharmony_ci			parseShaderCase(children);
1084e5c31af7Sopenharmony_ci		else
1085e5c31af7Sopenharmony_ci			parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
1086e5c31af7Sopenharmony_ci	}
1087e5c31af7Sopenharmony_ci
1088e5c31af7Sopenharmony_ci	advanceToken(TOKEN_END); // group end
1089e5c31af7Sopenharmony_ci
1090e5c31af7Sopenharmony_ci	// Create group node.
1091e5c31af7Sopenharmony_ci	tcu::TestCaseGroup* groupNode = new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1092e5c31af7Sopenharmony_ci	shaderNodeList.push_back(groupNode);
1093e5c31af7Sopenharmony_ci}
1094e5c31af7Sopenharmony_ci
1095e5c31af7Sopenharmony_civector<tcu::TestNode*> ShaderParser::parse(const char* input)
1096e5c31af7Sopenharmony_ci{
1097e5c31af7Sopenharmony_ci	// Initialize parser.
1098e5c31af7Sopenharmony_ci	m_input		  = input;
1099e5c31af7Sopenharmony_ci	m_curPtr	  = m_input.c_str();
1100e5c31af7Sopenharmony_ci	m_curToken	= TOKEN_INVALID;
1101e5c31af7Sopenharmony_ci	m_curTokenStr = "";
1102e5c31af7Sopenharmony_ci	advanceToken();
1103e5c31af7Sopenharmony_ci
1104e5c31af7Sopenharmony_ci	vector<tcu::TestNode*> nodeList;
1105e5c31af7Sopenharmony_ci
1106e5c31af7Sopenharmony_ci	// Parse all cases.
1107e5c31af7Sopenharmony_ci	PARSE_DBG(("parse()\n"));
1108e5c31af7Sopenharmony_ci	for (;;)
1109e5c31af7Sopenharmony_ci	{
1110e5c31af7Sopenharmony_ci		if (m_curToken == TOKEN_CASE)
1111e5c31af7Sopenharmony_ci			parseShaderCase(nodeList);
1112e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_GROUP)
1113e5c31af7Sopenharmony_ci			parseShaderGroup(nodeList);
1114e5c31af7Sopenharmony_ci		else if (m_curToken == TOKEN_EOF)
1115e5c31af7Sopenharmony_ci			break;
1116e5c31af7Sopenharmony_ci		else
1117e5c31af7Sopenharmony_ci			parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
1118e5c31af7Sopenharmony_ci	}
1119e5c31af7Sopenharmony_ci
1120e5c31af7Sopenharmony_ci	assumeToken(TOKEN_EOF);
1121e5c31af7Sopenharmony_ci	//  printf("  parsed %d test cases.\n", caseList.size());
1122e5c31af7Sopenharmony_ci	return nodeList;
1123e5c31af7Sopenharmony_ci}
1124e5c31af7Sopenharmony_ci
1125e5c31af7Sopenharmony_ci} // sl
1126e5c31af7Sopenharmony_ci
1127e5c31af7Sopenharmony_ciShaderLibrary::ShaderLibrary(tcu::TestContext& testCtx, RenderContext& renderCtx)
1128e5c31af7Sopenharmony_ci	: m_testCtx(testCtx), m_renderCtx(renderCtx)
1129e5c31af7Sopenharmony_ci{
1130e5c31af7Sopenharmony_ci}
1131e5c31af7Sopenharmony_ci
1132e5c31af7Sopenharmony_ciShaderLibrary::~ShaderLibrary(void)
1133e5c31af7Sopenharmony_ci{
1134e5c31af7Sopenharmony_ci}
1135e5c31af7Sopenharmony_ci
1136e5c31af7Sopenharmony_civector<tcu::TestNode*> ShaderLibrary::loadShaderFile(const char* fileName)
1137e5c31af7Sopenharmony_ci{
1138e5c31af7Sopenharmony_ci	tcu::Resource*	resource = m_testCtx.getArchive().getResource(fileName);
1139e5c31af7Sopenharmony_ci	std::vector<char> buf;
1140e5c31af7Sopenharmony_ci
1141e5c31af7Sopenharmony_ci	/*  printf("  loading '%s'\n", fileName);*/
1142e5c31af7Sopenharmony_ci
1143e5c31af7Sopenharmony_ci	try
1144e5c31af7Sopenharmony_ci	{
1145e5c31af7Sopenharmony_ci		int size = resource->getSize();
1146e5c31af7Sopenharmony_ci		buf.resize(size + 1);
1147e5c31af7Sopenharmony_ci		resource->read((deUint8*)&buf[0], size);
1148e5c31af7Sopenharmony_ci		buf[size] = '\0';
1149e5c31af7Sopenharmony_ci	}
1150e5c31af7Sopenharmony_ci	catch (const std::exception&)
1151e5c31af7Sopenharmony_ci	{
1152e5c31af7Sopenharmony_ci		delete resource;
1153e5c31af7Sopenharmony_ci		throw;
1154e5c31af7Sopenharmony_ci	}
1155e5c31af7Sopenharmony_ci
1156e5c31af7Sopenharmony_ci	delete resource;
1157e5c31af7Sopenharmony_ci
1158e5c31af7Sopenharmony_ci	sl::ShaderParser	   parser(m_testCtx, m_renderCtx);
1159e5c31af7Sopenharmony_ci	vector<tcu::TestNode*> nodes = parser.parse(&buf[0]);
1160e5c31af7Sopenharmony_ci
1161e5c31af7Sopenharmony_ci	return nodes;
1162e5c31af7Sopenharmony_ci}
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ci// ShaderLibraryGroup
1165e5c31af7Sopenharmony_ci
1166e5c31af7Sopenharmony_ciShaderLibraryGroup::ShaderLibraryGroup(Context& context, const char* name, const char* description,
1167e5c31af7Sopenharmony_ci									   const char* filename)
1168e5c31af7Sopenharmony_ci	: TestCaseGroup(context, name, description), m_filename(filename)
1169e5c31af7Sopenharmony_ci{
1170e5c31af7Sopenharmony_ci}
1171e5c31af7Sopenharmony_ci
1172e5c31af7Sopenharmony_ciShaderLibraryGroup::~ShaderLibraryGroup(void)
1173e5c31af7Sopenharmony_ci{
1174e5c31af7Sopenharmony_ci}
1175e5c31af7Sopenharmony_ci
1176e5c31af7Sopenharmony_civoid ShaderLibraryGroup::init(void)
1177e5c31af7Sopenharmony_ci{
1178e5c31af7Sopenharmony_ci	deqp::ShaderLibrary			shaderLibrary(m_testCtx, m_context.getRenderContext());
1179e5c31af7Sopenharmony_ci	std::vector<tcu::TestNode*> children = shaderLibrary.loadShaderFile(m_filename.c_str());
1180e5c31af7Sopenharmony_ci
1181e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)children.size(); i++)
1182e5c31af7Sopenharmony_ci		addChild(children[i]);
1183e5c31af7Sopenharmony_ci}
1184e5c31af7Sopenharmony_ci
1185e5c31af7Sopenharmony_ci} // deqp
1186