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 WHEN,
72 KEY,
73 TRACKED,
74 CTYPE,
75 SKPMCOLOR4F,
76 SKV4,
77 SKRECT,
78 SKIRECT,
79 SKPMCOLOR,
80 SKM44,
81 BOOL,
82 INT,
83 FLOAT,
84 };
85
86 Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors);
87
88 /**
89 * Consumes a complete .sksl file and returns the parse tree. Errors are reported via the
90 * ErrorReporter; the return value may contain some declarations even when errors have occurred.
91 */
92 std::unique_ptr<ASTFile> file();
93
94 StringFragment text(Token token);
95
96 Position position(Token token);
97
98private:
99 static void InitLayoutMap();
100
101 /**
102 * Return the next token, including whitespace tokens, from the parse stream.
103 */
104 Token nextRawToken();
105
106 /**
107 * Return the next non-whitespace token from the parse stream.
108 */
109 Token nextToken();
110
111 /**
112 * Push a token back onto the parse stream, so that it is the next one read. Only a single level
113 * of pushback is supported (that is, it is an error to call pushback() twice in a row without
114 * an intervening nextToken()).
115 */
116 void pushback(Token t);
117
118 /**
119 * Returns the next non-whitespace token without consuming it from the stream.
120 */
121 Token peek();
122
123 /**
124 * Checks to see if the next token is of the specified type. If so, stores it in result (if
125 * result is non-null) and returns true. Otherwise, pushes it back and returns false.
126 */
127 bool checkNext(Token::Kind kind, Token* result = nullptr);
128
129 /**
130 * Reads the next non-whitespace token and generates an error if it is not the expected type.
131 * The 'expected' string is part of the error message, which reads:
132 *
133 * "expected <expected>, but found '<actual text>'"
134 *
135 * If 'result' is non-null, it is set to point to the token that was read.
136 * Returns true if the read token was as expected, false otherwise.
137 */
138 bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
139 bool expect(Token::Kind kind, String expected, Token* result = nullptr);
140
141 void error(Token token, String msg);
142 void error(int offset, String msg);
143 /**
144 * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
145 * always return true.
146 */
147 bool isType(StringFragment name);
148
149 // The pointer to the node may be invalidated by modifying the fNodes vector
150 ASTNode& getNode(ASTNode::ID id) {
151 SkASSERT(id.fValue >= 0 && id.fValue < (int) fFile->fNodes.size());
152 return fFile->fNodes[id.fValue];
153 }
154
155 // these functions parse individual grammar rules from the current parse position; you probably
156 // don't need to call any of these outside of the parser. The function declarations in the .cpp
157 // file have comments describing the grammar rules.
158
159 ASTNode::ID precision();
160
161 ASTNode::ID directive();
162
163 ASTNode::ID section();
164
165 ASTNode::ID enumDeclaration();
166
167 ASTNode::ID declaration();
168
169 ASTNode::ID varDeclarations();
170
171 ASTNode::ID structDeclaration();
172
173 ASTNode::ID structVarDeclaration(Modifiers modifiers);
174
175 ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name);
176
177 ASTNode::ID parameter();
178
179 int layoutInt();
180
181 StringFragment layoutIdentifier();
182
183 StringFragment layoutCode();
184
185 Layout::Key layoutKey();
186
187 Layout::CType layoutCType();
188
189 Layout layout();
190
191 Modifiers modifiers();
192
193 Modifiers modifiersWithDefaults(int defaultFlags);
194
195 ASTNode::ID statement();
196
197 ASTNode::ID type();
198
199 ASTNode::ID interfaceBlock(Modifiers mods);
200
201 ASTNode::ID ifStatement();
202
203 ASTNode::ID doStatement();
204
205 ASTNode::ID whileStatement();
206
207 ASTNode::ID forStatement();
208
209 ASTNode::ID switchCase();
210
211 ASTNode::ID switchStatement();
212
213 ASTNode::ID returnStatement();
214
215 ASTNode::ID breakStatement();
216
217 ASTNode::ID continueStatement();
218
219 ASTNode::ID discardStatement();
220
221 ASTNode::ID block();
222
223 ASTNode::ID expressionStatement();
224
225 ASTNode::ID expression();
226
227 ASTNode::ID assignmentExpression();
228
229 ASTNode::ID ternaryExpression();
230
231 ASTNode::ID logicalOrExpression();
232
233 ASTNode::ID logicalXorExpression();
234
235 ASTNode::ID logicalAndExpression();
236
237 ASTNode::ID bitwiseOrExpression();
238
239 ASTNode::ID bitwiseXorExpression();
240
241 ASTNode::ID bitwiseAndExpression();
242
243 ASTNode::ID equalityExpression();
244
245 ASTNode::ID relationalExpression();
246
247 ASTNode::ID shiftExpression();
248
249 ASTNode::ID additiveExpression();
250
251 ASTNode::ID multiplicativeExpression();
252
253 ASTNode::ID unaryExpression();
254
255 ASTNode::ID postfixExpression();
256
257 ASTNode::ID suffix(ASTNode::ID base);
258
259 ASTNode::ID term();
260
261 bool intLiteral(SKSL_INT* dest);
262
263 bool floatLiteral(SKSL_FLOAT* dest);
264
265 bool boolLiteral(bool* dest);
266
267 bool identifier(StringFragment* dest);
268
269 static std::unordered_map<String, LayoutToken>* layoutTokens;
270
271 const char* fText;
272 Lexer fLexer;
273 YY_BUFFER_STATE fBuffer;
274 // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
275 // stack on pathological inputs
276 int fDepth = 0;
277 Token fPushback;
278 SymbolTable& fTypes;
279 ErrorReporter& fErrors;
280
281 std::unique_ptr<ASTFile> fFile;
282
283 friend class AutoDepth;
284 friend class HCodeGenerator;
285};
286
287} // namespace
288
289#endif
290