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