You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.6 KiB
198 lines
4.6 KiB
/*------------------------------------------------------------------------- |
|
* drawElements Quality Program Random Shader Generator |
|
* ---------------------------------------------------- |
|
* |
|
* Copyright 2014 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*//*! |
|
* \file |
|
* \brief Shader Source Formatter. |
|
*//*--------------------------------------------------------------------*/ |
|
|
|
#include "rsgPrettyPrinter.hpp" |
|
#include "deStringUtil.hpp" |
|
|
|
namespace rsg |
|
{ |
|
|
|
static const char* s_tokenStr[] = |
|
{ |
|
DE_NULL, // IDENTIFIER, |
|
"struct", // STRUCT, |
|
"invariant", // INVARIANT, |
|
"precision", // PRECISION, |
|
"void", // VOID, |
|
"break", // BREAK, |
|
"continue", // CONTINUE, |
|
"do ", // DO, |
|
"while ", // WHILE, |
|
"else ", // ELSE, |
|
"for ", // FOR, |
|
"if ", // IF, |
|
"discard", // DISCARD, |
|
"return ", // RETURN, |
|
"++", // INC_OP, |
|
"--", // DEC_OP, |
|
"(", // LEFT_PAREN, |
|
")", // RIGHT_PAREN, |
|
"[", // LEFT_BRACKET, |
|
"]", // RIGHT_BRACKET, |
|
"{", // LEFT_BRACE, |
|
"}", // RIGHT_BRACE, |
|
".", // DOT, |
|
", ", // COMMA, |
|
" : ", // COLON, |
|
";", // SEMICOLON, |
|
" - ", // MINUS, |
|
" + ", // PLUS, |
|
" * ", // MUL, |
|
" / ", // DIV, |
|
" % ", // MOD, |
|
" ? ", // QUESTION, |
|
"bool", // BOOL, |
|
"bvec2", // BVEC2, |
|
"bvec3", // BVEC3, |
|
"bvec4", // BVEC4, |
|
"int", // INT, |
|
"ivec2", // IVEC2, |
|
"ivec3", // IVEC3, |
|
"ivec4", // IVEC4, |
|
"float", // FLOAT, |
|
"vec2", // VEC2, |
|
"vec3", // VEC3, |
|
"vec4", // VEC4, |
|
"mat2", // MAT2, |
|
"mat3", // MAT3, |
|
"mat4", // MAT4, |
|
"sampler2D", // SAMPLER2D, |
|
"samplerCube", // SAMPLERCUBE, |
|
DE_NULL, // FLOAT_LITERAL, |
|
DE_NULL, // INT_LITERAL, |
|
DE_NULL, // BOOL_LITERAL, |
|
" = ", // EQUAL, |
|
" *= ", // MUL_ASSIGN, |
|
" /= ", // DIV_ASSIGN, |
|
" += ", // ADD_ASSIGN, |
|
" -= ", // SUB_ASSIGN, |
|
" < ", // CMP_LT, |
|
" > ", // CMP_GT, |
|
" <= ", // CMP_LE, |
|
" >= ", // CMP_GE, |
|
" == ", // CMP_EQ, |
|
" != ", // CMP_NE, |
|
" && ", // LOGICAL_AND, |
|
" || ", // LOGICAL_OR, |
|
"!", // LOGICAL_NOT, |
|
" ^^ ", // LOGICAL_XOR, |
|
"attribute", // ATTRIBUTE, |
|
"uniform", // UNIFORM, |
|
"varying", // VARYING, |
|
"const", // CONST, |
|
"flat", // FLAT, |
|
"highp", // HIGH_PRECISION, |
|
"mediump", // MEDIUM_PRECISION, |
|
"lowp", // LOW_PRECISION, |
|
"in", // IN, |
|
"out", // OUT, |
|
"inout", // INOUT, |
|
"layout", // LAYOUT, |
|
"location", // LOCATION, |
|
DE_NULL, // INDENT_INC, |
|
DE_NULL, // INDENT_DEC, |
|
"\n" // NEWLINE, |
|
}; |
|
|
|
PrettyPrinter::PrettyPrinter (std::ostringstream& str) |
|
: m_str (str) |
|
, m_indentDepth (0) |
|
{ |
|
} |
|
|
|
inline const char* PrettyPrinter::getSimpleTokenStr (Token::Type token) |
|
{ |
|
DE_ASSERT(de::inBounds<int>(token, 0, (int)DE_LENGTH_OF_ARRAY(s_tokenStr))); |
|
return s_tokenStr[token]; |
|
} |
|
|
|
void PrettyPrinter::append (const TokenStream& tokens) |
|
{ |
|
for (int ndx = 0; ndx < tokens.getSize(); ndx++) |
|
processToken(tokens[ndx]); |
|
} |
|
|
|
inline bool isIdentifierChar (char c) |
|
{ |
|
return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z') || de::inRange(c, '0', '9') || c == '_'; |
|
} |
|
|
|
void PrettyPrinter::processToken (const Token& token) |
|
{ |
|
bool prevIsIdentifierChar = m_line.length() > 0 && isIdentifierChar(m_line[m_line.length()-1]); |
|
|
|
switch (token.getType()) |
|
{ |
|
case Token::IDENTIFIER: |
|
if (prevIsIdentifierChar) |
|
m_line += " "; |
|
m_line += token.getIdentifier(); |
|
break; |
|
|
|
case Token::FLOAT_LITERAL: |
|
{ |
|
std::string f = de::toString(token.getFloat()); |
|
if (f.find('.') == std::string::npos) |
|
f += ".0"; // Make sure value parses as float |
|
m_line += f; |
|
break; |
|
} |
|
|
|
case Token::INT_LITERAL: |
|
m_line += de::toString(token.getInt()); |
|
break; |
|
|
|
case Token::BOOL_LITERAL: |
|
m_line += (token.getBool() ? "true" : "false"); |
|
break; |
|
|
|
case Token::INDENT_INC: |
|
m_indentDepth += 1; |
|
break; |
|
|
|
case Token::INDENT_DEC: |
|
m_indentDepth -= 1; |
|
break; |
|
|
|
case Token::NEWLINE: |
|
// Indent |
|
for (int i = 0; i < m_indentDepth; i++) |
|
m_str << "\t"; |
|
|
|
// Flush line to source |
|
m_str << m_line + "\n"; |
|
m_line = ""; |
|
break; |
|
|
|
default: |
|
{ |
|
const char* tokenStr = getSimpleTokenStr(token.getType()); |
|
if (prevIsIdentifierChar && isIdentifierChar(tokenStr[0])) |
|
m_line += " "; |
|
m_line += tokenStr; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
} // rsg
|
|
|