working on adding enum parameters to generate_spirv_parser
[kazan.git] / src / generate_spirv_parser / ast.h
1 /*
2 * Copyright 2017 Jacob Lifshay
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 */
23
24 #ifndef GENERATE_SPIRV_PARSER_AST_H_
25 #define GENERATE_SPIRV_PARSER_AST_H_
26
27 #include "json/json.h"
28 #include <cstdint>
29 #include <vector>
30 #include <string>
31
32 namespace vulkan_cpu
33 {
34 namespace generate_spirv_parser
35 {
36 namespace ast
37 {
38 struct Copyright
39 {
40 std::vector<std::string> lines;
41 Copyright() : lines()
42 {
43 }
44 explicit Copyright(std::vector<std::string> lines) noexcept : lines(std::move(lines))
45 {
46 }
47 json::ast::Value to_json() const;
48 template <typename Fn>
49 void visit(Fn fn) const
50 {
51 fn(*this);
52 }
53 };
54
55 struct Capabilities
56 {
57 std::vector<std::string> capabilities;
58 Capabilities() : capabilities()
59 {
60 }
61 explicit Capabilities(std::vector<std::string> capabilities) noexcept
62 : capabilities(std::move(capabilities))
63 {
64 }
65 bool empty() const noexcept
66 {
67 return capabilities.empty();
68 }
69 json::ast::Value to_json() const;
70 template <typename Fn>
71 void visit(Fn fn) const
72 {
73 fn(*this);
74 }
75 };
76
77 struct Extensions
78 {
79 std::vector<std::string> extensions;
80 Extensions() : extensions()
81 {
82 }
83 explicit Extensions(std::vector<std::string> extensions) noexcept
84 : extensions(std::move(extensions))
85 {
86 }
87 bool empty() const noexcept
88 {
89 return extensions.empty();
90 }
91 json::ast::Value to_json() const;
92 template <typename Fn>
93 void visit(Fn fn) const
94 {
95 fn(*this);
96 }
97 };
98
99 struct Instructions
100 {
101 struct Instruction
102 {
103 struct Operands
104 {
105 struct Operand
106 {
107 enum class Quantifier
108 {
109 none,
110 optional,
111 variable,
112 };
113 static constexpr const char *get_quantifier_string(Quantifier quantifier) noexcept
114 {
115 switch(quantifier)
116 {
117 case Quantifier::none:
118 return "";
119 case Quantifier::optional:
120 return "?";
121 case Quantifier::variable:
122 return "*";
123 }
124 return "";
125 }
126 std::string kind;
127 std::string name;
128 Quantifier quantifier;
129 Operand(std::string kind, std::string name, Quantifier quantifier) noexcept
130 : kind(std::move(kind)),
131 name(std::move(name)),
132 quantifier(quantifier)
133 {
134 }
135 json::ast::Value to_json() const;
136 template <typename Fn>
137 void visit(Fn fn) const
138 {
139 fn(*this);
140 }
141 };
142 std::vector<Operand> operands;
143 Operands() : operands()
144 {
145 }
146 explicit Operands(std::vector<Operand> operands) noexcept
147 : operands(std::move(operands))
148 {
149 }
150 bool empty() const noexcept
151 {
152 return operands.empty();
153 }
154 json::ast::Value to_json() const;
155 template <typename Fn>
156 void visit(Fn fn) const
157 {
158 fn(*this);
159 for(auto &operand : operands)
160 operand.visit(fn);
161 }
162 };
163 std::string opname;
164 std::uint32_t opcode;
165 Operands operands;
166 Capabilities capabilities;
167 Extensions extensions;
168 Instruction(std::string opname,
169 std::uint32_t opcode,
170 Operands operands,
171 Capabilities capabilities,
172 Extensions extensions) noexcept : opname(std::move(opname)),
173 opcode(opcode),
174 operands(std::move(operands)),
175 capabilities(std::move(capabilities)),
176 extensions(std::move(extensions))
177 {
178 }
179 json::ast::Value to_json() const;
180 template <typename Fn>
181 void visit(Fn fn) const
182 {
183 fn(*this);
184 operands.visit(fn);
185 capabilities.visit(fn);
186 extensions.visit(fn);
187 }
188 };
189 std::vector<Instruction> instructions;
190 explicit Instructions(std::vector<Instruction> instructions) noexcept
191 : instructions(std::move(instructions))
192 {
193 }
194 json::ast::Value to_json() const;
195 template <typename Fn>
196 void visit(Fn fn) const
197 {
198 fn(*this);
199 for(auto &instruction : instructions)
200 instruction.visit(fn);
201 }
202 };
203
204 struct Operand_kinds
205 {
206 struct Operand_kind
207 {
208 enum class Category
209 {
210 bit_enum,
211 value_enum,
212 id,
213 literal,
214 composite,
215 };
216 Category category;
217 static constexpr const char *get_json_name_from_category(Category category) noexcept
218 {
219 switch(category)
220 {
221 case Category::bit_enum:
222 return "BitEnum";
223 case Category::value_enum:
224 return "ValueEnum";
225 case Category::id:
226 return "Id";
227 case Category::literal:
228 return "Literal";
229 case Category::composite:
230 return "Composite";
231 }
232 return "";
233 }
234 std::string kind;
235 struct Enumerants
236 {
237 static constexpr const char *get_json_key_name() noexcept
238 {
239 return "enumerants";
240 }
241 struct Enumerant
242 {
243 std::string enumerant;
244 std::uint32_t value;
245 Capabilities capabilities;
246 struct Parameters
247 {
248 struct Parameter
249 {
250 std::string kind;
251 std::string name;
252 explicit Parameter(std::string kind, std::string name) noexcept
253 : kind(std::move(kind)),
254 name(std::move(name))
255 {
256 }
257 json::ast::Value to_json() const;
258 template <typename Fn>
259 void visit(Fn fn) const
260 {
261 fn(*this);
262 }
263 };
264 std::vector<Parameter> parameters;
265 Parameters() : parameters()
266 {
267 }
268 explicit Parameters(std::vector<Parameter> parameters) noexcept
269 : parameters(std::move(parameters))
270 {
271 }
272 json::ast::Value to_json() const;
273 bool empty() const noexcept
274 {
275 return parameters.empty();
276 }
277 template <typename Fn>
278 void visit(Fn fn) const
279 {
280 fn(*this);
281 for(auto &parameter : parameters)
282 parameter.visit(fn);
283 }
284 };
285 Parameters parameters;
286 Extensions extensions;
287 Enumerant(std::string enumerant,
288 std::uint32_t value,
289 Capabilities capabilities,
290 Parameters parameters,
291 Extensions extensions) noexcept : enumerant(std::move(enumerant)),
292 value(value),
293 capabilities(std::move(capabilities)),
294 parameters(std::move(parameters)),
295 extensions(std::move(extensions))
296 {
297 }
298 json::ast::Value to_json(bool is_bit_enumerant) const;
299 template <typename Fn>
300 void visit(Fn fn) const
301 {
302 fn(*this);
303 capabilities.visit(fn);
304 parameters.visit(fn);
305 extensions.visit(fn);
306 }
307 };
308 std::vector<Enumerant> enumerants;
309 explicit Enumerants(std::vector<Enumerant> enumerants) noexcept : enumerants(enumerants)
310 {
311 }
312 json::ast::Value to_json(bool is_bit_enumerant) const;
313 json::ast::Value to_json(Category category) const
314 {
315 return to_json(category == Category::bit_enum);
316 }
317 template <typename Fn>
318 void visit(Fn fn) const
319 {
320 fn(*this);
321 for(auto &enumerant : enumerants)
322 enumerant.visit(fn);
323 }
324 };
325 struct Doc
326 {
327 static constexpr const char *get_json_key_name() noexcept
328 {
329 return "doc";
330 }
331 std::string value;
332 Doc() = default;
333 explicit Doc(std::string value) noexcept : value(std::move(value))
334 {
335 }
336 json::ast::Value to_json() const;
337 json::ast::Value to_json(Category category) const
338 {
339 return to_json();
340 }
341 template <typename Fn>
342 void visit(Fn fn) const
343 {
344 fn(*this);
345 }
346 };
347 struct Bases
348 {
349 static constexpr const char *get_json_key_name() noexcept
350 {
351 return "bases";
352 }
353 std::vector<std::string> values;
354 Bases() = default;
355 explicit Bases(std::vector<std::string> values) noexcept : values(std::move(values))
356 {
357 }
358 json::ast::Value to_json() const;
359 json::ast::Value to_json(Category category) const
360 {
361 return to_json();
362 }
363 template <typename Fn>
364 void visit(Fn fn) const
365 {
366 fn(*this);
367 }
368 };
369 typedef util::variant<Enumerants, Doc, Bases> Value;
370 Value value;
371 static bool does_category_match_value(Category category, const Value &value) noexcept
372 {
373 switch(category)
374 {
375 case Category::bit_enum:
376 case Category::value_enum:
377 return util::holds_alternative<Enumerants>(value);
378 case Category::id:
379 case Category::literal:
380 return util::holds_alternative<Doc>(value);
381 case Category::composite:
382 return util::holds_alternative<Bases>(value);
383 }
384 return false;
385 }
386 static constexpr const char *get_value_json_key_name_from_category(
387 Category category) noexcept
388 {
389 switch(category)
390 {
391 case Category::bit_enum:
392 case Category::value_enum:
393 return Enumerants::get_json_key_name();
394 case Category::id:
395 case Category::literal:
396 return Doc::get_json_key_name();
397 case Category::composite:
398 return Bases::get_json_key_name();
399 }
400 return "";
401 }
402 Operand_kind(Category category, std::string kind, Value value) noexcept
403 : category(category),
404 kind(kind),
405 value(std::move(value))
406 {
407 }
408 json::ast::Value to_json() const;
409 template <typename Fn>
410 void visit(Fn fn) const
411 {
412 fn(*this);
413 util::visit(
414 [&](auto &&value)
415 {
416 value.visit(fn);
417 },
418 value);
419 }
420 };
421 std::vector<Operand_kind> operand_kinds;
422 explicit Operand_kinds(std::vector<Operand_kind> operand_kinds) noexcept
423 : operand_kinds(std::move(operand_kinds))
424 {
425 }
426 json::ast::Value to_json() const;
427 template <typename Fn>
428 void visit(Fn fn) const
429 {
430 fn(*this);
431 for(auto &operand_kind : operand_kinds)
432 operand_kind.visit(fn);
433 }
434 };
435
436 struct Top_level
437 {
438 Copyright copyright;
439 std::uint32_t magic_number;
440 std::size_t major_version;
441 std::size_t minor_version;
442 std::size_t revision;
443 Instructions instructions;
444 Operand_kinds operand_kinds;
445 Top_level(Copyright copyright,
446 std::uint32_t magic_number,
447 std::size_t major_version,
448 std::size_t minor_version,
449 std::size_t revision,
450 Instructions instructions,
451 Operand_kinds operand_kinds)
452 : copyright(std::move(copyright)),
453 magic_number(magic_number),
454 major_version(major_version),
455 minor_version(minor_version),
456 revision(revision),
457 instructions(std::move(instructions)),
458 operand_kinds(std::move(operand_kinds))
459 {
460 }
461 json::ast::Value to_json() const;
462 template <typename Fn>
463 void visit(Fn fn) const
464 {
465 fn(*this);
466 copyright.visit(fn);
467 instructions.visit(fn);
468 operand_kinds.visit(fn);
469 }
470 };
471 }
472 }
473 }
474
475 #endif /* GENERATE_SPIRV_PARSER_AST_H_ */