Add CTS_ARB_gl_spirv test implementation
[platform/upstream/VK-GL-CTS.git] / framework / randomshaders / rsgPrettyPrinter.cpp
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