blob: 485b0f9a070a4f1fd9950804377f020e8d737c57 [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;
27class SymbolTable;
28
29/**
30 * Consumes .sksl text and invokes DSL functions to instantiate the program.
31 */
32class DSLParser {
33public:
34 enum class LayoutToken {
35 LOCATION,
36 OFFSET,
37 BINDING,
38 INDEX,
39 SET,
40 BUILTIN,
41 INPUT_ATTACHMENT_INDEX,
42 ORIGIN_UPPER_LEFT,
43 OVERRIDE_COVERAGE,
44 EARLY_FRAGMENT_TESTS,
45 BLEND_SUPPORT_ALL_EQUATIONS,
46 PUSH_CONSTANT,
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040047 MARKER,
48 WHEN,
49 KEY,
50 TRACKED,
51 SRGB_UNPREMUL,
52 CTYPE,
53 SKPMCOLOR4F,
54 SKV4,
55 SKRECT,
56 SKIRECT,
57 SKPMCOLOR,
58 SKM44,
59 BOOL,
60 INT,
61 FLOAT,
62 };
63
64 DSLParser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind,
65 String text);
66
67 std::unique_ptr<Program> program();
68
69 skstd::string_view text(Token token);
70
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -040071 PositionInfo position(Token token);
72
73 PositionInfo position(int offset);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -040074
75private:
76 static void InitLayoutMap();
77
78 /**
79 * Return the next token, including whitespace tokens, from the parse stream.
80 */
81 Token nextRawToken();
82
83 /**
84 * Return the next non-whitespace token from the parse stream.
85 */
86 Token nextToken();
87
88 /**
89 * Push a token back onto the parse stream, so that it is the next one read. Only a single level
90 * of pushback is supported (that is, it is an error to call pushback() twice in a row without
91 * an intervening nextToken()).
92 */
93 void pushback(Token t);
94
95 /**
96 * Returns the next non-whitespace token without consuming it from the stream.
97 */
98 Token peek();
99
100 /**
101 * Checks to see if the next token is of the specified type. If so, stores it in result (if
102 * result is non-null) and returns true. Otherwise, pushes it back and returns false.
103 */
104 bool checkNext(Token::Kind kind, Token* result = nullptr);
105
106 /**
107 * Reads the next non-whitespace token and generates an error if it is not the expected type.
108 * The 'expected' string is part of the error message, which reads:
109 *
110 * "expected <expected>, but found '<actual text>'"
111 *
112 * If 'result' is non-null, it is set to point to the token that was read.
113 * Returns true if the read token was as expected, false otherwise.
114 */
115 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
116 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
117
118 /**
119 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
120 * If the token was actually a type, generates an error message of the form:
121 *
122 * "expected an identifier, but found type 'float2'"
123 */
124 bool expectIdentifier(Token* result);
125
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400126 void error(Token token, String msg);
127 void error(int offset, String msg);
128
129 SymbolTable& symbols() {
130 return *dsl::CurrentSymbolTable();
131 }
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 ASTNode::ID precision();
138
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400139 SKSL_INT arraySize();
140
Ethan Nicholas642215e2021-09-03 11:10:54 -0400141 void directive();
142
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400143 bool declaration();
144
John Stilese53c7212021-08-05 10:19:11 -0400145 bool functionDeclarationEnd(const dsl::DSLModifiers& modifiers,
146 dsl::DSLType type,
147 const Token& name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400148
149 struct VarDeclarationsPrefix {
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400150 PositionInfo fPosition;
151 dsl::DSLModifiers fModifiers;
152 dsl::DSLType fType = dsl::DSLType(dsl::kVoid_Type);
153 Token fName;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400154 };
155
156 bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData);
157
158 skstd::optional<dsl::DSLStatement> varDeclarationsOrExpressionStatement();
159
160 skstd::optional<dsl::DSLStatement> varDeclarations();
161
162 skstd::optional<dsl::DSLType> structDeclaration();
163
John Stilese53c7212021-08-05 10:19:11 -0400164 SkTArray<dsl::DSLGlobalVar> structVarDeclaration(const dsl::DSLModifiers& modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400165
Ethan Nicholas6c302ba2021-09-14 09:16:12 -0400166 bool parseArrayDimensions(int offset, dsl::DSLType* type);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400167
Ethan Nicholas6c302ba2021-09-14 09:16:12 -0400168 bool parseInitializer(int offset, dsl::DSLExpression* initializer);
169
170 void globalVarDeclarationEnd(PositionInfo position, const dsl::DSLModifiers& mods,
171 dsl::DSLType baseType, skstd::string_view name);
172
173 skstd::optional<dsl::DSLStatement> localVarDeclarationEnd(PositionInfo position,
174 const dsl::DSLModifiers& mods, dsl::DSLType baseType, skstd::string_view name);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400175
176 skstd::optional<dsl::DSLWrapper<dsl::DSLParameter>> parameter();
177
178 int layoutInt();
179
180 skstd::string_view layoutIdentifier();
181
182 dsl::DSLLayout layout();
183
184 dsl::DSLModifiers modifiers();
185
186 dsl::DSLModifiers modifiersWithDefaults(int defaultFlags);
187
188 skstd::optional<dsl::DSLStatement> statement();
189
John Stilese53c7212021-08-05 10:19:11 -0400190 skstd::optional<dsl::DSLType> type(const dsl::DSLModifiers& modifiers);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400191
John Stilese53c7212021-08-05 10:19:11 -0400192 bool interfaceBlock(const dsl::DSLModifiers& mods);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400193
194 skstd::optional<dsl::DSLStatement> ifStatement();
195
196 skstd::optional<dsl::DSLStatement> doStatement();
197
198 skstd::optional<dsl::DSLStatement> whileStatement();
199
200 skstd::optional<dsl::DSLStatement> forStatement();
201
202 skstd::optional<dsl::DSLCase> switchCase();
203
204 skstd::optional<dsl::DSLStatement> switchStatement();
205
206 skstd::optional<dsl::DSLStatement> returnStatement();
207
208 skstd::optional<dsl::DSLStatement> breakStatement();
209
210 skstd::optional<dsl::DSLStatement> continueStatement();
211
212 skstd::optional<dsl::DSLStatement> discardStatement();
213
214 skstd::optional<dsl::DSLBlock> block();
215
216 skstd::optional<dsl::DSLStatement> expressionStatement();
217
218 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> expression();
219
220 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> assignmentExpression();
221
222 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> ternaryExpression();
223
224 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> logicalOrExpression();
225
226 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> logicalXorExpression();
227
228 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> logicalAndExpression();
229
230 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> bitwiseOrExpression();
231
232 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> bitwiseXorExpression();
233
234 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> bitwiseAndExpression();
235
236 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> equalityExpression();
237
238 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> relationalExpression();
239
240 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> shiftExpression();
241
242 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> additiveExpression();
243
244 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> multiplicativeExpression();
245
246 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> unaryExpression();
247
248 skstd::optional<dsl::DSLWrapper<dsl::DSLExpression>> postfixExpression();
249
250 skstd::optional<dsl::Wrapper<dsl::DSLExpression>> swizzle(int offset, dsl::DSLExpression base,
251 skstd::string_view swizzleMask);
252
253 skstd::optional<dsl::Wrapper<dsl::DSLExpression>> call(int offset, dsl::DSLExpression base,
Ethan Nicholas9a1f92e2021-09-09 15:03:22 -0400254 ExpressionArray args);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400255
256 skstd::optional<dsl::Wrapper<dsl::DSLExpression>> suffix(dsl::DSLExpression base);
257
258 skstd::optional<dsl::Wrapper<dsl::DSLExpression>> term();
259
260 bool intLiteral(SKSL_INT* dest);
261
262 bool floatLiteral(SKSL_FLOAT* dest);
263
264 bool boolLiteral(bool* dest);
265
266 bool identifier(skstd::string_view* dest);
267
Ethan Nicholas55478662021-08-10 17:14:26 -0400268 class Checkpoint {
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400269 public:
270 Checkpoint(DSLParser* p) : fParser(p) {
271 fPushbackCheckpoint = fParser->fPushback;
272 fLexerCheckpoint = fParser->fLexer.getCheckpoint();
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400273 fOldErrorReporter = &dsl::GetErrorReporter();
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400274 fOldEncounteredFatalError = fParser->fEncounteredFatalError;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400275 SkASSERT(fOldErrorReporter);
276 dsl::SetErrorReporter(&fErrorReporter);
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400277 }
278
Ethan Nicholas55478662021-08-10 17:14:26 -0400279 ~Checkpoint() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400280 SkASSERTF(!fOldErrorReporter,
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400281 "Checkpoint was not accepted or rewound before destruction");
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400282 }
283
284 void accept() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400285 this->restoreErrorReporter();
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400286 // Parser errors should have been fatal, but we can encounter other errors like type
287 // mismatches despite accepting the parse. Forward those messages to the actual error
288 // handler now.
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400289 fErrorReporter.forwardErrors();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400290 }
291
292 void rewind() {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400293 this->restoreErrorReporter();
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400294 fParser->fPushback = fPushbackCheckpoint;
295 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400296 fParser->fEncounteredFatalError = fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400297 }
298
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400299 private:
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400300 class ForwardingErrorReporter : public ErrorReporter {
Ethan Nicholas55478662021-08-10 17:14:26 -0400301 public:
Ethan Nicholas32724122021-09-07 13:49:07 -0400302 void handleError(skstd::string_view msg, PositionInfo pos) override {
Ethan Nicholas55478662021-08-10 17:14:26 -0400303 fErrors.push_back({String(msg), pos});
304 }
305
306 void forwardErrors() {
307 for (Error& error : fErrors) {
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400308 dsl::GetErrorReporter().error(error.fMsg.c_str(), error.fPos);
Ethan Nicholas55478662021-08-10 17:14:26 -0400309 }
310 }
311
312 private:
313 struct Error {
314 String fMsg;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400315 PositionInfo fPos;
Ethan Nicholas55478662021-08-10 17:14:26 -0400316 };
317
318 SkTArray<Error> fErrors;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400319 };
320
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400321 void restoreErrorReporter() {
322 SkASSERT(fOldErrorReporter);
Ethan Nicholas5c4463e2021-08-29 14:31:19 -0400323 fErrorReporter.reportPendingErrors(PositionInfo());
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400324 dsl::SetErrorReporter(fOldErrorReporter);
325 fOldErrorReporter = nullptr;
Ethan Nicholas65e368b2021-08-05 14:53:02 -0400326 }
327
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400328 DSLParser* fParser;
329 Token fPushbackCheckpoint;
330 int32_t fLexerCheckpoint;
Ethan Nicholas4a5e22a2021-08-13 17:29:51 -0400331 ForwardingErrorReporter fErrorReporter;
332 ErrorReporter* fOldErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400333 bool fOldEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400334 };
335
336 static std::unordered_map<skstd::string_view, LayoutToken>* layoutTokens;
337
338 Compiler& fCompiler;
339 ProgramSettings fSettings;
340 ErrorReporter* fErrorReporter;
Ethan Nicholas5d97a962021-08-30 15:58:52 -0400341 bool fEncounteredFatalError;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400342 ProgramKind fKind;
Ethan Nicholas6f20b8d2021-08-31 07:40:24 -0400343 std::unique_ptr<String> fText;
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400344 Lexer fLexer;
345 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
346 // stack on pathological inputs
347 int fDepth = 0;
348 Token fPushback;
349
350 friend class AutoDSLDepth;
351 friend class HCodeGenerator;
352};
353
354} // namespace SkSL
355
356#endif // SKSL_DSL_PARSER
357
358#endif