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