From d70f2511884d40d088162abde845f70d2b8f1885 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 4 Nov 2020 14:14:40 +0000 Subject: [PATCH] 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 Reviewed-by: dan sinclair --- src/reader/wgsl/parser_impl.cc | 72 ++++++++++++++++++++++++++++++++++ src/reader/wgsl/parser_impl.h | 36 +++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index 5252e963aa..f383deea3d 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -3621,6 +3621,78 @@ std::unique_ptr ParserImpl::const_expr_internal( 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(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(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 eb0a77fd9e..0cf0903039 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -428,6 +428,42 @@ class ParserImpl { std::unique_ptr 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);