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