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