blob: 15d478f9e4c6777392716b7cb59950fc6e4dabb3 [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
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040021namespace SkSL {
22
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -040023class ErrorReporter;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040024struct Modifiers;
Ethan Nicholas051aeb72021-09-24 16:39:19 -040025struct ParsedModule;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040026class SymbolTable;
27
28/**
29 * Consumes .sksl text and invokes DSL functions to instantiate the program.
30 */
31class DSLParser {
32public:
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,
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040046 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
Ethan Nicholas051aeb72021-09-24 16:39:19 -040068 SkSL::LoadedModule moduleInheritingFrom(SkSL::ParsedModule baseModule);
69
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040070 skstd::string_view text(Token token);
71
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -040072 PositionInfo position(Token token);
73
Ethan Nicholas89cfde12021-09-27 11:20:34 -040074 PositionInfo position(int line);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040075
76private:
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
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400127 void error(Token token, String msg);
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400128 void error(int line, String msg);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400129
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
Ethan Nicholas051aeb72021-09-24 16:39:19 -0400138 void declarations();
139
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400140 SKSL_INT arraySize();
141
Ethan Nicholas642215e2021-09-03 11:10:54 -0400142 void directive();
143
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400144 bool declaration();
145
John Stilese53c7212021-08-05 10:19:11 -0400146 bool functionDeclarationEnd(const dsl::DSLModifiers& modifiers,
147 dsl::DSLType type,
148 const Token& name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400149
150 struct VarDeclarationsPrefix {
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400151 PositionInfo fPosition;
152 dsl::DSLModifiers fModifiers;
153 dsl::DSLType fType = dsl::DSLType(dsl::kVoid_Type);
154 Token fName;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400155 };
156
157 bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData);
158
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400159 dsl::DSLStatement varDeclarationsOrExpressionStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400160
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400161 dsl::DSLStatement varDeclarations();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400162
163 skstd::optional<dsl::DSLType> structDeclaration();
164
John Stilese53c7212021-08-05 10:19:11 -0400165 SkTArray<dsl::DSLGlobalVar> structVarDeclaration(const dsl::DSLModifiers& modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400166
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400167 bool parseArrayDimensions(int line, dsl::DSLType* type);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400168
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400169 bool parseInitializer(int line, dsl::DSLExpression* initializer);
Ethan Nicholas6c302ba2021-09-14 09:16:12 -0400170
171 void globalVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods,
172 dsl::DSLType baseType, skstd::string_view name);
173
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400174 dsl::DSLStatement localVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods,
175 dsl::DSLType baseType, skstd::string_view name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400176
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
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400187 dsl::DSLStatement statement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400188
John Stiles66aa1de2021-10-01 13:59:20 -0400189 skstd::optional<dsl::DSLType> type(dsl::DSLModifiers* modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400190
John Stilese53c7212021-08-05 10:19:11 -0400191 bool interfaceBlock(const dsl::DSLModifiers& mods);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400192
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400193 dsl::DSLStatement ifStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400194
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400195 dsl::DSLStatement doStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400196
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400197 dsl::DSLStatement whileStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400198
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400199 dsl::DSLStatement forStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400200
201 skstd::optional<dsl::DSLCase> switchCase();
202
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400203 dsl::DSLStatement switchStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400204
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400205 dsl::DSLStatement returnStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400206
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400207 dsl::DSLStatement breakStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400208
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400209 dsl::DSLStatement continueStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400210
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400211 dsl::DSLStatement discardStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400212
213 skstd::optional<dsl::DSLBlock> block();
214
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400215 dsl::DSLStatement expressionStatement();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400216
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400217 dsl::DSLExpression expression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400218
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400219 dsl::DSLExpression assignmentExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400220
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400221 dsl::DSLExpression ternaryExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400222
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400223 dsl::DSLExpression logicalOrExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400224
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400225 dsl::DSLExpression logicalXorExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400226
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400227 dsl::DSLExpression logicalAndExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400228
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400229 dsl::DSLExpression bitwiseOrExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400230
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400231 dsl::DSLExpression bitwiseXorExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400232
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400233 dsl::DSLExpression bitwiseAndExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400234
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400235 dsl::DSLExpression equalityExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400236
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400237 dsl::DSLExpression relationalExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400238
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400239 dsl::DSLExpression shiftExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400240
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400241 dsl::DSLExpression additiveExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400242
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400243 dsl::DSLExpression multiplicativeExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400244
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400245 dsl::DSLExpression unaryExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400246
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400247 dsl::DSLExpression postfixExpression();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400248
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400249 dsl::DSLExpression swizzle(int line, dsl::DSLExpression base, skstd::string_view swizzleMask);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400250
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400251 dsl::DSLExpression call(int line, dsl::DSLExpression base, ExpressionArray args);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400252
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400253 dsl::DSLExpression suffix(dsl::DSLExpression base);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400254
Ethan Nicholasb7cb38f2021-09-15 08:29:14 -0400255 dsl::DSLExpression term();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400256
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
Ethan Nicholas55478662021-08-10 17:14:26 -0400265 class Checkpoint {
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400266 public:
267 Checkpoint(DSLParser* p) : fParser(p) {
268 fPushbackCheckpoint = fParser->fPushback;
269 fLexerCheckpoint = fParser->fLexer.getCheckpoint();
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400270 fOldErrorReporter = &dsl::GetErrorReporter();
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400271 fOldEncounteredFatalError = fParser->fEncounteredFatalError;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400272 SkASSERT(fOldErrorReporter);
273 dsl::SetErrorReporter(&fErrorReporter);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400274 }
275
Ethan Nicholas55478662021-08-10 17:14:26 -0400276 ~Checkpoint() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400277 SkASSERTF(!fOldErrorReporter,
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400278 "Checkpoint was not accepted or rewound before destruction");
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400279 }
280
281 void accept() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400282 this->restoreErrorReporter();
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400283 // 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.
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400286 fErrorReporter.forwardErrors();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400287 }
288
289 void rewind() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400290 this->restoreErrorReporter();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400291 fParser->fPushback = fPushbackCheckpoint;
292 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400293 fParser->fEncounteredFatalError = fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400294 }
295
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400296 private:
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400297 class ForwardingErrorReporter : public ErrorReporter {
Ethan Nicholas55478662021-08-10 17:14:26 -0400298 public:
Ethan Nicholas32724122021-09-07 13:49:07 -0400299 void handleError(skstd::string_view msg, PositionInfo pos) override {
Ethan Nicholas55478662021-08-10 17:14:26 -0400300 fErrors.push_back({String(msg), pos});
301 }
302
303 void forwardErrors() {
304 for (Error& error : fErrors) {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400305 dsl::GetErrorReporter().error(error.fMsg.c_str(), error.fPos);
Ethan Nicholas55478662021-08-10 17:14:26 -0400306 }
307 }
308
309 private:
310 struct Error {
311 String fMsg;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400312 PositionInfo fPos;
Ethan Nicholas55478662021-08-10 17:14:26 -0400313 };
314
315 SkTArray<Error> fErrors;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400316 };
317
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400318 void restoreErrorReporter() {
319 SkASSERT(fOldErrorReporter);
Ethan Nicholas5c4463e2021-08-29 14:31:19 -0400320 fErrorReporter.reportPendingErrors(PositionInfo());
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400321 dsl::SetErrorReporter(fOldErrorReporter);
322 fOldErrorReporter = nullptr;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400323 }
324
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400325 DSLParser* fParser;
326 Token fPushbackCheckpoint;
Ethan Nicholas5fad2b882021-09-27 10:39:18 -0400327 SkSL::Lexer::Checkpoint fLexerCheckpoint;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400328 ForwardingErrorReporter fErrorReporter;
329 ErrorReporter* fOldErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400330 bool fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400331 };
332
333 static std::unordered_map<skstd::string_view, LayoutToken>* layoutTokens;
334
335 Compiler& fCompiler;
336 ProgramSettings fSettings;
337 ErrorReporter* fErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400338 bool fEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400339 ProgramKind fKind;
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400340 std::unique_ptr<String> fText;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400341 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
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400353#endif