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