From 4ce7a93202230111011b1554416de13f4c2b3a45 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 4 Nov 2020 18:39:41 +0000 Subject: [PATCH] wsgl parser: Add optional Source* out params ... to match() and expect_ident(). The uses of these two functions frequently want to know the souce of the matched token. Bug: tint:282 Change-Id: I5279fc2e0834f48d419c6d8c9888189f6212c44a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31732 Commit-Queue: dan sinclair Reviewed-by: dan sinclair --- src/reader/wgsl/parser_impl.cc | 73 ++++++++++++++++------------------ src/reader/wgsl/parser_impl.h | 10 ++++- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index d3e7536d23..e7b49a470b 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -457,10 +457,8 @@ std::unique_ptr ParserImpl::variable_decoration() { if (!expect("builtin decoration", Token::Type::kParenLeft)) return nullptr; - source = peek().source(); - std::string ident; - if (!expect_ident("builtin", &ident)) + if (!expect_ident("builtin", &ident, &source)) return nullptr; ast::Builtin builtin = ident_to_builtin(ident); @@ -1280,9 +1278,8 @@ bool ParserImpl::array_decoration_list(ast::ArrayDecorationList& decos) { next(); // consume the peek of [[ for (;;) { - auto source = peek().source(); - - if (!match(Token::Type::kStride)) { + Source source; + if (!match(Token::Type::kStride, &source)) { add_error(source, "unknown array decoration"); return false; } @@ -1596,9 +1593,8 @@ bool ParserImpl::struct_member_decoration_decl( // : OFFSET PAREN_LEFT INT_LITERAL PAREN_RIGHT std::unique_ptr ParserImpl::struct_member_decoration() { - auto source = peek().source(); - - if (!match(Token::Type::kOffset)) + Source source; + if (!match(Token::Type::kOffset, &source)) return nullptr; const char* use = "offset decoration"; @@ -1779,9 +1775,8 @@ ast::type::Type* ParserImpl::function_type_decl() { // function_header // : FN IDENT PAREN_LEFT param_list PAREN_RIGHT ARROW function_type_decl std::unique_ptr ParserImpl::function_header() { - auto source = peek().source(); - - if (!match(Token::Type::kFn)) + Source source; + if (!match(Token::Type::kFn, &source)) return nullptr; const char* use = "function declaration"; @@ -2071,9 +2066,8 @@ std::unique_ptr ParserImpl::statement() { // return_stmt // : RETURN logical_or_expression? std::unique_ptr ParserImpl::return_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kReturn)) + Source source; + if (!match(Token::Type::kReturn, &source)) return nullptr; std::unique_ptr expr = nullptr; @@ -2149,9 +2143,8 @@ std::unique_ptr ParserImpl::variable_stmt() { // if_stmt // : IF paren_rhs_stmt body_stmt elseif_stmt? else_stmt? std::unique_ptr ParserImpl::if_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kIf)) + Source source; + if (!match(Token::Type::kIf, &source)) return nullptr; auto condition = paren_rhs_stmt(); @@ -2239,9 +2232,8 @@ std::unique_ptr ParserImpl::else_stmt() { // switch_stmt // : SWITCH paren_rhs_stmt BRACKET_LEFT switch_body+ BRACKET_RIGHT std::unique_ptr ParserImpl::switch_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kSwitch)) + Source source; + if (!match(Token::Type::kSwitch, &source)) return nullptr; auto condition = paren_rhs_stmt(); @@ -2387,9 +2379,8 @@ std::unique_ptr ParserImpl::case_body() { // loop_stmt // : LOOP BRACKET_LEFT statements continuing_stmt? BRACKET_RIGHT std::unique_ptr ParserImpl::loop_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kLoop)) + Source source; + if (!match(Token::Type::kLoop, &source)) return nullptr; auto t = next(); @@ -2483,9 +2474,8 @@ std::unique_ptr ParserImpl::for_header() { // for_statement // : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT std::unique_ptr ParserImpl::for_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kFor)) + Source source; + if (!match(Token::Type::kFor, &source)) return nullptr; if (!expect("for loop", Token::Type::kParenLeft)) @@ -2591,9 +2581,8 @@ std::unique_ptr ParserImpl::func_call_stmt() { // break_stmt // : BREAK std::unique_ptr ParserImpl::break_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kBreak)) + Source source; + if (!match(Token::Type::kBreak, &source)) return nullptr; return std::make_unique(source); @@ -2602,9 +2591,8 @@ std::unique_ptr ParserImpl::break_stmt() { // continue_stmt // : CONTINUE std::unique_ptr ParserImpl::continue_stmt() { - auto source = peek().source(); - - if (!match(Token::Type::kContinue)) + Source source; + if (!match(Token::Type::kContinue, &source)) return nullptr; return std::make_unique(source); @@ -2760,10 +2748,8 @@ std::unique_ptr ParserImpl::postfix_expr( } else if (t.IsPeriod()) { next(); // Consume the peek - source = peek().source(); - std::string ident; - if (!expect_ident("member accessor", &ident)) + if (!expect_ident("member accessor", &ident, &source)) return nullptr; expr = std::make_unique( @@ -3402,8 +3388,12 @@ std::unique_ptr ParserImpl::const_expr_internal( std::move(lit)); } -bool ParserImpl::match(Token::Type tok) { +bool ParserImpl::match(Token::Type tok, Source* source /*= nullptr*/) { auto t = peek(); + + if (source != nullptr) + *source = t.source(); + if (t.Is(tok)) { next(); return true; @@ -3464,12 +3454,19 @@ bool ParserImpl::expect_nonzero_positive_sint(const std::string& use, return true; } -bool ParserImpl::expect_ident(const std::string& use, std::string* out) { +bool ParserImpl::expect_ident(const std::string& use, + std::string* out, + Source* source /* = nullptr */) { auto t = next(); + + if (source != nullptr) + *source = t.source(); + if (!t.IsIdentifier()) { add_error(t, "expected identifier", use); return false; } + *out = t.to_str(); return true; } diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index 815601789d..3cf023ffec 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -429,7 +429,9 @@ class ParserImpl { private: /// @returns true and consumes the next token if it equals |tok|. - bool match(Token::Type tok); + /// @param source if not nullptr, the next token's source is written to this + /// pointer, regardless of success or error + bool match(Token::Type tok, Source* source = nullptr); /// Errors if the next token is not equal to |tok|. /// Always consumes the next token. /// @param use a description of what was being parsed if an error was raised. @@ -461,8 +463,12 @@ class ParserImpl { /// Always consumes the next token. /// @param use a description of what was being parsed if an error was raised /// @param out the pointer to write the parsed identifier to + /// @param source if not nullptr, the next token's source is written to this + /// pointer, regardless of success or error /// @returns true if the identifier was parsed without error - bool expect_ident(const std::string& use, std::string* out); + bool expect_ident(const std::string& use, + std::string* out, + Source* source = nullptr); ast::type::Type* type_decl_pointer(Token t); ast::type::Type* type_decl_vector(Token t);