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