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