• 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_PARSER
9 #define SKSL_PARSER
10 
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkSLDefines.h"
13 #include "include/private/base/SkTArray.h"
14 #include "include/sksl/DSLCore.h"
15 #include "include/sksl/DSLExpression.h"
16 #include "include/sksl/DSLLayout.h"
17 #include "include/sksl/DSLModifiers.h"
18 #include "include/sksl/DSLStatement.h"
19 #include "include/sksl/DSLType.h"
20 #include "include/sksl/SkSLErrorReporter.h"
21 #include "include/sksl/SkSLOperator.h"
22 #include "include/sksl/SkSLPosition.h"
23 #include "src/sksl/SkSLLexer.h"
24 #include "src/sksl/SkSLProgramSettings.h"
25 
26 #include <cstddef>
27 #include <cstdint>
28 #include <memory>
29 #include <optional>
30 #include <string>
31 #include <string_view>
32 
33 namespace SkSL {
34 
35 class Compiler;
36 class SymbolTable;
37 enum class ProgramKind : int8_t;
38 struct Module;
39 struct Program;
40 
41 namespace dsl {
42 class DSLBlock;
43 class DSLCase;
44 class DSLGlobalVar;
45 class DSLParameter;
46 class DSLVarBase;
47 }
48 
49 /**
50  * Consumes .sksl text and invokes DSL functions to instantiate the program.
51  */
52 class Parser {
53 public:
54     Parser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind, std::string text);
55 
56     std::unique_ptr<Program> program();
57 
58     std::unique_ptr<Module> moduleInheritingFrom(const Module* parent);
59 
60     std::string_view text(Token token);
61 
62     Position position(Token token);
63 
64 private:
65     class AutoDepth;
66     class AutoSymbolTable;
67 
68     /**
69      * Return the next token, including whitespace tokens, from the parse stream.
70      */
71     Token nextRawToken();
72 
73     /**
74      * Return the next non-whitespace token from the parse stream.
75      */
76     Token nextToken();
77 
78     /**
79      * Push a token back onto the parse stream, so that it is the next one read. Only a single level
80      * of pushback is supported (that is, it is an error to call pushback() twice in a row without
81      * an intervening nextToken()).
82      */
83     void pushback(Token t);
84 
85     /**
86      * Returns the next non-whitespace token without consuming it from the stream.
87      */
88     Token peek();
89 
90     /**
91      * Checks to see if the next token is of the specified type. If so, stores it in result (if
92      * result is non-null) and returns true. Otherwise, pushes it back and returns false.
93      */
94     bool checkNext(Token::Kind kind, Token* result = nullptr);
95 
96     /**
97      * Behaves like checkNext(TK_IDENTIFIER), but also verifies that identifier is not a builtin
98      * type. If the token was actually a builtin type, false is returned (the next token is not
99      * considered to be an identifier).
100      */
101     bool checkIdentifier(Token* result = nullptr);
102 
103     /**
104      * Reads the next non-whitespace token and generates an error if it is not the expected type.
105      * The 'expected' string is part of the error message, which reads:
106      *
107      * "expected <expected>, but found '<actual text>'"
108      *
109      * If 'result' is non-null, it is set to point to the token that was read.
110      * Returns true if the read token was as expected, false otherwise.
111      */
112     bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
113     bool expect(Token::Kind kind, std::string expected, Token* result = nullptr);
114 
115     /**
116      * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
117      * If the token was actually a type, generates an error message of the form:
118      *
119      * "expected an identifier, but found type 'float2'"
120      */
121     bool expectIdentifier(Token* result);
122 
123     /** If the next token is a newline, consumes it and returns true. If not, returns false. */
124     bool expectNewline();
125 
126     void error(Token token, std::string_view msg);
127     void error(Position position, std::string_view msg);
128 
129     // Returns the range from `start` to the current parse position.
130     Position rangeFrom(Position start);
131     Position rangeFrom(Token start);
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     void declarations();
138 
139     /**
140      * Parses an expression representing an array size. Reports errors if the array size is not
141      * valid (out of bounds, not a literal integer). Returns true if an expression was
142      * successfully parsed, even if that array size is not actually valid. In the event of a true
143      * return, outResult always contains a valid array size (even if the parsed array size was not
144      * actually valid; invalid array sizes result in a 1 to avoid additional errors downstream).
145      */
146     bool arraySize(SKSL_INT* outResult);
147 
148     void directive(bool allowVersion);
149 
150     bool declaration();
151 
152     bool functionDeclarationEnd(Position start,
153                                 dsl::DSLModifiers& modifiers,
154                                 dsl::DSLType type,
155                                 const Token& name);
156 
157     struct VarDeclarationsPrefix {
158         Position 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     dsl::DSLType structDeclaration();
171 
172     SkTArray<dsl::DSLGlobalVar> structVarDeclaration(Position start,
173                                                      const dsl::DSLModifiers& modifiers);
174 
allowUnsizedArrays()175     bool allowUnsizedArrays() {
176         return ProgramConfig::IsCompute(fKind) || ProgramConfig::IsFragment(fKind) ||
177                ProgramConfig::IsVertex(fKind);
178     }
179 
180     bool parseArrayDimensions(Position pos, dsl::DSLType* type);
181 
182     bool parseInitializer(Position pos, dsl::DSLExpression* initializer);
183 
184     void globalVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods,
185             dsl::DSLType baseType, Token name);
186 
187     dsl::DSLStatement localVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods,
188             dsl::DSLType baseType, Token name);
189 
190     std::optional<dsl::DSLParameter> parameter(size_t paramIndex);
191 
192     int layoutInt();
193 
194     std::string_view layoutIdentifier();
195 
196     dsl::DSLLayout layout();
197 
198     dsl::DSLModifiers modifiers();
199 
200     dsl::DSLStatement statement();
201 
202     dsl::DSLType type(dsl::DSLModifiers* modifiers);
203 
204     bool interfaceBlock(const dsl::DSLModifiers& mods);
205 
206     dsl::DSLStatement ifStatement();
207 
208     dsl::DSLStatement doStatement();
209 
210     dsl::DSLStatement whileStatement();
211 
212     dsl::DSLStatement forStatement();
213 
214     std::optional<dsl::DSLCase> switchCase();
215 
216     dsl::DSLStatement switchStatement();
217 
218     dsl::DSLStatement returnStatement();
219 
220     dsl::DSLStatement breakStatement();
221 
222     dsl::DSLStatement continueStatement();
223 
224     dsl::DSLStatement discardStatement();
225 
226     std::optional<dsl::DSLBlock> block();
227 
228     dsl::DSLStatement expressionStatement();
229 
230     using BinaryParseFn = dsl::DSLExpression (Parser::*)();
231     bool SK_WARN_UNUSED_RESULT operatorRight(AutoDepth& depth, Operator::Kind op,
232                                              BinaryParseFn rightFn, dsl::DSLExpression& result);
233 
234     dsl::DSLExpression expression();
235 
236     dsl::DSLExpression assignmentExpression();
237 
238     dsl::DSLExpression ternaryExpression();
239 
240     dsl::DSLExpression logicalOrExpression();
241 
242     dsl::DSLExpression logicalXorExpression();
243 
244     dsl::DSLExpression logicalAndExpression();
245 
246     dsl::DSLExpression bitwiseOrExpression();
247 
248     dsl::DSLExpression bitwiseXorExpression();
249 
250     dsl::DSLExpression bitwiseAndExpression();
251 
252     dsl::DSLExpression equalityExpression();
253 
254     dsl::DSLExpression relationalExpression();
255 
256     dsl::DSLExpression shiftExpression();
257 
258     dsl::DSLExpression additiveExpression();
259 
260     dsl::DSLExpression multiplicativeExpression();
261 
262     dsl::DSLExpression unaryExpression();
263 
264     dsl::DSLExpression postfixExpression();
265 
266     dsl::DSLExpression swizzle(Position pos, dsl::DSLExpression base,
267             std::string_view swizzleMask, Position maskPos);
268 
269     dsl::DSLExpression call(Position pos, dsl::DSLExpression base, ExpressionArray args);
270 
271     dsl::DSLExpression suffix(dsl::DSLExpression base);
272 
273     dsl::DSLExpression term();
274 
275     bool intLiteral(SKSL_INT* dest);
276 
277     bool floatLiteral(SKSL_FLOAT* dest);
278 
279     bool boolLiteral(bool* dest);
280 
281     bool identifier(std::string_view* dest);
282 
283     std::shared_ptr<SymbolTable>& symbolTable();
284 
285     void addToSymbolTable(dsl::DSLVarBase& var, Position pos = {});
286 
287     class Checkpoint {
288     public:
Checkpoint(Parser * p)289         Checkpoint(Parser* p) : fParser(p) {
290             fPushbackCheckpoint = fParser->fPushback;
291             fLexerCheckpoint = fParser->fLexer.getCheckpoint();
292             fOldErrorReporter = &dsl::GetErrorReporter();
293             fOldEncounteredFatalError = fParser->fEncounteredFatalError;
294             SkASSERT(fOldErrorReporter);
295             dsl::SetErrorReporter(&fErrorReporter);
296         }
297 
~Checkpoint()298         ~Checkpoint() {
299             SkASSERTF(!fOldErrorReporter,
300                       "Checkpoint was not accepted or rewound before destruction");
301         }
302 
accept()303         void accept() {
304             this->restoreErrorReporter();
305             // Parser errors should have been fatal, but we can encounter other errors like type
306             // mismatches despite accepting the parse. Forward those messages to the actual error
307             // handler now.
308             fErrorReporter.forwardErrors();
309         }
310 
rewind()311         void rewind() {
312             this->restoreErrorReporter();
313             fParser->fPushback = fPushbackCheckpoint;
314             fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
315             fParser->fEncounteredFatalError = fOldEncounteredFatalError;
316         }
317 
318     private:
319         class ForwardingErrorReporter : public ErrorReporter {
320         public:
handleError(std::string_view msg,Position pos)321             void handleError(std::string_view msg, Position pos) override {
322                 fErrors.push_back({std::string(msg), pos});
323             }
324 
forwardErrors()325             void forwardErrors() {
326                 for (Error& error : fErrors) {
327                     dsl::GetErrorReporter().error(error.fPos, error.fMsg);
328                 }
329             }
330 
331         private:
332             struct Error {
333                 std::string fMsg;
334                 Position fPos;
335             };
336 
337             SkTArray<Error> fErrors;
338         };
339 
restoreErrorReporter()340         void restoreErrorReporter() {
341             SkASSERT(fOldErrorReporter);
342             dsl::SetErrorReporter(fOldErrorReporter);
343             fOldErrorReporter = nullptr;
344         }
345 
346         Parser* fParser;
347         Token fPushbackCheckpoint;
348         SkSL::Lexer::Checkpoint fLexerCheckpoint;
349         ForwardingErrorReporter fErrorReporter;
350         ErrorReporter* fOldErrorReporter;
351         bool fOldEncounteredFatalError;
352     };
353 
354     Compiler& fCompiler;
355     ProgramSettings fSettings;
356     ErrorReporter* fErrorReporter;
357     bool fEncounteredFatalError;
358     ProgramKind fKind;
359     std::unique_ptr<std::string> fText;
360     Lexer fLexer;
361     // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
362     // stack on pathological inputs
363     int fDepth = 0;
364     Token fPushback;
365 };
366 
367 }  // namespace SkSL
368 
369 #endif
370