• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SRC_READER_WGSL_PARSER_IMPL_H_
16 #define SRC_READER_WGSL_PARSER_IMPL_H_
17 
18 #include <deque>
19 #include <memory>
20 #include <string>
21 #include <unordered_map>
22 #include <utility>
23 #include <vector>
24 
25 #include "src/ast/access.h"
26 #include "src/program_builder.h"
27 #include "src/reader/wgsl/parser_impl_detail.h"
28 #include "src/reader/wgsl/token.h"
29 #include "src/sem/storage_texture_type.h"
30 
31 namespace tint {
32 namespace ast {
33 class AssignmentStatement;
34 class BreakStatement;
35 class CallStatement;
36 class ContinueStatement;
37 class IfStatement;
38 class LoopStatement;
39 class ReturnStatement;
40 class SwitchStatement;
41 class VariableDeclStatement;
42 }  // namespace ast
43 
44 namespace reader {
45 namespace wgsl {
46 
47 class Lexer;
48 
49 /// Struct holding information for a for loop
50 struct ForHeader {
51   /// Constructor
52   /// @param init the initializer statement
53   /// @param cond the condition statement
54   /// @param cont the continuing statement
55   ForHeader(const ast::Statement* init,
56             const ast::Expression* cond,
57             const ast::Statement* cont);
58 
59   ~ForHeader();
60 
61   /// The for loop initializer
62   const ast::Statement* initializer = nullptr;
63   /// The for loop condition
64   const ast::Expression* condition = nullptr;
65   /// The for loop continuing statement
66   const ast::Statement* continuing = nullptr;
67 };
68 
69 /// ParserImpl for WGSL source data
70 class ParserImpl {
71   /// Failure holds enumerator values used for the constructing an Expect and
72   /// Match in an errored state.
73   struct Failure {
74     enum Errored { kErrored };
75     enum NoMatch { kNoMatch };
76   };
77 
78  public:
79   /// Expect is the return type of the parser methods that are expected to
80   /// return a parsed value of type T, unless there was an parse error.
81   /// In the case of a parse error the called method will have called
82   /// add_error() and #errored will be set to true.
83   template <typename T>
84   struct Expect {
85     /// An alias to the templated type T.
86     using type = T;
87 
88     /// Don't allow an Expect to take a nullptr.
89     inline Expect(std::nullptr_t) = delete;  // NOLINT
90 
91     /// Constructor for a successful parse.
92     /// @param val the result value of the parse
93     /// @param s the optional source of the value
94     template <typename U>
95     inline Expect(U&& val, const Source& s = {})  // NOLINT
valueExpect96         : value(std::forward<U>(val)), source(s) {}
97 
98     /// Constructor for parse error.
ExpectExpect99     inline Expect(Failure::Errored) : errored(true) {}  // NOLINT
100 
101     /// Copy constructor
102     inline Expect(const Expect&) = default;
103     /// Move constructor
104     inline Expect(Expect&&) = default;
105     /// Assignment operator
106     /// @return this Expect
107     inline Expect& operator=(const Expect&) = default;
108     /// Assignment move operator
109     /// @return this Expect
110     inline Expect& operator=(Expect&&) = default;
111 
112     /// @return a pointer to the returned value. If T is a pointer or
113     /// std::unique_ptr, operator->() automatically dereferences so that the
114     /// return type will always be a pointer to a non-pointer type. #errored
115     /// must be false to call.
116     inline typename detail::OperatorArrow<T>::type operator->() {
117       TINT_ASSERT(Reader, !errored);
118       return detail::OperatorArrow<T>::ptr(value);
119     }
120 
121     /// The expected value of a successful parse.
122     /// Zero-initialized when there was a parse error.
123     T value{};
124     /// Optional source of the value.
125     Source source;
126     /// True if there was a error parsing.
127     bool errored = false;
128   };
129 
130   /// Maybe is the return type of the parser methods that attempts to match a
131   /// grammar and return a parsed value of type T, or may parse part of the
132   /// grammar and then hit a parse error.
133   /// In the case of a successful grammar match, the Maybe will have #matched
134   /// set to true.
135   /// In the case of a parse error the called method will have called
136   /// add_error() and the Maybe will have #errored set to true.
137   template <typename T>
138   struct Maybe {
139     inline Maybe(std::nullptr_t) = delete;  // NOLINT
140 
141     /// Constructor for a successful parse.
142     /// @param val the result value of the parse
143     /// @param s the optional source of the value
144     template <typename U>
145     inline Maybe(U&& val, const Source& s = {})  // NOLINT
valueMaybe146         : value(std::forward<U>(val)), source(s), matched(true) {}
147 
148     /// Constructor for parse error state.
MaybeMaybe149     inline Maybe(Failure::Errored) : errored(true) {}  // NOLINT
150 
151     /// Constructor for the no-match state.
MaybeMaybe152     inline Maybe(Failure::NoMatch) {}  // NOLINT
153 
154     /// Constructor from an Expect.
155     /// @param e the Expect to copy this Maybe from
156     template <typename U>
MaybeMaybe157     inline Maybe(const Expect<U>& e)  // NOLINT
158         : value(e.value),
159           source(e.value),
160           errored(e.errored),
161           matched(!e.errored) {}
162 
163     /// Move from an Expect.
164     /// @param e the Expect to move this Maybe from
165     template <typename U>
MaybeMaybe166     inline Maybe(Expect<U>&& e)  // NOLINT
167         : value(std::move(e.value)),
168           source(std::move(e.source)),
169           errored(e.errored),
170           matched(!e.errored) {}
171 
172     /// Copy constructor
173     inline Maybe(const Maybe&) = default;
174     /// Move constructor
175     inline Maybe(Maybe&&) = default;
176     /// Assignment operator
177     /// @return this Maybe
178     inline Maybe& operator=(const Maybe&) = default;
179     /// Assignment move operator
180     /// @return this Maybe
181     inline Maybe& operator=(Maybe&&) = default;
182 
183     /// @return a pointer to the returned value. If T is a pointer or
184     /// std::unique_ptr, operator->() automatically dereferences so that the
185     /// return type will always be a pointer to a non-pointer type. #errored
186     /// must be false to call.
187     inline typename detail::OperatorArrow<T>::type operator->() {
188       TINT_ASSERT(Reader, !errored);
189       return detail::OperatorArrow<T>::ptr(value);
190     }
191 
192     /// The value of a successful parse.
193     /// Zero-initialized when there was a parse error.
194     T value{};
195     /// Optional source of the value.
196     Source source;
197     /// True if there was a error parsing.
198     bool errored = false;
199     /// True if there was a error parsing.
200     bool matched = false;
201   };
202 
203   /// TypedIdentifier holds a parsed identifier and type. Returned by
204   /// variable_ident_decl().
205   struct TypedIdentifier {
206     /// Constructor
207     TypedIdentifier();
208     /// Copy constructor
209     /// @param other the FunctionHeader to copy
210     TypedIdentifier(const TypedIdentifier& other);
211     /// Constructor
212     /// @param type_in parsed type
213     /// @param name_in parsed identifier
214     /// @param source_in source to the identifier
215     TypedIdentifier(const ast::Type* type_in,
216                     std::string name_in,
217                     Source source_in);
218     /// Destructor
219     ~TypedIdentifier();
220 
221     /// Parsed type. May be nullptr for inferred types.
222     const ast::Type* type = nullptr;
223     /// Parsed identifier.
224     std::string name;
225     /// Source to the identifier.
226     Source source;
227   };
228 
229   /// FunctionHeader contains the parsed information for a function header.
230   struct FunctionHeader {
231     /// Constructor
232     FunctionHeader();
233     /// Copy constructor
234     /// @param other the FunctionHeader to copy
235     FunctionHeader(const FunctionHeader& other);
236     /// Constructor
237     /// @param src parsed header source
238     /// @param n function name
239     /// @param p function parameters
240     /// @param ret_ty function return type
241     /// @param ret_decos return type decorations
242     FunctionHeader(Source src,
243                    std::string n,
244                    ast::VariableList p,
245                    const ast::Type* ret_ty,
246                    ast::DecorationList ret_decos);
247     /// Destructor
248     ~FunctionHeader();
249     /// Assignment operator
250     /// @param other the FunctionHeader to copy
251     /// @returns this FunctionHeader
252     FunctionHeader& operator=(const FunctionHeader& other);
253 
254     /// Parsed header source
255     Source source;
256     /// Function name
257     std::string name;
258     /// Function parameters
259     ast::VariableList params;
260     /// Function return type
261     const ast::Type* return_type = nullptr;
262     /// Function return type decorations
263     ast::DecorationList return_type_decorations;
264   };
265 
266   /// VarDeclInfo contains the parsed information for variable declaration.
267   struct VarDeclInfo {
268     /// Constructor
269     VarDeclInfo();
270     /// Copy constructor
271     /// @param other the VarDeclInfo to copy
272     VarDeclInfo(const VarDeclInfo& other);
273     /// Constructor
274     /// @param source_in variable declaration source
275     /// @param name_in variable name
276     /// @param storage_class_in variable storage class
277     /// @param access_in variable access control
278     /// @param type_in variable type
279     VarDeclInfo(Source source_in,
280                 std::string name_in,
281                 ast::StorageClass storage_class_in,
282                 ast::Access access_in,
283                 const ast::Type* type_in);
284     /// Destructor
285     ~VarDeclInfo();
286 
287     /// Variable declaration source
288     Source source;
289     /// Variable name
290     std::string name;
291     /// Variable storage class
292     ast::StorageClass storage_class = ast::StorageClass::kNone;
293     /// Variable access control
294     ast::Access access = ast::Access::kUndefined;
295     /// Variable type
296     const ast::Type* type = nullptr;
297   };
298 
299   /// VariableQualifier contains the parsed information for a variable qualifier
300   struct VariableQualifier {
301     /// The variable's storage class
302     ast::StorageClass storage_class = ast::StorageClass::kNone;
303     /// The variable's access control
304     ast::Access access = ast::Access::kUndefined;
305   };
306 
307   /// Creates a new parser using the given file
308   /// @param file the input source file to parse
309   explicit ParserImpl(Source::File const* file);
310   ~ParserImpl();
311 
312   /// Run the parser
313   /// @returns true if the parse was successful, false otherwise.
314   bool Parse();
315 
316   /// set_max_diagnostics sets the maximum number of reported errors before
317   /// aborting parsing.
318   /// @param limit the new maximum number of errors
set_max_errors(size_t limit)319   void set_max_errors(size_t limit) { max_errors_ = limit; }
320 
321   /// @return the number of maximum number of reported errors before aborting
322   /// parsing.
get_max_errors()323   size_t get_max_errors() const { return max_errors_; }
324 
325   /// @returns true if an error was encountered.
has_error()326   bool has_error() const { return builder_.Diagnostics().contains_errors(); }
327 
328   /// @returns the parser error string
error()329   std::string error() const {
330     diag::Formatter formatter{{false, false, false, false}};
331     return formatter.format(builder_.Diagnostics());
332   }
333 
334   /// @returns the Program. The program builder in the parser will be reset
335   /// after this.
program()336   Program program() { return Program(std::move(builder_)); }
337 
338   /// @returns the program builder.
builder()339   ProgramBuilder& builder() { return builder_; }
340 
341   /// @returns the next token
342   Token next();
343   /// Peeks ahead and returns the token at `idx` ahead of the current position
344   /// @param idx the index of the token to return
345   /// @returns the token `idx` positions ahead without advancing
346   Token peek(size_t idx = 0);
347   /// Peeks ahead and returns true if the token at `idx` ahead of the current
348   /// position is |tok|
349   /// @param idx the index of the token to return
350   /// @param tok the token to look for
351   /// @returns true if the token `idx` positions ahead is |tok|
352   bool peek_is(Token::Type tok, size_t idx = 0);
353   /// @returns the last token that was returned by `next()`
354   Token last_token() const;
355   /// Appends an error at `t` with the message `msg`
356   /// @param t the token to associate the error with
357   /// @param msg the error message
358   /// @return `Failure::Errored::kError` so that you can combine an add_error()
359   /// call and return on the same line.
360   Failure::Errored add_error(const Token& t, const std::string& msg);
361   /// Appends an error raised when parsing `use` at `t` with the message
362   /// `msg`
363   /// @param source the source to associate the error with
364   /// @param msg the error message
365   /// @param use a description of what was being parsed when the error was
366   /// raised.
367   /// @return `Failure::Errored::kError` so that you can combine an add_error()
368   /// call and return on the same line.
369   Failure::Errored add_error(const Source& source,
370                              const std::string& msg,
371                              const std::string& use);
372   /// Appends an error at `source` with the message `msg`
373   /// @param source the source to associate the error with
374   /// @param msg the error message
375   /// @return `Failure::Errored::kError` so that you can combine an add_error()
376   /// call and return on the same line.
377   Failure::Errored add_error(const Source& source, const std::string& msg);
378   /// Appends a deprecated-language-feature warning at `source` with the message
379   /// `msg`
380   /// @param source the source to associate the error with
381   /// @param msg the warning message
382   void deprecated(const Source& source, const std::string& msg);
383   /// Parses the `translation_unit` grammar element
384   void translation_unit();
385   /// Parses the `global_decl` grammar element, erroring on parse failure.
386   /// @return true on parse success, otherwise an error.
387   Expect<bool> expect_global_decl();
388   /// Parses a `global_variable_decl` grammar element with the initial
389   /// `variable_decoration_list*` provided as `decos`
390   /// @returns the variable parsed or nullptr
391   /// @param decos the list of decorations for the variable declaration.
392   Maybe<const ast::Variable*> global_variable_decl(ast::DecorationList& decos);
393   /// Parses a `global_constant_decl` grammar element with the initial
394   /// `variable_decoration_list*` provided as `decos`
395   /// @returns the const object or nullptr
396   /// @param decos the list of decorations for the constant declaration.
397   Maybe<const ast::Variable*> global_constant_decl(ast::DecorationList& decos);
398   /// Parses a `variable_decl` grammar element
399   /// @param allow_inferred if true, do not fail if variable decl does not
400   /// specify type
401   /// @returns the parsed variable declaration info
402   Maybe<VarDeclInfo> variable_decl(bool allow_inferred = false);
403   /// Parses a `variable_ident_decl` grammar element, erroring on parse
404   /// failure.
405   /// @param use a description of what was being parsed if an error was raised.
406   /// @param allow_inferred if true, do not fail if variable decl does not
407   /// specify type
408   /// @returns the identifier and type parsed or empty otherwise
409   Expect<TypedIdentifier> expect_variable_ident_decl(
410       const std::string& use,
411       bool allow_inferred = false);
412   /// Parses a `variable_qualifier` grammar element
413   /// @returns the variable qualifier information
414   Maybe<VariableQualifier> variable_qualifier();
415   /// Parses a `type_alias` grammar element
416   /// @returns the type alias or nullptr on error
417   Maybe<const ast::Alias*> type_alias();
418   /// Parses a `type_decl` grammar element
419   /// @returns the parsed Type or nullptr if none matched.
420   Maybe<const ast::Type*> type_decl();
421   /// Parses a `type_decl` grammar element with the given pre-parsed
422   /// decorations.
423   /// @param decos the list of decorations for the type.
424   /// @returns the parsed Type or nullptr if none matched.
425   Maybe<const ast::Type*> type_decl(ast::DecorationList& decos);
426   /// Parses a `storage_class` grammar element, erroring on parse failure.
427   /// @param use a description of what was being parsed if an error was raised.
428   /// @returns the storage class or StorageClass::kNone if none matched
429   Expect<ast::StorageClass> expect_storage_class(const std::string& use);
430   /// Parses a `struct_decl` grammar element with the initial
431   /// `struct_decoration_decl*` provided as `decos`.
432   /// @returns the struct type or nullptr on error
433   /// @param decos the list of decorations for the struct declaration.
434   Maybe<const ast::Struct*> struct_decl(ast::DecorationList& decos);
435   /// Parses a `struct_body_decl` grammar element, erroring on parse failure.
436   /// @returns the struct members
437   Expect<ast::StructMemberList> expect_struct_body_decl();
438   /// Parses a `struct_member` grammar element with the initial
439   /// `struct_member_decoration_decl+` provided as `decos`, erroring on parse
440   /// failure.
441   /// @param decos the list of decorations for the struct member.
442   /// @returns the struct member or nullptr
443   Expect<ast::StructMember*> expect_struct_member(ast::DecorationList& decos);
444   /// Parses a `function_decl` grammar element with the initial
445   /// `function_decoration_decl*` provided as `decos`.
446   /// @param decos the list of decorations for the function declaration.
447   /// @returns the parsed function, nullptr otherwise
448   Maybe<const ast::Function*> function_decl(ast::DecorationList& decos);
449   /// Parses a `texture_sampler_types` grammar element
450   /// @returns the parsed Type or nullptr if none matched.
451   Maybe<const ast::Type*> texture_sampler_types();
452   /// Parses a `sampler_type` grammar element
453   /// @returns the parsed Type or nullptr if none matched.
454   Maybe<const ast::Type*> sampler_type();
455   /// Parses a `multisampled_texture_type` grammar element
456   /// @returns returns the multisample texture dimension or kNone if none
457   /// matched.
458   Maybe<const ast::TextureDimension> multisampled_texture_type();
459   /// Parses a `sampled_texture_type` grammar element
460   /// @returns returns the sample texture dimension or kNone if none matched.
461   Maybe<const ast::TextureDimension> sampled_texture_type();
462   /// Parses a `storage_texture_type` grammar element
463   /// @returns returns the storage texture dimension.
464   /// Returns kNone if none matched.
465   Maybe<const ast::TextureDimension> storage_texture_type();
466   /// Parses a `depth_texture_type` grammar element
467   /// @returns the parsed Type or nullptr if none matched.
468   Maybe<const ast::Type*> depth_texture_type();
469   /// Parses a 'texture_external_type' grammar element
470   /// @returns the parsed Type or nullptr if none matched
471   Maybe<const ast::Type*> external_texture_type();
472   /// Parses a `image_storage_type` grammar element
473   /// @param use a description of what was being parsed if an error was raised
474   /// @returns returns the image format or kNone if none matched.
475   Expect<ast::ImageFormat> expect_image_storage_type(const std::string& use);
476   /// Parses a `function_header` grammar element
477   /// @returns the parsed function header
478   Maybe<FunctionHeader> function_header();
479   /// Parses a `param_list` grammar element, erroring on parse failure.
480   /// @returns the parsed variables
481   Expect<ast::VariableList> expect_param_list();
482   /// Parses a `param` grammar element, erroring on parse failure.
483   /// @returns the parsed variable
484   Expect<ast::Variable*> expect_param();
485   /// Parses a `pipeline_stage` grammar element, erroring if the next token does
486   /// not match a stage name.
487   /// @returns the pipeline stage.
488   Expect<ast::PipelineStage> expect_pipeline_stage();
489   /// Parses an access control identifier, erroring if the next token does not
490   /// match a valid access control.
491   /// @param use a description of what was being parsed if an error was raised
492   /// @returns the parsed access control.
493   Expect<ast::Access> expect_access(const std::string& use);
494   /// Parses a builtin identifier, erroring if the next token does not match a
495   /// valid builtin name.
496   /// @returns the parsed builtin.
497   Expect<ast::Builtin> expect_builtin();
498   /// Parses a `body_stmt` grammar element, erroring on parse failure.
499   /// @returns the parsed statements
500   Expect<ast::BlockStatement*> expect_body_stmt();
501   /// Parses a `paren_rhs_stmt` grammar element, erroring on parse failure.
502   /// @returns the parsed element or nullptr
503   Expect<const ast::Expression*> expect_paren_rhs_stmt();
504   /// Parses a `statements` grammar element
505   /// @returns the statements parsed
506   Expect<ast::StatementList> expect_statements();
507   /// Parses a `statement` grammar element
508   /// @returns the parsed statement or nullptr
509   Maybe<const ast::Statement*> statement();
510   /// Parses a `break_stmt` grammar element
511   /// @returns the parsed statement or nullptr
512   Maybe<const ast::BreakStatement*> break_stmt();
513   /// Parses a `return_stmt` grammar element
514   /// @returns the parsed statement or nullptr
515   Maybe<const ast::ReturnStatement*> return_stmt();
516   /// Parses a `continue_stmt` grammar element
517   /// @returns the parsed statement or nullptr
518   Maybe<const ast::ContinueStatement*> continue_stmt();
519   /// Parses a `variable_stmt` grammar element
520   /// @returns the parsed variable or nullptr
521   Maybe<const ast::VariableDeclStatement*> variable_stmt();
522   /// Parses a `if_stmt` grammar element
523   /// @returns the parsed statement or nullptr
524   Maybe<const ast::IfStatement*> if_stmt();
525   /// Parses a `elseif_stmt` grammar element
526   /// @returns the parsed elements
527   Maybe<ast::ElseStatementList> elseif_stmt();
528   /// Parses a `else_stmt` grammar element
529   /// @returns the parsed statement or nullptr
530   Maybe<const ast::ElseStatement*> else_stmt();
531   /// Parses a `switch_stmt` grammar element
532   /// @returns the parsed statement or nullptr
533   Maybe<const ast::SwitchStatement*> switch_stmt();
534   /// Parses a `switch_body` grammar element
535   /// @returns the parsed statement or nullptr
536   Maybe<const ast::CaseStatement*> switch_body();
537   /// Parses a `case_selectors` grammar element
538   /// @returns the list of literals
539   Expect<ast::CaseSelectorList> expect_case_selectors();
540   /// Parses a `case_body` grammar element
541   /// @returns the parsed statements
542   Maybe<const ast::BlockStatement*> case_body();
543   /// Parses a `func_call_stmt` grammar element
544   /// @returns the parsed function call or nullptr
545   Maybe<const ast::CallStatement*> func_call_stmt();
546   /// Parses a `loop_stmt` grammar element
547   /// @returns the parsed loop or nullptr
548   Maybe<const ast::LoopStatement*> loop_stmt();
549   /// Parses a `for_header` grammar element, erroring on parse failure.
550   /// @returns the parsed for header or nullptr
551   Expect<std::unique_ptr<ForHeader>> expect_for_header();
552   /// Parses a `for_stmt` grammar element
553   /// @returns the parsed for loop or nullptr
554   Maybe<const ast::ForLoopStatement*> for_stmt();
555   /// Parses a `continuing_stmt` grammar element
556   /// @returns the parsed statements
557   Maybe<const ast::BlockStatement*> continuing_stmt();
558   /// Parses a `const_literal` grammar element
559   /// @returns the const literal parsed or nullptr if none found
560   Maybe<const ast::LiteralExpression*> const_literal();
561   /// Parses a `const_expr` grammar element, erroring on parse failure.
562   /// @returns the parsed constructor expression or nullptr on error
563   Expect<const ast::Expression*> expect_const_expr();
564   /// Parses a `primary_expression` grammar element
565   /// @returns the parsed expression or nullptr
566   Maybe<const ast::Expression*> primary_expression();
567   /// Parses a `argument_expression_list` grammar element, erroring on parse
568   /// failure.
569   /// @param use a description of what was being parsed if an error was raised
570   /// @returns the list of arguments
571   Expect<ast::ExpressionList> expect_argument_expression_list(
572       const std::string& use);
573   /// Parses the recursive portion of the postfix_expression
574   /// @param prefix the left side of the expression
575   /// @returns the parsed expression or nullptr
576   Maybe<const ast::Expression*> postfix_expression(
577       const ast::Expression* prefix);
578   /// Parses a `singular_expression` grammar elment
579   /// @returns the parsed expression or nullptr
580   Maybe<const ast::Expression*> singular_expression();
581   /// Parses a `unary_expression` grammar element
582   /// @returns the parsed expression or nullptr
583   Maybe<const ast::Expression*> unary_expression();
584   /// Parses the recursive part of the `multiplicative_expression`, erroring on
585   /// parse failure.
586   /// @param lhs the left side of the expression
587   /// @returns the parsed expression or nullptr
588   Expect<const ast::Expression*> expect_multiplicative_expr(
589       const ast::Expression* lhs);
590   /// Parses the `multiplicative_expression` grammar element
591   /// @returns the parsed expression or nullptr
592   Maybe<const ast::Expression*> multiplicative_expression();
593   /// Parses the recursive part of the `additive_expression`, erroring on parse
594   /// failure.
595   /// @param lhs the left side of the expression
596   /// @returns the parsed expression or nullptr
597   Expect<const ast::Expression*> expect_additive_expr(
598       const ast::Expression* lhs);
599   /// Parses the `additive_expression` grammar element
600   /// @returns the parsed expression or nullptr
601   Maybe<const ast::Expression*> additive_expression();
602   /// Parses the recursive part of the `shift_expression`, erroring on parse
603   /// failure.
604   /// @param lhs the left side of the expression
605   /// @returns the parsed expression or nullptr
606   Expect<const ast::Expression*> expect_shift_expr(const ast::Expression* lhs);
607   /// Parses the `shift_expression` grammar element
608   /// @returns the parsed expression or nullptr
609   Maybe<const ast::Expression*> shift_expression();
610   /// Parses the recursive part of the `relational_expression`, erroring on
611   /// parse failure.
612   /// @param lhs the left side of the expression
613   /// @returns the parsed expression or nullptr
614   Expect<const ast::Expression*> expect_relational_expr(
615       const ast::Expression* lhs);
616   /// Parses the `relational_expression` grammar element
617   /// @returns the parsed expression or nullptr
618   Maybe<const ast::Expression*> relational_expression();
619   /// Parses the recursive part of the `equality_expression`, erroring on parse
620   /// failure.
621   /// @param lhs the left side of the expression
622   /// @returns the parsed expression or nullptr
623   Expect<const ast::Expression*> expect_equality_expr(
624       const ast::Expression* lhs);
625   /// Parses the `equality_expression` grammar element
626   /// @returns the parsed expression or nullptr
627   Maybe<const ast::Expression*> equality_expression();
628   /// Parses the recursive part of the `and_expression`, erroring on parse
629   /// failure.
630   /// @param lhs the left side of the expression
631   /// @returns the parsed expression or nullptr
632   Expect<const ast::Expression*> expect_and_expr(const ast::Expression* lhs);
633   /// Parses the `and_expression` grammar element
634   /// @returns the parsed expression or nullptr
635   Maybe<const ast::Expression*> and_expression();
636   /// Parses the recursive part of the `exclusive_or_expression`, erroring on
637   /// parse failure.
638   /// @param lhs the left side of the expression
639   /// @returns the parsed expression or nullptr
640   Expect<const ast::Expression*> expect_exclusive_or_expr(
641       const ast::Expression* lhs);
642   /// Parses the `exclusive_or_expression` grammar elememnt
643   /// @returns the parsed expression or nullptr
644   Maybe<const ast::Expression*> exclusive_or_expression();
645   /// Parses the recursive part of the `inclusive_or_expression`, erroring on
646   /// parse failure.
647   /// @param lhs the left side of the expression
648   /// @returns the parsed expression or nullptr
649   Expect<const ast::Expression*> expect_inclusive_or_expr(
650       const ast::Expression* lhs);
651   /// Parses the `inclusive_or_expression` grammar element
652   /// @returns the parsed expression or nullptr
653   Maybe<const ast::Expression*> inclusive_or_expression();
654   /// Parses the recursive part of the `logical_and_expression`, erroring on
655   /// parse failure.
656   /// @param lhs the left side of the expression
657   /// @returns the parsed expression or nullptr
658   Expect<const ast::Expression*> expect_logical_and_expr(
659       const ast::Expression* lhs);
660   /// Parses a `logical_and_expression` grammar element
661   /// @returns the parsed expression or nullptr
662   Maybe<const ast::Expression*> logical_and_expression();
663   /// Parses the recursive part of the `logical_or_expression`, erroring on
664   /// parse failure.
665   /// @param lhs the left side of the expression
666   /// @returns the parsed expression or nullptr
667   Expect<const ast::Expression*> expect_logical_or_expr(
668       const ast::Expression* lhs);
669   /// Parses a `logical_or_expression` grammar element
670   /// @returns the parsed expression or nullptr
671   Maybe<const ast::Expression*> logical_or_expression();
672   /// Parses a `assignment_stmt` grammar element
673   /// @returns the parsed assignment or nullptr
674   Maybe<const ast::AssignmentStatement*> assignment_stmt();
675   /// Parses one or more bracketed decoration lists.
676   /// @return the parsed decoration list, or an empty list on error.
677   Maybe<ast::DecorationList> decoration_list();
678   /// Parses a list of decorations between `ATTR_LEFT` and `ATTR_RIGHT`
679   /// brackets.
680   /// @param decos the list to append newly parsed decorations to.
681   /// @return true if any decorations were be parsed, otherwise false.
682   Maybe<bool> decoration_bracketed_list(ast::DecorationList& decos);
683   /// Parses a single decoration of the following types:
684   /// * `struct_decoration`
685   /// * `struct_member_decoration`
686   /// * `array_decoration`
687   /// * `variable_decoration`
688   /// * `global_const_decoration`
689   /// * `function_decoration`
690   /// @return the parsed decoration, or nullptr.
691   Maybe<const ast::Decoration*> decoration();
692   /// Parses a single decoration, reporting an error if the next token does not
693   /// represent a decoration.
694   /// @see #decoration for the full list of decorations this method parses.
695   /// @return the parsed decoration, or nullptr on error.
696   Expect<const ast::Decoration*> expect_decoration();
697 
698  private:
699   /// ReturnType resolves to the return type for the function or lambda F.
700   template <typename F>
701   using ReturnType = typename std::result_of<F()>::type;
702 
703   /// ResultType resolves to `T` for a `RESULT` of type Expect<T>.
704   template <typename RESULT>
705   using ResultType = typename RESULT::type;
706 
707   /// @returns true and consumes the next token if it equals `tok`
708   /// @param source if not nullptr, the next token's source is written to this
709   /// pointer, regardless of success or error
710   bool match(Token::Type tok, Source* source = nullptr);
711   /// Errors if the next token is not equal to `tok`
712   /// Consumes the next token on match.
713   /// expect() also updates #synchronized_, setting it to `true` if the next
714   /// token is equal to `tok`, otherwise `false`.
715   /// @param use a description of what was being parsed if an error was raised.
716   /// @param tok the token to test against
717   /// @returns true if the next token equals `tok`
718   bool expect(const std::string& use, Token::Type tok);
719   /// Parses a signed integer from the next token in the stream, erroring if the
720   /// next token is not a signed integer.
721   /// Consumes the next token on match.
722   /// @param use a description of what was being parsed if an error was raised
723   /// @returns the parsed integer.
724   Expect<int32_t> expect_sint(const std::string& use);
725   /// Parses a signed integer from the next token in the stream, erroring if
726   /// the next token is not a signed integer or is negative.
727   /// Consumes the next token if it is a signed integer (not necessarily
728   /// negative).
729   /// @param use a description of what was being parsed if an error was raised
730   /// @returns the parsed integer.
731   Expect<uint32_t> expect_positive_sint(const std::string& use);
732   /// Parses a non-zero signed integer from the next token in the stream,
733   /// erroring if the next token is not a signed integer or is less than 1.
734   /// Consumes the next token if it is a signed integer (not necessarily
735   /// >= 1).
736   /// @param use a description of what was being parsed if an error was raised
737   /// @returns the parsed integer.
738   Expect<uint32_t> expect_nonzero_positive_sint(const std::string& use);
739   /// Errors if the next token is not an identifier.
740   /// Consumes the next token on match.
741   /// @param use a description of what was being parsed if an error was raised
742   /// @returns the parsed identifier.
743   Expect<std::string> expect_ident(const std::string& use);
744   /// Parses a lexical block starting with the token `start` and ending with
745   /// the token `end`. `body` is called to parse the lexical block body
746   /// between the `start` and `end` tokens. If the `start` or `end` tokens
747   /// are not matched then an error is generated and a zero-initialized `T` is
748   /// returned. If `body` raises an error while parsing then a zero-initialized
749   /// `T` is returned.
750   /// @param start the token that begins the lexical block
751   /// @param end the token that ends the lexical block
752   /// @param use a description of what was being parsed if an error was raised
753   /// @param body a function or lambda that is called to parse the lexical block
754   /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
755   /// @return the value returned by `body` if no errors are raised, otherwise
756   /// an Expect with error state.
757   template <typename F, typename T = ReturnType<F>>
758   T expect_block(Token::Type start,
759                  Token::Type end,
760                  const std::string& use,
761                  F&& body);
762   /// A convenience function that calls expect_block() passing
763   /// `Token::Type::kParenLeft` and `Token::Type::kParenRight` for the `start`
764   /// and `end` arguments, respectively.
765   /// @param use a description of what was being parsed if an error was raised
766   /// @param body a function or lambda that is called to parse the lexical block
767   /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
768   /// @return the value returned by `body` if no errors are raised, otherwise
769   /// an Expect with error state.
770   template <typename F, typename T = ReturnType<F>>
771   T expect_paren_block(const std::string& use, F&& body);
772   /// A convenience function that calls `expect_block` passing
773   /// `Token::Type::kBraceLeft` and `Token::Type::kBraceRight` for the `start`
774   /// and `end` arguments, respectively.
775   /// @param use a description of what was being parsed if an error was raised
776   /// @param body a function or lambda that is called to parse the lexical block
777   /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
778   /// @return the value returned by `body` if no errors are raised, otherwise
779   /// an Expect with error state.
780   template <typename F, typename T = ReturnType<F>>
781   T expect_brace_block(const std::string& use, F&& body);
782   /// A convenience function that calls `expect_block` passing
783   /// `Token::Type::kLessThan` and `Token::Type::kGreaterThan` for the `start`
784   /// and `end` arguments, respectively.
785   /// @param use a description of what was being parsed if an error was raised
786   /// @param body a function or lambda that is called to parse the lexical block
787   /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
788   /// @return the value returned by `body` if no errors are raised, otherwise
789   /// an Expect with error state.
790   template <typename F, typename T = ReturnType<F>>
791   T expect_lt_gt_block(const std::string& use, F&& body);
792 
793   /// sync() calls the function `func`, and attempts to resynchronize the
794   /// parser to the next found resynchronization token if `func` fails. If the
795   /// next found resynchronization token is `tok`, then sync will also consume
796   /// `tok`.
797   ///
798   /// sync() will transiently add `tok` to the parser's stack of
799   /// synchronization tokens for the duration of the call to `func`. Once @p
800   /// func returns,
801   /// `tok` is removed from the stack of resynchronization tokens. sync calls
802   /// may be nested, and so the number of resynchronization tokens is equal to
803   /// the number of sync() calls in the current stack frame.
804   ///
805   /// sync() updates #synchronized_, setting it to `true` if the next
806   /// resynchronization token found was `tok`, otherwise `false`.
807   ///
808   /// @param tok the token to attempt to synchronize the parser to if `func`
809   /// fails.
810   /// @param func a function or lambda with the signature: `Expect<Result>()` or
811   /// `Maybe<Result>()`.
812   /// @return the value returned by `func`
813   template <typename F, typename T = ReturnType<F>>
814   T sync(Token::Type tok, F&& func);
815   /// sync_to() attempts to resynchronize the parser to the next found
816   /// resynchronization token or `tok` (whichever comes first).
817   ///
818   /// Synchronization tokens are transiently defined by calls to sync().
819   ///
820   /// sync_to() updates #synchronized_, setting it to `true` if a
821   /// resynchronization token was found and it was `tok`, otherwise `false`.
822   ///
823   /// @param tok the token to attempt to synchronize the parser to.
824   /// @param consume if true and the next found resynchronization token is
825   /// `tok` then sync_to() will also consume `tok`.
826   /// @return the state of #synchronized_.
827   /// @see sync().
828   bool sync_to(Token::Type tok, bool consume);
829   /// @return true if `t` is in the stack of resynchronization tokens.
830   /// @see sync().
831   bool is_sync_token(const Token& t) const;
832 
833   /// @returns true if #synchronized_ is true and the number of reported errors
834   /// is less than #max_errors_.
continue_parsing()835   bool continue_parsing() {
836     return synchronized_ && builder_.Diagnostics().error_count() < max_errors_;
837   }
838 
839   /// without_error() calls the function `func` muting any grammatical errors
840   /// found while executing the function. This can be used as a best-effort to
841   /// produce a meaningful error message when the parser is out of sync.
842   /// @param func a function or lambda with the signature: `Expect<Result>()` or
843   /// `Maybe<Result>()`.
844   /// @return the value returned by `func`
845   template <typename F, typename T = ReturnType<F>>
846   T without_error(F&& func);
847 
848   /// Reports an error if the decoration list `list` is not empty.
849   /// Used to ensure that all decorations are consumed.
850   bool expect_decorations_consumed(ast::DecorationList& list);
851 
852   Expect<const ast::Type*> expect_type_decl_pointer(Token t);
853   Expect<const ast::Type*> expect_type_decl_atomic(Token t);
854   Expect<const ast::Type*> expect_type_decl_vector(Token t);
855   Expect<const ast::Type*> expect_type_decl_array(Token t,
856                                                   ast::DecorationList decos);
857   Expect<const ast::Type*> expect_type_decl_matrix(Token t);
858 
859   Expect<const ast::Type*> expect_type(const std::string& use);
860 
861   Maybe<const ast::Statement*> non_block_statement();
862   Maybe<const ast::Statement*> for_header_initializer();
863   Maybe<const ast::Statement*> for_header_continuing();
864 
865   class MultiTokenSource;
866   MultiTokenSource make_source_range();
867   MultiTokenSource make_source_range_from(const Source& start);
868 
869   /// Creates a new `ast::Node` owned by the Module. When the Module is
870   /// destructed, the `ast::Node` will also be destructed.
871   /// @param args the arguments to pass to the type constructor
872   /// @returns the node pointer
873   template <typename T, typename... ARGS>
create(ARGS &&...args)874   T* create(ARGS&&... args) {
875     return builder_.create<T>(std::forward<ARGS>(args)...);
876   }
877 
878   std::unique_ptr<Lexer> lexer_;
879   std::deque<Token> token_queue_;
880   Token last_token_;
881   bool synchronized_ = true;
882   uint32_t parse_depth_ = 0;
883   std::vector<Token::Type> sync_tokens_;
884   int silence_errors_ = 0;
885   ProgramBuilder builder_;
886   size_t max_errors_ = 25;
887 };
888 
889 }  // namespace wgsl
890 }  // namespace reader
891 }  // namespace tint
892 
893 #endif  // SRC_READER_WGSL_PARSER_IMPL_H_
894