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 <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index d3e7536..e7b49a4 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -457,10 +457,8 @@
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 @@
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 @@
// : OFFSET PAREN_LEFT INT_LITERAL PAREN_RIGHT
std::unique_ptr<ast::StructMemberDecoration>
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 @@
// function_header
// : FN IDENT PAREN_LEFT param_list PAREN_RIGHT ARROW function_type_decl
std::unique_ptr<ast::Function> 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 @@
// return_stmt
// : RETURN logical_or_expression?
std::unique_ptr<ast::ReturnStatement> 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<ast::Expression> expr = nullptr;
@@ -2149,9 +2143,8 @@
// if_stmt
// : IF paren_rhs_stmt body_stmt elseif_stmt? else_stmt?
std::unique_ptr<ast::IfStatement> 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 @@
// switch_stmt
// : SWITCH paren_rhs_stmt BRACKET_LEFT switch_body+ BRACKET_RIGHT
std::unique_ptr<ast::SwitchStatement> 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 @@
// loop_stmt
// : LOOP BRACKET_LEFT statements continuing_stmt? BRACKET_RIGHT
std::unique_ptr<ast::LoopStatement> 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 @@
// for_statement
// : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT
std::unique_ptr<ast::Statement> 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 @@
// break_stmt
// : BREAK
std::unique_ptr<ast::BreakStatement> 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<ast::BreakStatement>(source);
@@ -2602,9 +2591,8 @@
// continue_stmt
// : CONTINUE
std::unique_ptr<ast::ContinueStatement> 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<ast::ContinueStatement>(source);
@@ -2760,10 +2748,8 @@
} 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<ast::MemberAccessorExpression>(
@@ -3402,8 +3388,12 @@
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 @@
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 8156017..3cf023f 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -429,7 +429,9 @@
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 @@
/// 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);