Home | History | Annotate | Download | only in randomshaders
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Random Shader Generator
      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 Shader Source Formatter.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "rsgPrettyPrinter.hpp"
     25 #include "deStringUtil.hpp"
     26 
     27 namespace rsg
     28 {
     29 
     30 static const char* s_tokenStr[] =
     31 {
     32 	DE_NULL,		// IDENTIFIER,
     33 	"struct",		// STRUCT,
     34 	"invariant",	// INVARIANT,
     35 	"precision",	// PRECISION,
     36 	"void",			// VOID,
     37 	"break",		// BREAK,
     38 	"continue",		// CONTINUE,
     39 	"do ",			// DO,
     40 	"while ",		// WHILE,
     41 	"else ",		// ELSE,
     42 	"for ",			// FOR,
     43 	"if ",			// IF,
     44 	"discard",		// DISCARD,
     45 	"return ",		// RETURN,
     46 	"++",			// INC_OP,
     47 	"--",			// DEC_OP,
     48 	"(",			// LEFT_PAREN,
     49 	")",			// RIGHT_PAREN,
     50 	"[",			// LEFT_BRACKET,
     51 	"]",			// RIGHT_BRACKET,
     52 	"{",			// LEFT_BRACE,
     53 	"}",			// RIGHT_BRACE,
     54 	".",			// DOT,
     55 	", ",			// COMMA,
     56 	" : ",			// COLON,
     57 	";",			// SEMICOLON,
     58 	" - ",			// MINUS,
     59 	" + ",			// PLUS,
     60 	" * ",			// MUL,
     61 	" / ",			// DIV,
     62 	" % ",			// MOD,
     63 	" ? ",			// QUESTION,
     64 	"bool",			// BOOL,
     65 	"bvec2",		// BVEC2,
     66 	"bvec3",		// BVEC3,
     67 	"bvec4",		// BVEC4,
     68 	"int",			// INT,
     69 	"ivec2",		// IVEC2,
     70 	"ivec3",		// IVEC3,
     71 	"ivec4",		// IVEC4,
     72 	"float",		// FLOAT,
     73 	"vec2",			// VEC2,
     74 	"vec3",			// VEC3,
     75 	"vec4",			// VEC4,
     76 	"mat2",			// MAT2,
     77 	"mat3",			// MAT3,
     78 	"mat4",			// MAT4,
     79 	"sampler2D",	// SAMPLER2D,
     80 	"samplerCube",	// SAMPLERCUBE,
     81 	DE_NULL,		// FLOAT_LITERAL,
     82 	DE_NULL,		// INT_LITERAL,
     83 	DE_NULL,		// BOOL_LITERAL,
     84 	" = ",			// EQUAL,
     85 	" *= ",			// MUL_ASSIGN,
     86 	" /= ",			// DIV_ASSIGN,
     87 	" += ",			// ADD_ASSIGN,
     88 	" -= ",			// SUB_ASSIGN,
     89 	" < ",			// CMP_LT,
     90 	" > ",			// CMP_GT,
     91 	" <= ",			// CMP_LE,
     92 	" >= ",			// CMP_GE,
     93 	" == ",			// CMP_EQ,
     94 	" != ",			// CMP_NE,
     95 	" && ",			// LOGICAL_AND,
     96 	" || ",			// LOGICAL_OR,
     97 	"!",			// LOGICAL_NOT,
     98 	" ^^ ",			// LOGICAL_XOR,
     99 	"attribute",	// ATTRIBUTE,
    100 	"uniform",		// UNIFORM,
    101 	"varying",		// VARYING,
    102 	"const",		// CONST,
    103 	"flat",			// FLAT,
    104 	"highp",		// HIGH_PRECISION,
    105 	"mediump",		// MEDIUM_PRECISION,
    106 	"lowp",			// LOW_PRECISION,
    107 	"in",			// IN,
    108 	"out",			// OUT,
    109 	"inout",		// INOUT,
    110 	"layout",		// LAYOUT,
    111 	"location",		// LOCATION,
    112 	DE_NULL,		// INDENT_INC,
    113 	DE_NULL,		// INDENT_DEC,
    114 	"\n"			// NEWLINE,
    115 };
    116 
    117 PrettyPrinter::PrettyPrinter (std::ostringstream& str)
    118 	: m_str			(str)
    119 	, m_indentDepth	(0)
    120 {
    121 }
    122 
    123 inline const char* PrettyPrinter::getSimpleTokenStr (Token::Type token)
    124 {
    125 	DE_ASSERT(de::inBounds<int>(token, 0, (int)DE_LENGTH_OF_ARRAY(s_tokenStr)));
    126 	return s_tokenStr[token];
    127 }
    128 
    129 void PrettyPrinter::append (const TokenStream& tokens)
    130 {
    131 	for (int ndx = 0; ndx < tokens.getSize(); ndx++)
    132 		processToken(tokens[ndx]);
    133 }
    134 
    135 inline bool isIdentifierChar (char c)
    136 {
    137 	return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z') || de::inRange(c, '0', '9') || c == '_';
    138 }
    139 
    140 void PrettyPrinter::processToken (const Token& token)
    141 {
    142 	bool prevIsIdentifierChar = m_line.length() > 0 && isIdentifierChar(m_line[m_line.length()-1]);
    143 
    144 	switch (token.getType())
    145 	{
    146 		case Token::IDENTIFIER:
    147 			if (prevIsIdentifierChar)
    148 				m_line += " ";
    149 			m_line += token.getIdentifier();
    150 			break;
    151 
    152 		case Token::FLOAT_LITERAL:
    153 		{
    154 			std::string f = de::toString(token.getFloat());
    155 			if (f.find('.') == std::string::npos)
    156 				f += ".0"; // Make sure value parses as float
    157 			m_line += f;
    158 			break;
    159 		}
    160 
    161 		case Token::INT_LITERAL:
    162 			m_line += de::toString(token.getInt());
    163 			break;
    164 
    165 		case Token::BOOL_LITERAL:
    166 			m_line += (token.getBool() ? "true" : "false");
    167 			break;
    168 
    169 		case Token::INDENT_INC:
    170 			m_indentDepth += 1;
    171 			break;
    172 
    173 		case Token::INDENT_DEC:
    174 			m_indentDepth -= 1;
    175 			break;
    176 
    177 		case Token::NEWLINE:
    178 			// Indent
    179 			for (int i = 0; i < m_indentDepth; i++)
    180 				m_str << "\t";
    181 
    182 			// Flush line to source
    183 			m_str << m_line + "\n";
    184 			m_line = "";
    185 			break;
    186 
    187 		default:
    188 		{
    189 			const char* tokenStr = getSimpleTokenStr(token.getType());
    190 			if (prevIsIdentifierChar && isIdentifierChar(tokenStr[0]))
    191 				m_line += " ";
    192 			m_line += tokenStr;
    193 			break;
    194 		}
    195 	}
    196 }
    197 
    198 } // rsg
    199