blob: aed2a1956777434e5a6ff78bc8c509798bbc9b3e [file] [log] [blame]
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -04001/*
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"
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040018#include "src/sksl/SkSLLexer.h"
19#include "src/sksl/ir/SkSLProgram.h"
20
21#if SKSL_DSL_PARSER
22
23namespace SkSL {
24
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -040025class ErrorReporter;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040026struct Modifiers;
Ethan Nicholas051aeb72021-09-24 16:39:19 -040027struct ParsedModule;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040028class SymbolTable;
29
30/**
31 * Consumes .sksl text and invokes DSL functions to instantiate the program.
32 */
33class DSLParser {
34public:
35 enum class LayoutToken {
36 LOCATION,
37 OFFSET,
38 BINDING,
39 INDEX,
40 SET,
41 BUILTIN,
42 INPUT_ATTACHMENT_INDEX,
43 ORIGIN_UPPER_LEFT,
44 OVERRIDE_COVERAGE,
45 EARLY_FRAGMENT_TESTS,
46 BLEND_SUPPORT_ALL_EQUATIONS,
47 PUSH_CONSTANT,
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040048 MARKER,
49 WHEN,
50 KEY,
51 TRACKED,
52 SRGB_UNPREMUL,
53 CTYPE,
54 SKPMCOLOR4F,
55 SKV4,
56 SKRECT,
57 SKIRECT,
58 SKPMCOLOR,
59 SKM44,
60 BOOL,
61 INT,
62 FLOAT,
63 };
64
65 DSLParser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind,
66 String text);
67
68 std::unique_ptr<Program> program();
69
Ethan Nicholas051aeb72021-09-24 16:39:19 -040070 SkSL::LoadedModule moduleInheritingFrom(SkSL::ParsedModule baseModule);
71
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040072 skstd::string_view text(Token token);
73
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -040074 PositionInfo position(Token token);
75
Brian Osmancc914522021-09-24 18:58:37 +000076 PositionInfo position(int offset);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040077
78private:
79 static void InitLayoutMap();
80
81 /**
82 * Return the next token, including whitespace tokens, from the parse stream.
83 */
84 Token nextRawToken();
85
86 /**
87 * Return the next non-whitespace token from the parse stream.
88 */
89 Token nextToken();
90
91 /**
92 * Push a token back onto the parse stream, so that it is the next one read. Only a single level
93 * of pushback is supported (that is, it is an error to call pushback() twice in a row without
94 * an intervening nextToken()).
95 */
96 void pushback(Token t);
97
98 /**
99 * Returns the next non-whitespace token without consuming it from the stream.
100 */
101 Token peek();
102
103 /**
104 * Checks to see if the next token is of the specified type. If so, stores it in result (if
105 * result is non-null) and returns true. Otherwise, pushes it back and returns false.
106 */
107 bool checkNext(Token::Kind kind, Token* result = nullptr);
108
109 /**
110 * Reads the next non-whitespace token and generates an error if it is not the expected type.
111 * The 'expected' string is part of the error message, which reads:
112 *
113 * "expected <expected>, but found '<actual text>'"
114 *
115 * If 'result' is non-null, it is set to point to the token that was read.
116 * Returns true if the read token was as expected, false otherwise.
117 */
118 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
119 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
120
121 /**
122 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
123 * If the token was actually a type, generates an error message of the form:
124 *
125 * "expected an identifier, but found type 'float2'"
126 */
127 bool expectIdentifier(Token* result);
128
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400129 void error(Token token, String msg);
Brian Osmancc914522021-09-24 18:58:37 +0000130 void error(int offset, String msg);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400131
132 SymbolTable& symbols() {
133 return *dsl::CurrentSymbolTable();
134 }
135
136 // these functions parse individual grammar rules from the current parse position; you probably
137 // don't need to call any of these outside of the parser. The function declarations in the .cpp
138 // file have comments describing the grammar rules.
139
Ethan Nicholas051aeb72021-09-24 16:39:19 -0400140 void declarations();
141
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400142 ASTNode::ID precision();
143
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400144 SKSL_INT arraySize();
145
Ethan Nicholas642215e2021-09-03 11:10:54 -0400146 void directive();
147
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400148 bool declaration();
149
John Stilese53c7212021-08-05 10:19:11 -0400150 bool functionDeclarationEnd(const dsl::DSLModifiers& modifiers,
151 dsl::DSLType type,
152 const Token& name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400153
154 struct VarDeclarationsPrefix {
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400155 PositionInfo fPosition;
156 dsl::DSLModifiers fModifiers;
157 dsl::DSLType fType = dsl::DSLType(dsl::kVoid_Type);
158 Token fName;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400159 };
160
161 bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData);
162
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400163 dsl::DSLStatement varDeclarationsOrExpressionStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400164
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400165 dsl::DSLStatement varDeclarations();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400166
167 skstd::optional<dsl::DSLType> structDeclaration();
168
John Stilese53c7212021-08-05 10:19:11 -0400169 SkTArray<dsl::DSLGlobalVar> structVarDeclaration(const dsl::DSLModifiers& modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400170
Brian Osmancc914522021-09-24 18:58:37 +0000171 bool parseArrayDimensions(int offset, dsl::DSLType* type);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400172
Brian Osmancc914522021-09-24 18:58:37 +0000173 bool parseInitializer(int offset, dsl::DSLExpression* initializer);
Ethan Nicholas6c302ba2021-09-14 09:16:12 -0400174
175 void globalVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods,
176 dsl::DSLType baseType, skstd::string_view name);
177
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400178 dsl::DSLStatement localVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods,
179 dsl::DSLType baseType, skstd::string_view name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400180
181 skstd::optional<dsl::DSLWrapper<dsl::DSLParameter>> parameter();
182
183 int layoutInt();
184
185 skstd::string_view layoutIdentifier();
186
187 dsl::DSLLayout layout();
188
189 dsl::DSLModifiers modifiers();
190
191 dsl::DSLModifiers modifiersWithDefaults(int defaultFlags);
192
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400193 dsl::DSLStatement statement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400194
John Stilese53c7212021-08-05 10:19:11 -0400195 skstd::optional<dsl::DSLType> type(const dsl::DSLModifiers& modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400196
John Stilese53c7212021-08-05 10:19:11 -0400197 bool interfaceBlock(const dsl::DSLModifiers& mods);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400198
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400199 dsl::DSLStatement ifStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400200
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400201 dsl::DSLStatement doStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400202
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400203 dsl::DSLStatement whileStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400204
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400205 dsl::DSLStatement forStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400206
207 skstd::optional<dsl::DSLCase> switchCase();
208
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400209 dsl::DSLStatement switchStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400210
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400211 dsl::DSLStatement returnStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400212
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400213 dsl::DSLStatement breakStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400214
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400215 dsl::DSLStatement continueStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400216
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400217 dsl::DSLStatement discardStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400218
219 skstd::optional<dsl::DSLBlock> block();
220
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400221 dsl::DSLStatement expressionStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400222
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400223 dsl::DSLExpression expression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400224
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400225 dsl::DSLExpression assignmentExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400226
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400227 dsl::DSLExpression ternaryExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400228
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400229 dsl::DSLExpression logicalOrExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400230
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400231 dsl::DSLExpression logicalXorExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400232
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400233 dsl::DSLExpression logicalAndExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400234
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400235 dsl::DSLExpression bitwiseOrExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400236
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400237 dsl::DSLExpression bitwiseXorExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400238
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400239 dsl::DSLExpression bitwiseAndExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400240
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400241 dsl::DSLExpression equalityExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400242
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400243 dsl::DSLExpression relationalExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400244
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400245 dsl::DSLExpression shiftExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400246
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400247 dsl::DSLExpression additiveExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400248
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400249 dsl::DSLExpression multiplicativeExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400250
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400251 dsl::DSLExpression unaryExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400252
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400253 dsl::DSLExpression postfixExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400254
Brian Osmancc914522021-09-24 18:58:37 +0000255 dsl::DSLExpression swizzle(int offset, dsl::DSLExpression base, skstd::string_view swizzleMask);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400256
Brian Osmancc914522021-09-24 18:58:37 +0000257 dsl::DSLExpression call(int offset, dsl::DSLExpression base, ExpressionArray args);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400258
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400259 dsl::DSLExpression suffix(dsl::DSLExpression base);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400260
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400261 dsl::DSLExpression term();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400262
263 bool intLiteral(SKSL_INT* dest);
264
265 bool floatLiteral(SKSL_FLOAT* dest);
266
267 bool boolLiteral(bool* dest);
268
269 bool identifier(skstd::string_view* dest);
270
Ethan Nicholas55478662021-08-10 17:14:26 -0400271 class Checkpoint {
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400272 public:
273 Checkpoint(DSLParser* p) : fParser(p) {
274 fPushbackCheckpoint = fParser->fPushback;
275 fLexerCheckpoint = fParser->fLexer.getCheckpoint();
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400276 fOldErrorReporter = &dsl::GetErrorReporter();
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400277 fOldEncounteredFatalError = fParser->fEncounteredFatalError;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400278 SkASSERT(fOldErrorReporter);
279 dsl::SetErrorReporter(&fErrorReporter);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400280 }
281
Ethan Nicholas55478662021-08-10 17:14:26 -0400282 ~Checkpoint() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400283 SkASSERTF(!fOldErrorReporter,
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400284 "Checkpoint was not accepted or rewound before destruction");
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400285 }
286
287 void accept() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400288 this->restoreErrorReporter();
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400289 // Parser errors should have been fatal, but we can encounter other errors like type
290 // mismatches despite accepting the parse. Forward those messages to the actual error
291 // handler now.
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400292 fErrorReporter.forwardErrors();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400293 }
294
295 void rewind() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400296 this->restoreErrorReporter();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400297 fParser->fPushback = fPushbackCheckpoint;
298 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400299 fParser->fEncounteredFatalError = fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400300 }
301
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400302 private:
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400303 class ForwardingErrorReporter : public ErrorReporter {
Ethan Nicholas55478662021-08-10 17:14:26 -0400304 public:
Ethan Nicholas32724122021-09-07 13:49:07 -0400305 void handleError(skstd::string_view msg, PositionInfo pos) override {
Ethan Nicholas55478662021-08-10 17:14:26 -0400306 fErrors.push_back({String(msg), pos});
307 }
308
309 void forwardErrors() {
310 for (Error& error : fErrors) {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400311 dsl::GetErrorReporter().error(error.fMsg.c_str(), error.fPos);
Ethan Nicholas55478662021-08-10 17:14:26 -0400312 }
313 }
314
315 private:
316 struct Error {
317 String fMsg;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400318 PositionInfo fPos;
Ethan Nicholas55478662021-08-10 17:14:26 -0400319 };
320
321 SkTArray<Error> fErrors;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400322 };
323
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400324 void restoreErrorReporter() {
325 SkASSERT(fOldErrorReporter);
Ethan Nicholas5c4463e2021-08-29 14:31:19 -0400326 fErrorReporter.reportPendingErrors(PositionInfo());
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400327 dsl::SetErrorReporter(fOldErrorReporter);
328 fOldErrorReporter = nullptr;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400329 }
330
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400331 DSLParser* fParser;
332 Token fPushbackCheckpoint;
Ethan Nicholas5fad2b82021-09-27 10:39:18 -0400333 SkSL::Lexer::Checkpoint fLexerCheckpoint;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400334 ForwardingErrorReporter fErrorReporter;
335 ErrorReporter* fOldErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400336 bool fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400337 };
338
339 static std::unordered_map<skstd::string_view, LayoutToken>* layoutTokens;
340
341 Compiler& fCompiler;
342 ProgramSettings fSettings;
343 ErrorReporter* fErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400344 bool fEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400345 ProgramKind fKind;
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400346 std::unique_ptr<String> fText;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400347 Lexer fLexer;
348 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
349 // stack on pathological inputs
350 int fDepth = 0;
351 Token fPushback;
352
353 friend class AutoDSLDepth;
354 friend class HCodeGenerator;
355};
356
357} // namespace SkSL
358
359#endif // SKSL_DSL_PARSER
360
361#endif