1 /* 2 * Copyright 2021 Google LLC. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_DSLPARSER 9 #define SKSL_DSLPARSER 10 11 #include "include/private/SkSLProgramKind.h" 12 #include "include/sksl/DSL.h" 13 #include "include/sksl/DSLSymbols.h" 14 #include "src/sksl/SkSLLexer.h" 15 #include "src/sksl/ir/SkSLProgram.h" 16 17 #include <memory> 18 #include <optional> 19 #include <string_view> 20 #include <unordered_map> 21 22 namespace SkSL { 23 24 class ErrorReporter; 25 struct Modifiers; 26 struct ParsedModule; 27 class SymbolTable; 28 29 /** 30 * Consumes .sksl text and invokes DSL functions to instantiate the program. 31 */ 32 class DSLParser { 33 public: 34 enum class LayoutToken { 35 LOCATION, 36 OFFSET, 37 BINDING, 38 INDEX, 39 SET, 40 BUILTIN, 41 INPUT_ATTACHMENT_INDEX, 42 ORIGIN_UPPER_LEFT, 43 BLEND_SUPPORT_ALL_EQUATIONS, 44 PUSH_CONSTANT, 45 COLOR, 46 }; 47 48 DSLParser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind, 49 std::string text); 50 51 std::unique_ptr<Program> program(); 52 53 SkSL::LoadedModule moduleInheritingFrom(SkSL::ParsedModule baseModule); 54 55 std::string_view text(Token token); 56 57 PositionInfo position(Token token); 58 59 PositionInfo position(int line); 60 61 private: 62 static void InitLayoutMap(); 63 64 /** 65 * Return the next token, including whitespace tokens, from the parse stream. 66 */ 67 Token nextRawToken(); 68 69 /** 70 * Return the next non-whitespace token from the parse stream. 71 */ 72 Token nextToken(); 73 74 /** 75 * Push a token back onto the parse stream, so that it is the next one read. Only a single level 76 * of pushback is supported (that is, it is an error to call pushback() twice in a row without 77 * an intervening nextToken()). 78 */ 79 void pushback(Token t); 80 81 /** 82 * Returns the next non-whitespace token without consuming it from the stream. 83 */ 84 Token peek(); 85 86 /** 87 * Checks to see if the next token is of the specified type. If so, stores it in result (if 88 * result is non-null) and returns true. Otherwise, pushes it back and returns false. 89 */ 90 bool checkNext(Token::Kind kind, Token* result = nullptr); 91 92 /** 93 * Behaves like checkNext(TK_IDENTIFIER), but also verifies that identifier is not a builtin 94 * type. If the token was actually a builtin type, false is returned (the next token is not 95 * considered to be an identifier). 96 */ 97 bool checkIdentifier(Token* result = nullptr); 98 99 /** 100 * Reads the next non-whitespace token and generates an error if it is not the expected type. 101 * The 'expected' string is part of the error message, which reads: 102 * 103 * "expected <expected>, but found '<actual text>'" 104 * 105 * If 'result' is non-null, it is set to point to the token that was read. 106 * Returns true if the read token was as expected, false otherwise. 107 */ 108 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr); 109 bool expect(Token::Kind kind, std::string expected, Token* result = nullptr); 110 111 /** 112 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type. 113 * If the token was actually a type, generates an error message of the form: 114 * 115 * "expected an identifier, but found type 'float2'" 116 */ 117 bool expectIdentifier(Token* result); 118 119 void error(Token token, std::string msg); 120 void error(int line, std::string msg); 121 122 // these functions parse individual grammar rules from the current parse position; you probably 123 // don't need to call any of these outside of the parser. The function declarations in the .cpp 124 // file have comments describing the grammar rules. 125 126 void declarations(); 127 128 SKSL_INT arraySize(); 129 130 void directive(); 131 132 bool declaration(); 133 134 bool functionDeclarationEnd(const dsl::DSLModifiers& modifiers, 135 dsl::DSLType type, 136 const Token& name); 137 138 struct VarDeclarationsPrefix { 139 PositionInfo fPosition; 140 dsl::DSLModifiers fModifiers; 141 dsl::DSLType fType = dsl::DSLType(dsl::kVoid_Type); 142 Token fName; 143 }; 144 145 bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData); 146 147 dsl::DSLStatement varDeclarationsOrExpressionStatement(); 148 149 dsl::DSLStatement varDeclarations(); 150 151 std::optional<dsl::DSLType> structDeclaration(); 152 153 SkTArray<dsl::DSLGlobalVar> structVarDeclaration(const dsl::DSLModifiers& modifiers); 154 155 bool parseArrayDimensions(int line, dsl::DSLType* type); 156 157 bool parseInitializer(int line, dsl::DSLExpression* initializer); 158 159 void globalVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods, 160 dsl::DSLType baseType, std::string_view name); 161 162 dsl::DSLStatement localVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods, 163 dsl::DSLType baseType, std::string_view name); 164 165 std::optional<dsl::DSLWrapper<dsl::DSLParameter>> parameter(size_t paramIndex); 166 167 int layoutInt(); 168 169 std::string_view layoutIdentifier(); 170 171 dsl::DSLLayout layout(); 172 173 dsl::DSLModifiers modifiers(); 174 175 dsl::DSLStatement statement(); 176 177 std::optional<dsl::DSLType> type(dsl::DSLModifiers* modifiers); 178 179 bool interfaceBlock(const dsl::DSLModifiers& mods); 180 181 dsl::DSLStatement ifStatement(); 182 183 dsl::DSLStatement doStatement(); 184 185 dsl::DSLStatement whileStatement(); 186 187 dsl::DSLStatement forStatement(); 188 189 std::optional<dsl::DSLCase> switchCase(); 190 191 dsl::DSLStatement switchStatement(); 192 193 dsl::DSLStatement returnStatement(); 194 195 dsl::DSLStatement breakStatement(); 196 197 dsl::DSLStatement continueStatement(); 198 199 dsl::DSLStatement discardStatement(); 200 201 std::optional<dsl::DSLBlock> block(); 202 203 dsl::DSLStatement expressionStatement(); 204 205 dsl::DSLExpression expression(); 206 207 dsl::DSLExpression assignmentExpression(); 208 209 dsl::DSLExpression ternaryExpression(); 210 211 dsl::DSLExpression logicalOrExpression(); 212 213 dsl::DSLExpression logicalXorExpression(); 214 215 dsl::DSLExpression logicalAndExpression(); 216 217 dsl::DSLExpression bitwiseOrExpression(); 218 219 dsl::DSLExpression bitwiseXorExpression(); 220 221 dsl::DSLExpression bitwiseAndExpression(); 222 223 dsl::DSLExpression equalityExpression(); 224 225 dsl::DSLExpression relationalExpression(); 226 227 dsl::DSLExpression shiftExpression(); 228 229 dsl::DSLExpression additiveExpression(); 230 231 dsl::DSLExpression multiplicativeExpression(); 232 233 dsl::DSLExpression unaryExpression(); 234 235 dsl::DSLExpression postfixExpression(); 236 237 dsl::DSLExpression swizzle(int line, dsl::DSLExpression base, std::string_view swizzleMask); 238 239 dsl::DSLExpression call(int line, dsl::DSLExpression base, ExpressionArray args); 240 241 dsl::DSLExpression suffix(dsl::DSLExpression base); 242 243 dsl::DSLExpression term(); 244 245 bool intLiteral(SKSL_INT* dest); 246 247 bool floatLiteral(SKSL_FLOAT* dest); 248 249 bool boolLiteral(bool* dest); 250 251 bool identifier(std::string_view* dest); 252 253 class Checkpoint { 254 public: Checkpoint(DSLParser * p)255 Checkpoint(DSLParser* p) : fParser(p) { 256 fPushbackCheckpoint = fParser->fPushback; 257 fLexerCheckpoint = fParser->fLexer.getCheckpoint(); 258 fOldErrorReporter = &dsl::GetErrorReporter(); 259 fOldEncounteredFatalError = fParser->fEncounteredFatalError; 260 SkASSERT(fOldErrorReporter); 261 dsl::SetErrorReporter(&fErrorReporter); 262 } 263 ~Checkpoint()264 ~Checkpoint() { 265 SkASSERTF(!fOldErrorReporter, 266 "Checkpoint was not accepted or rewound before destruction"); 267 } 268 accept()269 void accept() { 270 this->restoreErrorReporter(); 271 // Parser errors should have been fatal, but we can encounter other errors like type 272 // mismatches despite accepting the parse. Forward those messages to the actual error 273 // handler now. 274 fErrorReporter.forwardErrors(); 275 } 276 rewind()277 void rewind() { 278 this->restoreErrorReporter(); 279 fParser->fPushback = fPushbackCheckpoint; 280 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint); 281 fParser->fEncounteredFatalError = fOldEncounteredFatalError; 282 } 283 284 private: 285 class ForwardingErrorReporter : public ErrorReporter { 286 public: handleError(std::string_view msg,PositionInfo pos)287 void handleError(std::string_view msg, PositionInfo pos) override { 288 fErrors.push_back({std::string(msg), pos}); 289 } 290 forwardErrors()291 void forwardErrors() { 292 for (Error& error : fErrors) { 293 dsl::GetErrorReporter().error(error.fMsg.c_str(), error.fPos); 294 } 295 } 296 297 private: 298 struct Error { 299 std::string fMsg; 300 PositionInfo fPos; 301 }; 302 303 SkTArray<Error> fErrors; 304 }; 305 restoreErrorReporter()306 void restoreErrorReporter() { 307 SkASSERT(fOldErrorReporter); 308 fErrorReporter.reportPendingErrors(PositionInfo()); 309 dsl::SetErrorReporter(fOldErrorReporter); 310 fOldErrorReporter = nullptr; 311 } 312 313 DSLParser* fParser; 314 Token fPushbackCheckpoint; 315 SkSL::Lexer::Checkpoint fLexerCheckpoint; 316 ForwardingErrorReporter fErrorReporter; 317 ErrorReporter* fOldErrorReporter; 318 bool fOldEncounteredFatalError; 319 }; 320 321 static std::unordered_map<std::string_view, LayoutToken>* layoutTokens; 322 323 Compiler& fCompiler; 324 ProgramSettings fSettings; 325 ErrorReporter* fErrorReporter; 326 bool fEncounteredFatalError; 327 ProgramKind fKind; 328 std::unique_ptr<std::string> fText; 329 Lexer fLexer; 330 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the 331 // stack on pathological inputs 332 int fDepth = 0; 333 Token fPushback; 334 335 friend class AutoDSLDepth; 336 friend class HCodeGenerator; 337 }; 338 339 } // namespace SkSL 340 341 #endif 342