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