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_PARSER 9 #define SKSL_PARSER 10 11 #include "include/core/SkTypes.h" 12 #include "include/private/SkSLDefines.h" 13 #include "include/private/base/SkTArray.h" 14 #include "include/sksl/DSLCore.h" 15 #include "include/sksl/DSLExpression.h" 16 #include "include/sksl/DSLLayout.h" 17 #include "include/sksl/DSLModifiers.h" 18 #include "include/sksl/DSLStatement.h" 19 #include "include/sksl/DSLType.h" 20 #include "include/sksl/SkSLErrorReporter.h" 21 #include "include/sksl/SkSLOperator.h" 22 #include "include/sksl/SkSLPosition.h" 23 #include "src/sksl/SkSLLexer.h" 24 #include "src/sksl/SkSLProgramSettings.h" 25 26 #include <cstddef> 27 #include <cstdint> 28 #include <memory> 29 #include <optional> 30 #include <string> 31 #include <string_view> 32 33 namespace SkSL { 34 35 class Compiler; 36 class SymbolTable; 37 enum class ProgramKind : int8_t; 38 struct Module; 39 struct Program; 40 41 namespace dsl { 42 class DSLBlock; 43 class DSLCase; 44 class DSLGlobalVar; 45 class DSLParameter; 46 class DSLVarBase; 47 } 48 49 /** 50 * Consumes .sksl text and invokes DSL functions to instantiate the program. 51 */ 52 class Parser { 53 public: 54 Parser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind, std::string text); 55 56 std::unique_ptr<Program> program(); 57 58 std::unique_ptr<Module> moduleInheritingFrom(const Module* parent); 59 60 std::string_view text(Token token); 61 62 Position position(Token token); 63 64 private: 65 class AutoDepth; 66 class AutoSymbolTable; 67 68 /** 69 * Return the next token, including whitespace tokens, from the parse stream. 70 */ 71 Token nextRawToken(); 72 73 /** 74 * Return the next non-whitespace token from the parse stream. 75 */ 76 Token nextToken(); 77 78 /** 79 * Push a token back onto the parse stream, so that it is the next one read. Only a single level 80 * of pushback is supported (that is, it is an error to call pushback() twice in a row without 81 * an intervening nextToken()). 82 */ 83 void pushback(Token t); 84 85 /** 86 * Returns the next non-whitespace token without consuming it from the stream. 87 */ 88 Token peek(); 89 90 /** 91 * Checks to see if the next token is of the specified type. If so, stores it in result (if 92 * result is non-null) and returns true. Otherwise, pushes it back and returns false. 93 */ 94 bool checkNext(Token::Kind kind, Token* result = nullptr); 95 96 /** 97 * Behaves like checkNext(TK_IDENTIFIER), but also verifies that identifier is not a builtin 98 * type. If the token was actually a builtin type, false is returned (the next token is not 99 * considered to be an identifier). 100 */ 101 bool checkIdentifier(Token* result = nullptr); 102 103 /** 104 * Reads the next non-whitespace token and generates an error if it is not the expected type. 105 * The 'expected' string is part of the error message, which reads: 106 * 107 * "expected <expected>, but found '<actual text>'" 108 * 109 * If 'result' is non-null, it is set to point to the token that was read. 110 * Returns true if the read token was as expected, false otherwise. 111 */ 112 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr); 113 bool expect(Token::Kind kind, std::string expected, Token* result = nullptr); 114 115 /** 116 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type. 117 * If the token was actually a type, generates an error message of the form: 118 * 119 * "expected an identifier, but found type 'float2'" 120 */ 121 bool expectIdentifier(Token* result); 122 123 /** If the next token is a newline, consumes it and returns true. If not, returns false. */ 124 bool expectNewline(); 125 126 void error(Token token, std::string_view msg); 127 void error(Position position, std::string_view msg); 128 129 // Returns the range from `start` to the current parse position. 130 Position rangeFrom(Position start); 131 Position rangeFrom(Token start); 132 133 // these functions parse individual grammar rules from the current parse position; you probably 134 // don't need to call any of these outside of the parser. The function declarations in the .cpp 135 // file have comments describing the grammar rules. 136 137 void declarations(); 138 139 /** 140 * Parses an expression representing an array size. Reports errors if the array size is not 141 * valid (out of bounds, not a literal integer). Returns true if an expression was 142 * successfully parsed, even if that array size is not actually valid. In the event of a true 143 * return, outResult always contains a valid array size (even if the parsed array size was not 144 * actually valid; invalid array sizes result in a 1 to avoid additional errors downstream). 145 */ 146 bool arraySize(SKSL_INT* outResult); 147 148 void directive(bool allowVersion); 149 150 bool declaration(); 151 152 bool functionDeclarationEnd(Position start, 153 dsl::DSLModifiers& modifiers, 154 dsl::DSLType type, 155 const Token& name); 156 157 struct VarDeclarationsPrefix { 158 Position 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 dsl::DSLType structDeclaration(); 171 172 SkTArray<dsl::DSLGlobalVar> structVarDeclaration(Position start, 173 const dsl::DSLModifiers& modifiers); 174 allowUnsizedArrays()175 bool allowUnsizedArrays() { 176 return ProgramConfig::IsCompute(fKind) || ProgramConfig::IsFragment(fKind) || 177 ProgramConfig::IsVertex(fKind); 178 } 179 180 bool parseArrayDimensions(Position pos, dsl::DSLType* type); 181 182 bool parseInitializer(Position pos, dsl::DSLExpression* initializer); 183 184 void globalVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods, 185 dsl::DSLType baseType, Token name); 186 187 dsl::DSLStatement localVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods, 188 dsl::DSLType baseType, Token name); 189 190 std::optional<dsl::DSLParameter> parameter(size_t paramIndex); 191 192 int layoutInt(); 193 194 std::string_view layoutIdentifier(); 195 196 dsl::DSLLayout layout(); 197 198 dsl::DSLModifiers modifiers(); 199 200 dsl::DSLStatement statement(); 201 202 dsl::DSLType type(dsl::DSLModifiers* modifiers); 203 204 bool interfaceBlock(const dsl::DSLModifiers& mods); 205 206 dsl::DSLStatement ifStatement(); 207 208 dsl::DSLStatement doStatement(); 209 210 dsl::DSLStatement whileStatement(); 211 212 dsl::DSLStatement forStatement(); 213 214 std::optional<dsl::DSLCase> switchCase(); 215 216 dsl::DSLStatement switchStatement(); 217 218 dsl::DSLStatement returnStatement(); 219 220 dsl::DSLStatement breakStatement(); 221 222 dsl::DSLStatement continueStatement(); 223 224 dsl::DSLStatement discardStatement(); 225 226 std::optional<dsl::DSLBlock> block(); 227 228 dsl::DSLStatement expressionStatement(); 229 230 using BinaryParseFn = dsl::DSLExpression (Parser::*)(); 231 bool SK_WARN_UNUSED_RESULT operatorRight(AutoDepth& depth, Operator::Kind op, 232 BinaryParseFn rightFn, dsl::DSLExpression& result); 233 234 dsl::DSLExpression expression(); 235 236 dsl::DSLExpression assignmentExpression(); 237 238 dsl::DSLExpression ternaryExpression(); 239 240 dsl::DSLExpression logicalOrExpression(); 241 242 dsl::DSLExpression logicalXorExpression(); 243 244 dsl::DSLExpression logicalAndExpression(); 245 246 dsl::DSLExpression bitwiseOrExpression(); 247 248 dsl::DSLExpression bitwiseXorExpression(); 249 250 dsl::DSLExpression bitwiseAndExpression(); 251 252 dsl::DSLExpression equalityExpression(); 253 254 dsl::DSLExpression relationalExpression(); 255 256 dsl::DSLExpression shiftExpression(); 257 258 dsl::DSLExpression additiveExpression(); 259 260 dsl::DSLExpression multiplicativeExpression(); 261 262 dsl::DSLExpression unaryExpression(); 263 264 dsl::DSLExpression postfixExpression(); 265 266 dsl::DSLExpression swizzle(Position pos, dsl::DSLExpression base, 267 std::string_view swizzleMask, Position maskPos); 268 269 dsl::DSLExpression call(Position pos, dsl::DSLExpression base, ExpressionArray args); 270 271 dsl::DSLExpression suffix(dsl::DSLExpression base); 272 273 dsl::DSLExpression term(); 274 275 bool intLiteral(SKSL_INT* dest); 276 277 bool floatLiteral(SKSL_FLOAT* dest); 278 279 bool boolLiteral(bool* dest); 280 281 bool identifier(std::string_view* dest); 282 283 std::shared_ptr<SymbolTable>& symbolTable(); 284 285 void addToSymbolTable(dsl::DSLVarBase& var, Position pos = {}); 286 287 class Checkpoint { 288 public: Checkpoint(Parser * p)289 Checkpoint(Parser* p) : fParser(p) { 290 fPushbackCheckpoint = fParser->fPushback; 291 fLexerCheckpoint = fParser->fLexer.getCheckpoint(); 292 fOldErrorReporter = &dsl::GetErrorReporter(); 293 fOldEncounteredFatalError = fParser->fEncounteredFatalError; 294 SkASSERT(fOldErrorReporter); 295 dsl::SetErrorReporter(&fErrorReporter); 296 } 297 ~Checkpoint()298 ~Checkpoint() { 299 SkASSERTF(!fOldErrorReporter, 300 "Checkpoint was not accepted or rewound before destruction"); 301 } 302 accept()303 void accept() { 304 this->restoreErrorReporter(); 305 // Parser errors should have been fatal, but we can encounter other errors like type 306 // mismatches despite accepting the parse. Forward those messages to the actual error 307 // handler now. 308 fErrorReporter.forwardErrors(); 309 } 310 rewind()311 void rewind() { 312 this->restoreErrorReporter(); 313 fParser->fPushback = fPushbackCheckpoint; 314 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint); 315 fParser->fEncounteredFatalError = fOldEncounteredFatalError; 316 } 317 318 private: 319 class ForwardingErrorReporter : public ErrorReporter { 320 public: handleError(std::string_view msg,Position pos)321 void handleError(std::string_view msg, Position pos) override { 322 fErrors.push_back({std::string(msg), pos}); 323 } 324 forwardErrors()325 void forwardErrors() { 326 for (Error& error : fErrors) { 327 dsl::GetErrorReporter().error(error.fPos, error.fMsg); 328 } 329 } 330 331 private: 332 struct Error { 333 std::string fMsg; 334 Position fPos; 335 }; 336 337 SkTArray<Error> fErrors; 338 }; 339 restoreErrorReporter()340 void restoreErrorReporter() { 341 SkASSERT(fOldErrorReporter); 342 dsl::SetErrorReporter(fOldErrorReporter); 343 fOldErrorReporter = nullptr; 344 } 345 346 Parser* fParser; 347 Token fPushbackCheckpoint; 348 SkSL::Lexer::Checkpoint fLexerCheckpoint; 349 ForwardingErrorReporter fErrorReporter; 350 ErrorReporter* fOldErrorReporter; 351 bool fOldEncounteredFatalError; 352 }; 353 354 Compiler& fCompiler; 355 ProgramSettings fSettings; 356 ErrorReporter* fErrorReporter; 357 bool fEncounteredFatalError; 358 ProgramKind fKind; 359 std::unique_ptr<std::string> fText; 360 Lexer fLexer; 361 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the 362 // stack on pathological inputs 363 int fDepth = 0; 364 Token fPushback; 365 }; 366 367 } // namespace SkSL 368 369 #endif 370