blob: c2a679f3a7ab171ad8da90d3ed69b52bd45cf511 [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_PARSER
9#define SKSL_PARSER
10
ethannicholasb3058bd2016-07-01 08:22:01 -070011#include <vector>
12#include <memory>
Ethan Nicholas3614d9a2017-02-15 12:33:30 -050013#include <unordered_map>
ethannicholasb3058bd2016-07-01 08:22:01 -070014#include <unordered_set>
Ethan Nicholasfc994162019-06-06 10:04:27 -040015#include "src/sksl/SkSLASTFile.h"
Mike Klein4b432fa2019-06-06 11:44:05 -050016#include "src/sksl/SkSLASTNode.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/sksl/SkSLErrorReporter.h"
18#include "src/sksl/SkSLLexer.h"
19#include "src/sksl/ir/SkSLLayout.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070020
ethannicholasb3058bd2016-07-01 08:22:01 -070021namespace SkSL {
22
Ethan Nicholas11d53972016-11-28 11:23:23 -050023struct Modifiers;
ethannicholasb3058bd2016-07-01 08:22:01 -070024class SymbolTable;
25
26/**
27 * Consumes .sksl text and produces an abstract syntax tree describing the contents.
28 */
29class Parser {
30public:
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040031 enum class LayoutToken {
32 LOCATION,
33 OFFSET,
34 BINDING,
35 INDEX,
36 SET,
37 BUILTIN,
38 INPUT_ATTACHMENT_INDEX,
39 ORIGIN_UPPER_LEFT,
40 OVERRIDE_COVERAGE,
41 BLEND_SUPPORT_ALL_EQUATIONS,
42 BLEND_SUPPORT_MULTIPLY,
43 BLEND_SUPPORT_SCREEN,
44 BLEND_SUPPORT_OVERLAY,
45 BLEND_SUPPORT_DARKEN,
46 BLEND_SUPPORT_LIGHTEN,
47 BLEND_SUPPORT_COLORDODGE,
48 BLEND_SUPPORT_COLORBURN,
49 BLEND_SUPPORT_HARDLIGHT,
50 BLEND_SUPPORT_SOFTLIGHT,
51 BLEND_SUPPORT_DIFFERENCE,
52 BLEND_SUPPORT_EXCLUSION,
53 BLEND_SUPPORT_HSL_HUE,
54 BLEND_SUPPORT_HSL_SATURATION,
55 BLEND_SUPPORT_HSL_COLOR,
56 BLEND_SUPPORT_HSL_LUMINOSITY,
57 PUSH_CONSTANT,
58 POINTS,
59 LINES,
60 LINE_STRIP,
61 LINES_ADJACENCY,
62 TRIANGLES,
63 TRIANGLE_STRIP,
64 TRIANGLES_ADJACENCY,
65 MAX_VERTICES,
66 INVOCATIONS,
Brian Osmanf59a9612020-04-15 14:18:13 -040067 MARKER,
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040068 WHEN,
69 KEY,
Ethan Nicholas78aceb22018-08-31 16:13:58 -040070 TRACKED,
Brian Osmanb32d66b2020-04-30 17:12:03 -040071 SRGB_UNPREMUL,
Michael Ludwiga4275592018-08-31 10:52:47 -040072 CTYPE,
Brian Osmanf28e55d2018-10-03 16:35:54 -040073 SKPMCOLOR4F,
Mike Reedb26b4e72020-01-22 14:31:21 -050074 SKV4,
Ethan Nicholas78aceb22018-08-31 16:13:58 -040075 SKRECT,
76 SKIRECT,
77 SKPMCOLOR,
Mike Reedb26b4e72020-01-22 14:31:21 -050078 SKM44,
Ethan Nicholasc1c686b2019-04-02 17:30:23 -040079 BOOL,
80 INT,
81 FLOAT,
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040082 };
83
Ethan Nicholasc18bb512020-07-28 14:46:53 -040084 Parser(const char* text, size_t length, SymbolTable& symbols, ErrorReporter& errors);
ethannicholasb3058bd2016-07-01 08:22:01 -070085
86 /**
Ethan Nicholasfc994162019-06-06 10:04:27 -040087 * Consumes a complete .sksl file and returns the parse tree. Errors are reported via the
88 * ErrorReporter; the return value may contain some declarations even when errors have occurred.
ethannicholasb3058bd2016-07-01 08:22:01 -070089 */
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050090 std::unique_ptr<ASTFile> compilationUnit();
ethannicholasb3058bd2016-07-01 08:22:01 -070091
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070092 StringFragment text(Token token);
93
94 Position position(Token token);
95
ethannicholasb3058bd2016-07-01 08:22:01 -070096private:
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040097 static void InitLayoutMap();
98
ethannicholasb3058bd2016-07-01 08:22:01 -070099 /**
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700100 * Return the next token, including whitespace tokens, from the parse stream.
Ethan Nicholas762466e2017-06-29 10:03:38 -0400101 */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700102 Token nextRawToken();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400103
104 /**
105 * Return the next non-whitespace token from the parse stream.
ethannicholasb3058bd2016-07-01 08:22:01 -0700106 */
107 Token nextToken();
108
109 /**
110 * Push a token back onto the parse stream, so that it is the next one read. Only a single level
111 * of pushback is supported (that is, it is an error to call pushback() twice in a row without
112 * an intervening nextToken()).
113 */
114 void pushback(Token t);
115
116 /**
Ethan Nicholas762466e2017-06-29 10:03:38 -0400117 * Returns the next non-whitespace token without consuming it from the stream.
ethannicholasb3058bd2016-07-01 08:22:01 -0700118 */
119 Token peek();
120
121 /**
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400122 * Checks to see if the next token is of the specified type. If so, stores it in result (if
123 * result is non-null) and returns true. Otherwise, pushes it back and returns false.
124 */
125 bool checkNext(Token::Kind kind, Token* result = nullptr);
126
127 /**
Ethan Nicholas762466e2017-06-29 10:03:38 -0400128 * Reads the next non-whitespace token and generates an error if it is not the expected type.
129 * The 'expected' string is part of the error message, which reads:
ethannicholasb3058bd2016-07-01 08:22:01 -0700130 *
131 * "expected <expected>, but found '<actual text>'"
132 *
133 * If 'result' is non-null, it is set to point to the token that was read.
134 * Returns true if the read token was as expected, false otherwise.
135 */
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500136 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700137 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700138
John Stiles2630ea32020-12-04 10:51:21 -0500139 /**
140 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
141 * If the token was actually a type, generates an error message of the form:
142 *
143 * "expected an identifier, but found type 'float2'"
144 */
145 bool expectIdentifier(Token* result);
146
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700147 void error(Token token, String msg);
148 void error(int offset, String msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700149 /**
150 * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
151 * always return true.
152 */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700153 bool isType(StringFragment name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700154
Ethan Nicholasfc994162019-06-06 10:04:27 -0400155 // The pointer to the node may be invalidated by modifying the fNodes vector
156 ASTNode& getNode(ASTNode::ID id) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -0400157 SkASSERT(id.fValue >= 0 && id.fValue < (int) fFile->fNodes.size());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400158 return fFile->fNodes[id.fValue];
159 }
160
ethannicholasb3058bd2016-07-01 08:22:01 -0700161 // these functions parse individual grammar rules from the current parse position; you probably
162 // don't need to call any of these outside of the parser. The function declarations in the .cpp
163 // file have comments describing the grammar rules.
164
Ethan Nicholasfc994162019-06-06 10:04:27 -0400165 ASTNode::ID precision();
ethannicholasb3058bd2016-07-01 08:22:01 -0700166
Ethan Nicholasfc994162019-06-06 10:04:27 -0400167 ASTNode::ID directive();
ethannicholasb3058bd2016-07-01 08:22:01 -0700168
Ethan Nicholasfc994162019-06-06 10:04:27 -0400169 ASTNode::ID section();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400170
Ethan Nicholasfc994162019-06-06 10:04:27 -0400171 ASTNode::ID enumDeclaration();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500172
Ethan Nicholasfc994162019-06-06 10:04:27 -0400173 ASTNode::ID declaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700174
John Stiles76389b72021-01-25 13:49:05 -0500175 ASTNode::ID varDeclarationsOrExpressionStatement();
176
Ethan Nicholasfc994162019-06-06 10:04:27 -0400177 ASTNode::ID varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700178
Ethan Nicholasfc994162019-06-06 10:04:27 -0400179 ASTNode::ID structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700180
Ethan Nicholasfc994162019-06-06 10:04:27 -0400181 ASTNode::ID structVarDeclaration(Modifiers modifiers);
ethannicholasb3058bd2016-07-01 08:22:01 -0700182
Ethan Nicholasfc994162019-06-06 10:04:27 -0400183 ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700184
Ethan Nicholasfc994162019-06-06 10:04:27 -0400185 ASTNode::ID parameter();
ethannicholasb3058bd2016-07-01 08:22:01 -0700186
187 int layoutInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400188
Ethan Nicholasd608c092017-10-26 09:30:08 -0400189 StringFragment layoutIdentifier();
190
Ethan Nicholasfc994162019-06-06 10:04:27 -0400191 StringFragment layoutCode();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400192
193 Layout::Key layoutKey();
194
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400195 Layout::CType layoutCType();
196
Ethan Nicholas11d53972016-11-28 11:23:23 -0500197 Layout layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700198
Ethan Nicholas11d53972016-11-28 11:23:23 -0500199 Modifiers modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700200
Ethan Nicholas11d53972016-11-28 11:23:23 -0500201 Modifiers modifiersWithDefaults(int defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700202
Ethan Nicholasfc994162019-06-06 10:04:27 -0400203 ASTNode::ID statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700204
Ethan Nicholasfc994162019-06-06 10:04:27 -0400205 ASTNode::ID type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700206
Ethan Nicholasfc994162019-06-06 10:04:27 -0400207 ASTNode::ID interfaceBlock(Modifiers mods);
ethannicholasb3058bd2016-07-01 08:22:01 -0700208
Ethan Nicholasfc994162019-06-06 10:04:27 -0400209 ASTNode::ID ifStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700210
Ethan Nicholasfc994162019-06-06 10:04:27 -0400211 ASTNode::ID doStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700212
Ethan Nicholasfc994162019-06-06 10:04:27 -0400213 ASTNode::ID whileStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700214
Ethan Nicholasfc994162019-06-06 10:04:27 -0400215 ASTNode::ID forStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700216
Ethan Nicholasfc994162019-06-06 10:04:27 -0400217 ASTNode::ID switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500218
Ethan Nicholasfc994162019-06-06 10:04:27 -0400219 ASTNode::ID switchStatement();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500220
Ethan Nicholasfc994162019-06-06 10:04:27 -0400221 ASTNode::ID returnStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700222
Ethan Nicholasfc994162019-06-06 10:04:27 -0400223 ASTNode::ID breakStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700224
Ethan Nicholasfc994162019-06-06 10:04:27 -0400225 ASTNode::ID continueStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700226
Ethan Nicholasfc994162019-06-06 10:04:27 -0400227 ASTNode::ID discardStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700228
Ethan Nicholasfc994162019-06-06 10:04:27 -0400229 ASTNode::ID block();
ethannicholasb3058bd2016-07-01 08:22:01 -0700230
Ethan Nicholasfc994162019-06-06 10:04:27 -0400231 ASTNode::ID expressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700232
Ethan Nicholasfc994162019-06-06 10:04:27 -0400233 ASTNode::ID expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700234
Ethan Nicholasfc994162019-06-06 10:04:27 -0400235 ASTNode::ID assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400236
Ethan Nicholasfc994162019-06-06 10:04:27 -0400237 ASTNode::ID ternaryExpression();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400238
Ethan Nicholasfc994162019-06-06 10:04:27 -0400239 ASTNode::ID logicalOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700240
Ethan Nicholasfc994162019-06-06 10:04:27 -0400241 ASTNode::ID logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700242
Ethan Nicholasfc994162019-06-06 10:04:27 -0400243 ASTNode::ID logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700244
Ethan Nicholasfc994162019-06-06 10:04:27 -0400245 ASTNode::ID bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700246
Ethan Nicholasfc994162019-06-06 10:04:27 -0400247 ASTNode::ID bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700248
Ethan Nicholasfc994162019-06-06 10:04:27 -0400249 ASTNode::ID bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700250
Ethan Nicholasfc994162019-06-06 10:04:27 -0400251 ASTNode::ID equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700252
Ethan Nicholasfc994162019-06-06 10:04:27 -0400253 ASTNode::ID relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700254
Ethan Nicholasfc994162019-06-06 10:04:27 -0400255 ASTNode::ID shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700256
Ethan Nicholasfc994162019-06-06 10:04:27 -0400257 ASTNode::ID additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700258
Ethan Nicholasfc994162019-06-06 10:04:27 -0400259 ASTNode::ID multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700260
Ethan Nicholasfc994162019-06-06 10:04:27 -0400261 ASTNode::ID unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700262
Ethan Nicholasfc994162019-06-06 10:04:27 -0400263 ASTNode::ID postfixExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700264
Ethan Nicholasfc994162019-06-06 10:04:27 -0400265 ASTNode::ID suffix(ASTNode::ID base);
ethannicholasb3058bd2016-07-01 08:22:01 -0700266
Ethan Nicholasfc994162019-06-06 10:04:27 -0400267 ASTNode::ID term();
ethannicholasb3058bd2016-07-01 08:22:01 -0700268
Ethan Nicholasfc994162019-06-06 10:04:27 -0400269 bool intLiteral(SKSL_INT* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700270
Ethan Nicholasfc994162019-06-06 10:04:27 -0400271 bool floatLiteral(SKSL_FLOAT* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700272
273 bool boolLiteral(bool* dest);
274
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700275 bool identifier(StringFragment* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700276
John Stiles3b209362020-11-16 17:03:10 -0500277 template <typename... Args> ASTNode::ID createNode(Args&&... args);
278
279 ASTNode::ID addChild(ASTNode::ID target, ASTNode::ID child);
280
281 void createEmptyChild(ASTNode::ID target);
282
John Stiles8d3642e2021-01-22 09:50:04 -0500283 class Checkpoint {
284 public:
285 Checkpoint(Parser* p) : fParser(p) {
286 fPushbackCheckpoint = fParser->fPushback;
287 fLexerCheckpoint = fParser->fLexer.getCheckpoint();
288 fASTCheckpoint = fParser->fFile->fNodes.size();
289 fErrorCount = fParser->fErrors.errorCount();
290 }
291
292 void rewind() {
293 fParser->fPushback = fPushbackCheckpoint;
294 fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
295 fParser->fFile->fNodes.resize(fASTCheckpoint);
296 fParser->fErrors.setErrorCount(fErrorCount);
297 }
298
299 private:
300 Parser* fParser;
301 Token fPushbackCheckpoint;
302 int32_t fLexerCheckpoint;
303 size_t fASTCheckpoint;
304 int fErrorCount;
305 };
306
Brian Salomon140f3da2018-08-23 13:51:27 +0000307 static std::unordered_map<String, LayoutToken>* layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400308
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700309 const char* fText;
310 Lexer fLexer;
ethannicholascad64162016-10-27 10:54:02 -0700311 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
312 // stack on pathological inputs
313 int fDepth = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700314 Token fPushback;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400315 SymbolTable& fSymbols;
ethannicholasb3058bd2016-07-01 08:22:01 -0700316 ErrorReporter& fErrors;
ethannicholascad64162016-10-27 10:54:02 -0700317
Ethan Nicholasfc994162019-06-06 10:04:27 -0400318 std::unique_ptr<ASTFile> fFile;
319
ethannicholascad64162016-10-27 10:54:02 -0700320 friend class AutoDepth;
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500321 friend class HCodeGenerator;
ethannicholasb3058bd2016-07-01 08:22:01 -0700322};
323
John Stilesa6841be2020-08-06 14:11:56 -0400324} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700325
326#endif