wsgl parser: Add match() and expect() helpers

These will be used to simplify common parser patterns.

Bug: tint:282
Change-Id: Ia281b9aa66b98f4afc726e876fe8aeae5ff4f12c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31724
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 5252e96..f383dee 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -3621,6 +3621,78 @@
                                                             std::move(lit));
 }
 
+bool ParserImpl::match(Token::Type tok) {
+  auto t = peek();
+  if (t.Is(tok)) {
+    next();
+    return true;
+  }
+  return false;
+}
+
+bool ParserImpl::expect(const std::string& use, Token::Type tok) {
+  auto t = next();
+  if (!t.Is(tok)) {
+    std::stringstream err;
+    err << "expected " << Token::TypeToName(tok);
+    if (!use.empty()) {
+      err << " for " << use;
+    }
+    add_error(t, err.str());
+    return false;
+  }
+  return true;
+}
+
+bool ParserImpl::expect_sint(const std::string& use, int32_t* out) {
+  auto t = next();
+  if (!t.IsSintLiteral()) {
+    add_error(t, "expected signed integer literal", use);
+    return false;
+  }
+  *out = t.to_i32();
+  return true;
+}
+
+bool ParserImpl::expect_positive_sint(const std::string& use, uint32_t* out) {
+  auto t = peek();
+  int32_t val;
+  if (!expect_sint(use, &val))
+    return false;
+
+  if (val < 0) {
+    add_error(t, use + " must be positive");
+    return false;
+  }
+  *out = static_cast<uint32_t>(val);
+  return true;
+}
+
+bool ParserImpl::expect_nonzero_positive_sint(const std::string& use,
+                                              uint32_t* out) {
+  auto t = peek();
+  int32_t val;
+  if (!expect_sint(use, &val))
+    return false;
+
+  if (val <= 0) {
+    add_error(t, use + " must be greater than 0");
+    return false;
+  }
+  *out = static_cast<uint32_t>(val);
+  return true;
+}
+
+bool ParserImpl::expect_ident(const std::string& use, std::string* out) {
+  auto t = next();
+  if (!t.IsIdentifier()) {
+    add_error(t, "expected identifier", use);
+    return false;
+  }
+  *out = t.to_str();
+  return true;
+}
+
 }  // namespace wgsl
 }  // namespace reader
 }  // namespace tint
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index eb0a77f..0cf0903 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -428,6 +428,42 @@
   std::unique_ptr<ast::AssignmentStatement> assignment_stmt();
 
  private:
+  /// @returns true and consumes the next token if it equals |tok|.
+  bool match(Token::Type tok);
+  /// 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.
+  /// @param tok the token to test against
+  /// @returns true if the next token equals |tok|.
+  bool expect(const std::string& use, Token::Type tok);
+  /// Parses a signed integer from the next token in the stream, erroring if the
+  /// next token is not a signed integer.
+  /// 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 integer to
+  /// @returns true if the signed integer was parsed without error
+  bool expect_sint(const std::string& use, int32_t* out);
+  /// Parses a signed integer from the next token in the stream, erroring if
+  /// the next token is not a signed integer or is negative.
+  /// 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 integer to
+  /// @returns true if the signed integer was parsed without error
+  bool expect_positive_sint(const std::string& use, uint32_t* out);
+  /// Parses a non-zero signed integer from the next token in the stream,
+  /// erroring if the next token is not a signed integer or is less than 1.
+  /// 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 integer to
+  /// @returns true if the signed integer was parsed without error
+  bool expect_nonzero_positive_sint(const std::string& use, uint32_t* out);
+  /// Errors if the next token is not an identifier.
+  /// 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
+  /// @returns true if the identifier was parsed without error
+  bool expect_ident(const std::string& use, std::string* out);
+
   ast::type::Type* type_decl_pointer(Token t);
   ast::type::Type* type_decl_vector(Token t);
   ast::type::Type* type_decl_array(Token t, ast::ArrayDecorationList decos);