1/*
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 */
7
8#ifndef SKSL_PARSER
9#define SKSL_PARSER
10
11#include <vector>
12#include <memory>
13#include <unordered_map>
14#include <unordered_set>
15#include "src/sksl/SkSLASTFile.h"
16#include "src/sksl/SkSLASTNode.h"
17#include "src/sksl/SkSLErrorReporter.h"
18#include "src/sksl/SkSLLexer.h"
19#include "src/sksl/ir/SkSLLayout.h"
20
21struct yy_buffer_state;
22#define YY_TYPEDEF_YY_BUFFER_STATE
23typedef struct yy_buffer_state *YY_BUFFER_STATE;
24
25namespace SkSL {
26
27struct Modifiers;
28class SymbolTable;
29
30/**
31 * Consumes .sksl text and produces an abstract syntax tree describing the contents.
32 */
33class Parser {
34public:
35 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,
71 MARKER,
72 WHEN,
73 KEY,
74 TRACKED,
75 SRGB_UNPREMUL,
76 CTYPE,
77 SKPMCOLOR4F,
78 SKV4,
79 SKRECT,
80 SKIRECT,
81 SKPMCOLOR,
82 SKM44,
83 BOOL,
84 INT,
85 FLOAT,
86 };
87
88 Parser(const char* text, size_t length, SymbolTable& symbols, ErrorReporter& errors);
89
90 /**
91 * 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.
93 */
94 std::unique_ptr<ASTFile> file();
95
96 StringFragment text(Token token);
97
98 Position position(Token token);
99
100private:
101 static void InitLayoutMap();
102
103 /**
104 * Return the next token, including whitespace tokens, from the parse stream.
105 */
106 Token nextRawToken();
107
108 /**
109 * Return the next non-whitespace token from the parse stream.
110 */
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 /**
121 * Returns the next non-whitespace token without consuming it from the stream.
122 */
123 Token peek();
124
125 /**
126 * 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 /**
132 * 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:
134 *
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 */
140 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
141 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
142
143 void error(Token token, String msg);
144 void error(int offset, String msg);
145 /**
146 * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
147 * always return true.
148 */
149 bool isType(StringFragment name);
150
151 // The pointer to the node may be invalidated by modifying the fNodes vector
152 ASTNode& getNode(ASTNode::ID id) {
153 SkASSERT(id.fValue >= 0 && id.fValue < (int) fFile->fNodes.size());
154 return fFile->fNodes[id.fValue];
155 }
156
157 // these functions parse individual grammar rules from the current parse position; you probably
158 // don't need to call any of these outside of the parser. The function declarations in the .cpp
159 // file have comments describing the grammar rules.
160
161 ASTNode::ID precision();
162
163 ASTNode::ID directive();
164
165 ASTNode::ID section();
166
167 ASTNode::ID enumDeclaration();
168
169 ASTNode::ID declaration();
170
171 ASTNode::ID varDeclarations();
172
173 ASTNode::ID structDeclaration();
174
175 ASTNode::ID structVarDeclaration(Modifiers modifiers);
176
177 ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name);
178
179 ASTNode::ID parameter();
180
181 int layoutInt();
182
183 StringFragment layoutIdentifier();
184
185 StringFragment layoutCode();
186
187 Layout::Key layoutKey();
188
189 Layout::CType layoutCType();
190
191 Layout layout();
192
193 Modifiers modifiers();
194
195 Modifiers modifiersWithDefaults(int defaultFlags);
196
197 ASTNode::ID statement();
198
199 ASTNode::ID type();
200
201 ASTNode::ID interfaceBlock(Modifiers mods);
202
203 ASTNode::ID ifStatement();
204
205 ASTNode::ID doStatement();
206
207 ASTNode::ID whileStatement();
208
209 ASTNode::ID forStatement();
210
211 ASTNode::ID switchCase();
212
213 ASTNode::ID switchStatement();
214
215 ASTNode::ID returnStatement();
216
217 ASTNode::ID breakStatement();
218
219 ASTNode::ID continueStatement();
220
221 ASTNode::ID discardStatement();
222
223 ASTNode::ID block();
224
225 ASTNode::ID expressionStatement();
226
227 ASTNode::ID expression();
228
229 ASTNode::ID assignmentExpression();
230
231 ASTNode::ID ternaryExpression();
232
233 ASTNode::ID logicalOrExpression();
234
235 ASTNode::ID logicalXorExpression();
236
237 ASTNode::ID logicalAndExpression();
238
239 ASTNode::ID bitwiseOrExpression();
240
241 ASTNode::ID bitwiseXorExpression();
242
243 ASTNode::ID bitwiseAndExpression();
244
245 ASTNode::ID equalityExpression();
246
247 ASTNode::ID relationalExpression();
248
249 ASTNode::ID shiftExpression();
250
251 ASTNode::ID additiveExpression();
252
253 ASTNode::ID multiplicativeExpression();
254
255 ASTNode::ID unaryExpression();
256
257 ASTNode::ID postfixExpression();
258
259 ASTNode::ID suffix(ASTNode::ID base);
260
261 ASTNode::ID term();
262
263 bool intLiteral(SKSL_INT* dest);
264
265 bool floatLiteral(SKSL_FLOAT* dest);
266
267 bool boolLiteral(bool* dest);
268
269 bool identifier(StringFragment* dest);
270
271 static std::unordered_map<String, LayoutToken>* layoutTokens;
272
273 const char* fText;
274 Lexer fLexer;
275 YY_BUFFER_STATE fBuffer;
276 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
277 // stack on pathological inputs
278 int fDepth = 0;
279 Token fPushback;
280 SymbolTable& fSymbols;
281 ErrorReporter& fErrors;
282
283 std::unique_ptr<ASTFile> fFile;
284
285 friend class AutoDepth;
286 friend class HCodeGenerator;
287};
288
289} // namespace SkSL
290
291#endif
292