blob: 6d5c927921973a3679f3c0c958029fed472f8d11 [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
21struct yy_buffer_state;
22#define YY_TYPEDEF_YY_BUFFER_STATE
23typedef struct yy_buffer_state *YY_BUFFER_STATE;
24
25namespace SkSL {
26
Ethan Nicholas11d53972016-11-28 11:23:23 -050027struct Modifiers;
ethannicholasb3058bd2016-07-01 08:22:01 -070028class SymbolTable;
29
30/**
31 * Consumes .sksl text and produces an abstract syntax tree describing the contents.
32 */
33class Parser {
34public:
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040035 enum class LayoutToken {
36 LOCATION,
37 OFFSET,
38 BINDING,
39 INDEX,
40 SET,
41 BUILTIN,
42 INPUT_ATTACHMENT_INDEX,
43 ORIGIN_UPPER_LEFT,
44 OVERRIDE_COVERAGE,
45 BLEND_SUPPORT_ALL_EQUATIONS,
46 BLEND_SUPPORT_MULTIPLY,
47 BLEND_SUPPORT_SCREEN,
48 BLEND_SUPPORT_OVERLAY,
49 BLEND_SUPPORT_DARKEN,
50 BLEND_SUPPORT_LIGHTEN,
51 BLEND_SUPPORT_COLORDODGE,
52 BLEND_SUPPORT_COLORBURN,
53 BLEND_SUPPORT_HARDLIGHT,
54 BLEND_SUPPORT_SOFTLIGHT,
55 BLEND_SUPPORT_DIFFERENCE,
56 BLEND_SUPPORT_EXCLUSION,
57 BLEND_SUPPORT_HSL_HUE,
58 BLEND_SUPPORT_HSL_SATURATION,
59 BLEND_SUPPORT_HSL_COLOR,
60 BLEND_SUPPORT_HSL_LUMINOSITY,
61 PUSH_CONSTANT,
62 POINTS,
63 LINES,
64 LINE_STRIP,
65 LINES_ADJACENCY,
66 TRIANGLES,
67 TRIANGLE_STRIP,
68 TRIANGLES_ADJACENCY,
69 MAX_VERTICES,
70 INVOCATIONS,
Brian Osmanf59a9612020-04-15 14:18:13 -040071 MARKER,
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040072 WHEN,
73 KEY,
Ethan Nicholas78aceb22018-08-31 16:13:58 -040074 TRACKED,
Brian Osmanb32d66b2020-04-30 17:12:03 -040075 SRGB_UNPREMUL,
Michael Ludwiga4275592018-08-31 10:52:47 -040076 CTYPE,
Brian Osmanf28e55d2018-10-03 16:35:54 -040077 SKPMCOLOR4F,
Mike Reedb26b4e72020-01-22 14:31:21 -050078 SKV4,
Ethan Nicholas78aceb22018-08-31 16:13:58 -040079 SKRECT,
80 SKIRECT,
81 SKPMCOLOR,
Mike Reedb26b4e72020-01-22 14:31:21 -050082 SKM44,
Ethan Nicholasc1c686b2019-04-02 17:30:23 -040083 BOOL,
84 INT,
85 FLOAT,
Ethan Nicholasb93af7e2018-07-24 11:28:52 -040086 };
87
Ethan Nicholasc18bb512020-07-28 14:46:53 -040088 Parser(const char* text, size_t length, SymbolTable& symbols, ErrorReporter& errors);
ethannicholasb3058bd2016-07-01 08:22:01 -070089
90 /**
Ethan Nicholasfc994162019-06-06 10:04:27 -040091 * Consumes a complete .sksl file and returns the parse tree. Errors are reported via the
92 * ErrorReporter; the return value may contain some declarations even when errors have occurred.
ethannicholasb3058bd2016-07-01 08:22:01 -070093 */
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050094 std::unique_ptr<ASTFile> compilationUnit();
ethannicholasb3058bd2016-07-01 08:22:01 -070095
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070096 StringFragment text(Token token);
97
98 Position position(Token token);
99
ethannicholasb3058bd2016-07-01 08:22:01 -0700100private:
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400101 static void InitLayoutMap();
102
ethannicholasb3058bd2016-07-01 08:22:01 -0700103 /**
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700104 * Return the next token, including whitespace tokens, from the parse stream.
Ethan Nicholas762466e2017-06-29 10:03:38 -0400105 */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700106 Token nextRawToken();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107
108 /**
109 * Return the next non-whitespace token from the parse stream.
ethannicholasb3058bd2016-07-01 08:22:01 -0700110 */
111 Token nextToken();
112
113 /**
114 * Push a token back onto the parse stream, so that it is the next one read. Only a single level
115 * of pushback is supported (that is, it is an error to call pushback() twice in a row without
116 * an intervening nextToken()).
117 */
118 void pushback(Token t);
119
120 /**
Ethan Nicholas762466e2017-06-29 10:03:38 -0400121 * Returns the next non-whitespace token without consuming it from the stream.
ethannicholasb3058bd2016-07-01 08:22:01 -0700122 */
123 Token peek();
124
125 /**
Ethan Nicholas0c9d13b2017-05-08 16:18:19 -0400126 * Checks to see if the next token is of the specified type. If so, stores it in result (if
127 * result is non-null) and returns true. Otherwise, pushes it back and returns false.
128 */
129 bool checkNext(Token::Kind kind, Token* result = nullptr);
130
131 /**
Ethan Nicholas762466e2017-06-29 10:03:38 -0400132 * Reads the next non-whitespace token and generates an error if it is not the expected type.
133 * The 'expected' string is part of the error message, which reads:
ethannicholasb3058bd2016-07-01 08:22:01 -0700134 *
135 * "expected <expected>, but found '<actual text>'"
136 *
137 * If 'result' is non-null, it is set to point to the token that was read.
138 * Returns true if the read token was as expected, false otherwise.
139 */
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500140 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700141 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700142
John Stiles2630ea32020-12-04 10:51:21 -0500143 /**
144 * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
145 * If the token was actually a type, generates an error message of the form:
146 *
147 * "expected an identifier, but found type 'float2'"
148 */
149 bool expectIdentifier(Token* result);
150
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700151 void error(Token token, String msg);
152 void error(int offset, String msg);
ethannicholasb3058bd2016-07-01 08:22:01 -0700153 /**
154 * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
155 * always return true.
156 */
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700157 bool isType(StringFragment name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700158
Ethan Nicholasfc994162019-06-06 10:04:27 -0400159 // The pointer to the node may be invalidated by modifying the fNodes vector
160 ASTNode& getNode(ASTNode::ID id) {
Ethan Nicholas0c8582e2019-07-19 09:26:46 -0400161 SkASSERT(id.fValue >= 0 && id.fValue < (int) fFile->fNodes.size());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400162 return fFile->fNodes[id.fValue];
163 }
164
ethannicholasb3058bd2016-07-01 08:22:01 -0700165 // these functions parse individual grammar rules from the current parse position; you probably
166 // don't need to call any of these outside of the parser. The function declarations in the .cpp
167 // file have comments describing the grammar rules.
168
Ethan Nicholasfc994162019-06-06 10:04:27 -0400169 ASTNode::ID precision();
ethannicholasb3058bd2016-07-01 08:22:01 -0700170
Ethan Nicholasfc994162019-06-06 10:04:27 -0400171 ASTNode::ID directive();
ethannicholasb3058bd2016-07-01 08:22:01 -0700172
Ethan Nicholasfc994162019-06-06 10:04:27 -0400173 ASTNode::ID section();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400174
Ethan Nicholasfc994162019-06-06 10:04:27 -0400175 ASTNode::ID enumDeclaration();
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500176
Ethan Nicholasfc994162019-06-06 10:04:27 -0400177 ASTNode::ID declaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700178
Ethan Nicholasfc994162019-06-06 10:04:27 -0400179 ASTNode::ID varDeclarations();
ethannicholasb3058bd2016-07-01 08:22:01 -0700180
Ethan Nicholasfc994162019-06-06 10:04:27 -0400181 ASTNode::ID structDeclaration();
ethannicholasb3058bd2016-07-01 08:22:01 -0700182
Ethan Nicholasfc994162019-06-06 10:04:27 -0400183 ASTNode::ID structVarDeclaration(Modifiers modifiers);
ethannicholasb3058bd2016-07-01 08:22:01 -0700184
Ethan Nicholasfc994162019-06-06 10:04:27 -0400185 ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700186
Ethan Nicholasfc994162019-06-06 10:04:27 -0400187 ASTNode::ID parameter();
ethannicholasb3058bd2016-07-01 08:22:01 -0700188
189 int layoutInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400190
Ethan Nicholasd608c092017-10-26 09:30:08 -0400191 StringFragment layoutIdentifier();
192
Ethan Nicholasfc994162019-06-06 10:04:27 -0400193 StringFragment layoutCode();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400194
195 Layout::Key layoutKey();
196
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400197 Layout::CType layoutCType();
198
Ethan Nicholas11d53972016-11-28 11:23:23 -0500199 Layout layout();
ethannicholasb3058bd2016-07-01 08:22:01 -0700200
Ethan Nicholas11d53972016-11-28 11:23:23 -0500201 Modifiers modifiers();
ethannicholasb3058bd2016-07-01 08:22:01 -0700202
Ethan Nicholas11d53972016-11-28 11:23:23 -0500203 Modifiers modifiersWithDefaults(int defaultFlags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700204
Ethan Nicholasfc994162019-06-06 10:04:27 -0400205 ASTNode::ID statement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700206
Ethan Nicholasfc994162019-06-06 10:04:27 -0400207 ASTNode::ID type();
ethannicholasb3058bd2016-07-01 08:22:01 -0700208
Ethan Nicholasfc994162019-06-06 10:04:27 -0400209 ASTNode::ID interfaceBlock(Modifiers mods);
ethannicholasb3058bd2016-07-01 08:22:01 -0700210
Ethan Nicholasfc994162019-06-06 10:04:27 -0400211 ASTNode::ID ifStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700212
Ethan Nicholasfc994162019-06-06 10:04:27 -0400213 ASTNode::ID doStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700214
Ethan Nicholasfc994162019-06-06 10:04:27 -0400215 ASTNode::ID whileStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700216
Ethan Nicholasfc994162019-06-06 10:04:27 -0400217 ASTNode::ID forStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700218
Ethan Nicholasfc994162019-06-06 10:04:27 -0400219 ASTNode::ID switchCase();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500220
Ethan Nicholasfc994162019-06-06 10:04:27 -0400221 ASTNode::ID switchStatement();
Ethan Nicholasaf197692017-02-27 13:26:45 -0500222
Ethan Nicholasfc994162019-06-06 10:04:27 -0400223 ASTNode::ID returnStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700224
Ethan Nicholasfc994162019-06-06 10:04:27 -0400225 ASTNode::ID breakStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700226
Ethan Nicholasfc994162019-06-06 10:04:27 -0400227 ASTNode::ID continueStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700228
Ethan Nicholasfc994162019-06-06 10:04:27 -0400229 ASTNode::ID discardStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700230
Ethan Nicholasfc994162019-06-06 10:04:27 -0400231 ASTNode::ID block();
ethannicholasb3058bd2016-07-01 08:22:01 -0700232
Ethan Nicholasfc994162019-06-06 10:04:27 -0400233 ASTNode::ID expressionStatement();
ethannicholasb3058bd2016-07-01 08:22:01 -0700234
Ethan Nicholasfc994162019-06-06 10:04:27 -0400235 ASTNode::ID expression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700236
Ethan Nicholasfc994162019-06-06 10:04:27 -0400237 ASTNode::ID assignmentExpression();
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400238
Ethan Nicholasfc994162019-06-06 10:04:27 -0400239 ASTNode::ID ternaryExpression();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400240
Ethan Nicholasfc994162019-06-06 10:04:27 -0400241 ASTNode::ID logicalOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700242
Ethan Nicholasfc994162019-06-06 10:04:27 -0400243 ASTNode::ID logicalXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700244
Ethan Nicholasfc994162019-06-06 10:04:27 -0400245 ASTNode::ID logicalAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700246
Ethan Nicholasfc994162019-06-06 10:04:27 -0400247 ASTNode::ID bitwiseOrExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700248
Ethan Nicholasfc994162019-06-06 10:04:27 -0400249 ASTNode::ID bitwiseXorExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700250
Ethan Nicholasfc994162019-06-06 10:04:27 -0400251 ASTNode::ID bitwiseAndExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700252
Ethan Nicholasfc994162019-06-06 10:04:27 -0400253 ASTNode::ID equalityExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700254
Ethan Nicholasfc994162019-06-06 10:04:27 -0400255 ASTNode::ID relationalExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700256
Ethan Nicholasfc994162019-06-06 10:04:27 -0400257 ASTNode::ID shiftExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700258
Ethan Nicholasfc994162019-06-06 10:04:27 -0400259 ASTNode::ID additiveExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700260
Ethan Nicholasfc994162019-06-06 10:04:27 -0400261 ASTNode::ID multiplicativeExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700262
Ethan Nicholasfc994162019-06-06 10:04:27 -0400263 ASTNode::ID unaryExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700264
Ethan Nicholasfc994162019-06-06 10:04:27 -0400265 ASTNode::ID postfixExpression();
ethannicholasb3058bd2016-07-01 08:22:01 -0700266
Ethan Nicholasfc994162019-06-06 10:04:27 -0400267 ASTNode::ID suffix(ASTNode::ID base);
ethannicholasb3058bd2016-07-01 08:22:01 -0700268
Ethan Nicholasfc994162019-06-06 10:04:27 -0400269 ASTNode::ID term();
ethannicholasb3058bd2016-07-01 08:22:01 -0700270
Ethan Nicholasfc994162019-06-06 10:04:27 -0400271 bool intLiteral(SKSL_INT* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700272
Ethan Nicholasfc994162019-06-06 10:04:27 -0400273 bool floatLiteral(SKSL_FLOAT* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700274
275 bool boolLiteral(bool* dest);
276
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700277 bool identifier(StringFragment* dest);
ethannicholasb3058bd2016-07-01 08:22:01 -0700278
John Stiles3b209362020-11-16 17:03:10 -0500279 template <typename... Args> ASTNode::ID createNode(Args&&... args);
280
281 ASTNode::ID addChild(ASTNode::ID target, ASTNode::ID child);
282
283 void createEmptyChild(ASTNode::ID target);
284
Brian Salomon140f3da2018-08-23 13:51:27 +0000285 static std::unordered_map<String, LayoutToken>* layoutTokens;
Ethan Nicholasb93af7e2018-07-24 11:28:52 -0400286
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700287 const char* fText;
288 Lexer fLexer;
ethannicholasb3058bd2016-07-01 08:22:01 -0700289 YY_BUFFER_STATE fBuffer;
ethannicholascad64162016-10-27 10:54:02 -0700290 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
291 // stack on pathological inputs
292 int fDepth = 0;
ethannicholasb3058bd2016-07-01 08:22:01 -0700293 Token fPushback;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400294 SymbolTable& fSymbols;
ethannicholasb3058bd2016-07-01 08:22:01 -0700295 ErrorReporter& fErrors;
ethannicholascad64162016-10-27 10:54:02 -0700296
Ethan Nicholasfc994162019-06-06 10:04:27 -0400297 std::unique_ptr<ASTFile> fFile;
298
ethannicholascad64162016-10-27 10:54:02 -0700299 friend class AutoDepth;
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500300 friend class HCodeGenerator;
ethannicholasb3058bd2016-07-01 08:22:01 -0700301};
302
John Stilesa6841be2020-08-06 14:11:56 -0400303} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700304
305#endif