wsgl parser: Add ParserImpl::Expect<T>
And use it for the ParserImpl::expect_xxx() methods. This is the first step towards supporting multiple error messages, as the caller can now test to see if the specific call errored, instead of using a global error state. Also cleans up a bunch of code. Bug: tint:282 Change-Id: I5e39fc33bd1e16620cee80d27fa728bc2af3387e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32101 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
f2e91857e1
commit
653c4042e2
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@
|
||||||
#ifndef SRC_READER_WGSL_PARSER_IMPL_H_
|
#ifndef SRC_READER_WGSL_PARSER_IMPL_H_
|
||||||
#define SRC_READER_WGSL_PARSER_IMPL_H_
|
#define SRC_READER_WGSL_PARSER_IMPL_H_
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -79,7 +80,61 @@ struct ForHeader {
|
||||||
|
|
||||||
/// ParserImpl for WGSL source data
|
/// ParserImpl for WGSL source data
|
||||||
class ParserImpl {
|
class ParserImpl {
|
||||||
|
/// Failure holds enumerator values used for the constructing an Expect in the
|
||||||
|
/// errored state.
|
||||||
|
struct Failure {
|
||||||
|
enum Errored { kErrored };
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Expect is the return type of the parser methods that are expected to
|
||||||
|
/// return a parsed value of type T, unless there was an parse error.
|
||||||
|
/// In the case of a parse error the called method will have called
|
||||||
|
/// |add_error()| and the Expect will have |errored| set to true.
|
||||||
|
template <typename T>
|
||||||
|
struct Expect {
|
||||||
|
/// An alias to the templated type T.
|
||||||
|
using type = T;
|
||||||
|
|
||||||
|
/// Don't allow an Expect to take a nullptr.
|
||||||
|
inline Expect(std::nullptr_t) = delete; // NOLINT
|
||||||
|
|
||||||
|
/// Constructor for a successful parse.
|
||||||
|
/// @param val the result value of the parse
|
||||||
|
/// @param s the optional source of the value
|
||||||
|
template <typename U>
|
||||||
|
inline Expect(U&& val, const Source& s = {}) // NOLINT
|
||||||
|
: value(std::forward<U>(val)), source(s) {}
|
||||||
|
|
||||||
|
/// Constructor for parse error.
|
||||||
|
inline Expect(Failure::Errored) : errored(true) {} // NOLINT
|
||||||
|
|
||||||
|
/// Copy constructor
|
||||||
|
inline Expect(const Expect&) = default;
|
||||||
|
/// Move constructor
|
||||||
|
inline Expect(Expect&&) = default;
|
||||||
|
/// Assignment operator
|
||||||
|
/// @return this Expect
|
||||||
|
inline Expect& operator=(const Expect&) = default;
|
||||||
|
/// Assignment move operator
|
||||||
|
/// @return this Expect
|
||||||
|
inline Expect& operator=(Expect&&) = default;
|
||||||
|
|
||||||
|
/// @return a pointer to |value|. |errored| must be false to call.
|
||||||
|
inline T* operator->() {
|
||||||
|
assert(!errored);
|
||||||
|
return &value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The expected value of a successful parse.
|
||||||
|
/// Zero-initialized when there was a parse error.
|
||||||
|
T value{};
|
||||||
|
/// Optional source of the value.
|
||||||
|
Source source;
|
||||||
|
/// True if there was a error parsing.
|
||||||
|
bool errored = false;
|
||||||
|
};
|
||||||
|
|
||||||
/// TypedIdentifier holds a parsed identifier and type. Returned by
|
/// TypedIdentifier holds a parsed identifier and type. Returned by
|
||||||
/// variable_ident_decl().
|
/// variable_ident_decl().
|
||||||
struct TypedIdentifier {
|
struct TypedIdentifier {
|
||||||
|
@ -130,19 +185,25 @@ class ParserImpl {
|
||||||
/// Appends an error at |t| with the message |msg|
|
/// Appends an error at |t| with the message |msg|
|
||||||
/// @param t the token to associate the error with
|
/// @param t the token to associate the error with
|
||||||
/// @param msg the error message
|
/// @param msg the error message
|
||||||
void add_error(const Token& t, const std::string& msg);
|
/// @return |errored| so that you can combine an add_error call and return on
|
||||||
|
/// the same line.
|
||||||
|
Failure::Errored add_error(const Token& t, const std::string& msg);
|
||||||
/// Appends an error raised when parsing |use| at |t| with the message |msg|
|
/// Appends an error raised when parsing |use| at |t| with the message |msg|
|
||||||
/// @param source the source to associate the error with
|
/// @param source the source to associate the error with
|
||||||
/// @param msg the error message
|
/// @param msg the error message
|
||||||
/// @param use a description of what was being parsed when the error was
|
/// @param use a description of what was being parsed when the error was
|
||||||
/// raised.
|
/// raised.
|
||||||
void add_error(const Source& source,
|
/// @return |errored| so that you can combine an add_error call and return on
|
||||||
|
/// the same line.
|
||||||
|
Failure::Errored add_error(const Source& source,
|
||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
const std::string& use);
|
const std::string& use);
|
||||||
/// Appends an error at |source| with the message |msg|
|
/// Appends an error at |source| with the message |msg|
|
||||||
/// @param source the source to associate the error with
|
/// @param source the source to associate the error with
|
||||||
/// @param msg the error message
|
/// @param msg the error message
|
||||||
void add_error(const Source& source, const std::string& msg);
|
/// @return |errored| so that you can combine an add_error call and return on
|
||||||
|
/// the same line.
|
||||||
|
Failure::Errored add_error(const Source& source, const std::string& msg);
|
||||||
|
|
||||||
/// Registers a constructed type into the parser
|
/// Registers a constructed type into the parser
|
||||||
/// @param name the constructed name
|
/// @param name the constructed name
|
||||||
|
@ -156,7 +217,8 @@ class ParserImpl {
|
||||||
/// Parses the `translation_unit` grammar element
|
/// Parses the `translation_unit` grammar element
|
||||||
void translation_unit();
|
void translation_unit();
|
||||||
/// Parses the `global_decl` grammar element, erroring on parse failure.
|
/// Parses the `global_decl` grammar element, erroring on parse failure.
|
||||||
void expect_global_decl();
|
/// @return true on parse success, otherwise an error.
|
||||||
|
Expect<bool> expect_global_decl();
|
||||||
/// Parses a `global_variable_decl` grammar element with the initial
|
/// Parses a `global_variable_decl` grammar element with the initial
|
||||||
/// `variable_decoration_list*` provided as |decos|.
|
/// `variable_decoration_list*` provided as |decos|.
|
||||||
/// @returns the variable parsed or nullptr
|
/// @returns the variable parsed or nullptr
|
||||||
|
@ -173,7 +235,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param use a description of what was being parsed if an error was raised.
|
/// @param use a description of what was being parsed if an error was raised.
|
||||||
/// @returns the identifier and type parsed or empty otherwise
|
/// @returns the identifier and type parsed or empty otherwise
|
||||||
TypedIdentifier expect_variable_ident_decl(const std::string& use);
|
Expect<TypedIdentifier> expect_variable_ident_decl(const std::string& use);
|
||||||
/// Parses a `variable_storage_decoration` grammar element
|
/// Parses a `variable_storage_decoration` grammar element
|
||||||
/// @returns the storage class or StorageClass::kNone if none matched
|
/// @returns the storage class or StorageClass::kNone if none matched
|
||||||
ast::StorageClass variable_storage_decoration();
|
ast::StorageClass variable_storage_decoration();
|
||||||
|
@ -183,10 +245,10 @@ class ParserImpl {
|
||||||
/// Parses a `type_decl` grammar element
|
/// Parses a `type_decl` grammar element
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
ast::type::Type* type_decl();
|
ast::type::Type* type_decl();
|
||||||
/// Parses a `storage_class` grammar element
|
/// Parses a `storage_class` grammar element, erroring on parse failure.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised.
|
||||||
/// @returns the storage class or StorageClass::kNone if none matched
|
/// @returns the storage class or StorageClass::kNone if none matched
|
||||||
ast::StorageClass expect_storage_class(const std::string& use);
|
Expect<ast::StorageClass> expect_storage_class(const std::string& use);
|
||||||
/// Parses a `struct_decl` grammar element with the initial
|
/// Parses a `struct_decl` grammar element with the initial
|
||||||
/// `struct_decoration_decl*` provided as |decos|.
|
/// `struct_decoration_decl*` provided as |decos|.
|
||||||
/// @returns the struct type or nullptr on error
|
/// @returns the struct type or nullptr on error
|
||||||
|
@ -195,13 +257,13 @@ class ParserImpl {
|
||||||
ast::DecorationList& decos);
|
ast::DecorationList& decos);
|
||||||
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
|
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
|
||||||
/// @returns the struct members
|
/// @returns the struct members
|
||||||
ast::StructMemberList expect_struct_body_decl();
|
Expect<ast::StructMemberList> expect_struct_body_decl();
|
||||||
/// Parses a `struct_member` grammar element with the initial
|
/// Parses a `struct_member` grammar element with the initial
|
||||||
/// `struct_member_decoration_decl+` provided as |decos|, erroring on parse
|
/// `struct_member_decoration_decl+` provided as |decos|, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param decos the list of decorations for the struct member.
|
/// @param decos the list of decorations for the struct member.
|
||||||
/// @returns the struct member or nullptr
|
/// @returns the struct member or nullptr
|
||||||
std::unique_ptr<ast::StructMember> expect_struct_member(
|
Expect<std::unique_ptr<ast::StructMember>> expect_struct_member(
|
||||||
ast::DecorationList& decos);
|
ast::DecorationList& decos);
|
||||||
/// Parses a `function_decl` grammar element with the initial
|
/// Parses a `function_decl` grammar element with the initial
|
||||||
/// `function_decoration_decl*` provided as |decos|.
|
/// `function_decoration_decl*` provided as |decos|.
|
||||||
|
@ -230,8 +292,10 @@ class ParserImpl {
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
ast::type::Type* depth_texture_type();
|
ast::type::Type* depth_texture_type();
|
||||||
/// Parses a `image_storage_type` grammar element
|
/// Parses a `image_storage_type` grammar element
|
||||||
|
/// @param use a description of what was being parsed if an error was raised.
|
||||||
/// @returns returns the image format or kNone if none matched.
|
/// @returns returns the image format or kNone if none matched.
|
||||||
ast::type::ImageFormat image_storage_type();
|
Expect<ast::type::ImageFormat> expect_image_storage_type(
|
||||||
|
const std::string& use);
|
||||||
/// Parses a `function_type_decl` grammar element
|
/// Parses a `function_type_decl` grammar element
|
||||||
/// @returns the parsed type or nullptr otherwise
|
/// @returns the parsed type or nullptr otherwise
|
||||||
ast::type::Type* function_type_decl();
|
ast::type::Type* function_type_decl();
|
||||||
|
@ -240,26 +304,24 @@ class ParserImpl {
|
||||||
std::unique_ptr<ast::Function> function_header();
|
std::unique_ptr<ast::Function> function_header();
|
||||||
/// Parses a `param_list` grammar element, erroring on parse failure.
|
/// Parses a `param_list` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed variables
|
/// @returns the parsed variables
|
||||||
ast::VariableList expect_param_list();
|
Expect<ast::VariableList> expect_param_list();
|
||||||
/// Parses a `pipeline_stage` grammar element, erroring if the next token does
|
/// Parses a `pipeline_stage` grammar element, erroring if the next token does
|
||||||
/// not match a stage name.
|
/// not match a stage name.
|
||||||
/// @returns the pipeline stage or PipelineStage::kNone if none matched, along
|
/// @returns the pipeline stage.
|
||||||
/// with the source location for the stage.
|
Expect<ast::PipelineStage> expect_pipeline_stage();
|
||||||
std::pair<ast::PipelineStage, Source> expect_pipeline_stage();
|
|
||||||
/// Parses a builtin identifier, erroring if the next token does not match a
|
/// Parses a builtin identifier, erroring if the next token does not match a
|
||||||
/// valid builtin name.
|
/// valid builtin name.
|
||||||
/// @returns the builtin or Builtin::kNone if none matched, along with the
|
/// @returns the parsed builtin.
|
||||||
/// source location for the stage.
|
Expect<ast::Builtin> expect_builtin();
|
||||||
std::pair<ast::Builtin, Source> expect_builtin();
|
|
||||||
/// Parses a `body_stmt` grammar element, erroring on parse failure.
|
/// Parses a `body_stmt` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
std::unique_ptr<ast::BlockStatement> expect_body_stmt();
|
Expect<std::unique_ptr<ast::BlockStatement>> expect_body_stmt();
|
||||||
/// Parses a `paren_rhs_stmt` grammar element, erroring on parse failure.
|
/// Parses a `paren_rhs_stmt` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed element or nullptr
|
/// @returns the parsed element or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_paren_rhs_stmt();
|
Expect<std::unique_ptr<ast::Expression>> expect_paren_rhs_stmt();
|
||||||
/// Parses a `statements` grammar element
|
/// Parses a `statements` grammar element
|
||||||
/// @returns the statements parsed
|
/// @returns the statements parsed
|
||||||
std::unique_ptr<ast::BlockStatement> statements();
|
Expect<std::unique_ptr<ast::BlockStatement>> expect_statements();
|
||||||
/// Parses a `statement` grammar element
|
/// Parses a `statement` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::Statement> statement();
|
std::unique_ptr<ast::Statement> statement();
|
||||||
|
@ -292,7 +354,7 @@ class ParserImpl {
|
||||||
std::unique_ptr<ast::CaseStatement> switch_body();
|
std::unique_ptr<ast::CaseStatement> switch_body();
|
||||||
/// Parses a `case_selectors` grammar element
|
/// Parses a `case_selectors` grammar element
|
||||||
/// @returns the list of literals
|
/// @returns the list of literals
|
||||||
ast::CaseSelectorList case_selectors();
|
Expect<ast::CaseSelectorList> expect_case_selectors();
|
||||||
/// Parses a `case_body` grammar element
|
/// Parses a `case_body` grammar element
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
std::unique_ptr<ast::BlockStatement> case_body();
|
std::unique_ptr<ast::BlockStatement> case_body();
|
||||||
|
@ -304,7 +366,7 @@ class ParserImpl {
|
||||||
std::unique_ptr<ast::LoopStatement> loop_stmt();
|
std::unique_ptr<ast::LoopStatement> loop_stmt();
|
||||||
/// Parses a `for_header` grammar element, erroring on parse failure.
|
/// Parses a `for_header` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed for header or nullptr
|
/// @returns the parsed for header or nullptr
|
||||||
std::unique_ptr<ForHeader> expect_for_header();
|
Expect<std::unique_ptr<ForHeader>> expect_for_header();
|
||||||
/// Parses a `for_stmt` grammar element
|
/// Parses a `for_stmt` grammar element
|
||||||
/// @returns the parsed for loop or nullptr
|
/// @returns the parsed for loop or nullptr
|
||||||
std::unique_ptr<ast::Statement> for_stmt();
|
std::unique_ptr<ast::Statement> for_stmt();
|
||||||
|
@ -316,14 +378,14 @@ class ParserImpl {
|
||||||
std::unique_ptr<ast::Literal> const_literal();
|
std::unique_ptr<ast::Literal> const_literal();
|
||||||
/// Parses a `const_expr` grammar element, erroring on parse failure.
|
/// Parses a `const_expr` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed constructor expression or nullptr on error
|
/// @returns the parsed constructor expression or nullptr on error
|
||||||
std::unique_ptr<ast::ConstructorExpression> expect_const_expr();
|
Expect<std::unique_ptr<ast::ConstructorExpression>> expect_const_expr();
|
||||||
/// Parses a `primary_expression` grammar element
|
/// Parses a `primary_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> primary_expression();
|
std::unique_ptr<ast::Expression> primary_expression();
|
||||||
/// Parses a `argument_expression_list` grammar element, erroring on parse
|
/// Parses a `argument_expression_list` grammar element, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @returns the list of arguments
|
/// @returns the list of arguments
|
||||||
ast::ExpressionList expect_argument_expression_list();
|
Expect<ast::ExpressionList> expect_argument_expression_list();
|
||||||
/// Parses the recursive portion of the postfix_expression
|
/// Parses the recursive portion of the postfix_expression
|
||||||
/// @param prefix the left side of the expression
|
/// @param prefix the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -339,7 +401,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_multiplicative_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_multiplicative_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `multiplicative_expression` grammar element
|
/// Parses the `multiplicative_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -348,7 +410,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_additive_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_additive_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `additive_expression` grammar element
|
/// Parses the `additive_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -357,7 +419,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_shift_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_shift_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `shift_expression` grammar element
|
/// Parses the `shift_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -366,7 +428,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_relational_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_relational_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `relational_expression` grammar element
|
/// Parses the `relational_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -375,7 +437,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_equality_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_equality_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `equality_expression` grammar element
|
/// Parses the `equality_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -384,7 +446,7 @@ class ParserImpl {
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_and_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_and_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `and_expression` grammar element
|
/// Parses the `and_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -393,7 +455,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_exclusive_or_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_exclusive_or_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `exclusive_or_expression` grammar elememnt
|
/// Parses the `exclusive_or_expression` grammar elememnt
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -402,7 +464,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_inclusive_or_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_inclusive_or_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses the `inclusive_or_expression` grammar element
|
/// Parses the `inclusive_or_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -411,7 +473,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_logical_and_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_logical_and_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses a `logical_and_expression` grammar element
|
/// Parses a `logical_and_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -420,7 +482,7 @@ class ParserImpl {
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> expect_logical_or_expr(
|
Expect<std::unique_ptr<ast::Expression>> expect_logical_or_expr(
|
||||||
std::unique_ptr<ast::Expression> lhs);
|
std::unique_ptr<ast::Expression> lhs);
|
||||||
/// Parses a `logical_or_expression` grammar element
|
/// Parses a `logical_or_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
|
@ -449,12 +511,16 @@ class ParserImpl {
|
||||||
/// represent a decoration.
|
/// represent a decoration.
|
||||||
/// @see #decoration for the full list of decorations this method parses.
|
/// @see #decoration for the full list of decorations this method parses.
|
||||||
/// @return the parsed decoration, or nullptr on error.
|
/// @return the parsed decoration, or nullptr on error.
|
||||||
std::unique_ptr<ast::Decoration> expect_decoration();
|
Expect<std::unique_ptr<ast::Decoration>> expect_decoration();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// ResultType resolves to the return type for the function or lambda F.
|
/// ReturnType resolves to the return type for the function or lambda F.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
using ResultType = typename std::result_of<F()>::type;
|
using ReturnType = typename std::result_of<F()>::type;
|
||||||
|
|
||||||
|
/// ResultType resolves to |T| for a |RESULT| of type Expect<T>.
|
||||||
|
template <typename RESULT>
|
||||||
|
using ResultType = typename RESULT::type;
|
||||||
|
|
||||||
/// @returns true and consumes the next token if it equals |tok|.
|
/// @returns true and consumes the next token if it equals |tok|.
|
||||||
/// @param source if not nullptr, the next token's source is written to this
|
/// @param source if not nullptr, the next token's source is written to this
|
||||||
|
@ -470,33 +536,25 @@ class ParserImpl {
|
||||||
/// next token is not a signed integer.
|
/// next token is not a signed integer.
|
||||||
/// Always consumes the next token.
|
/// Always consumes the next token.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @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 the parsed integer.
|
||||||
/// @returns true if the signed integer was parsed without error
|
Expect<int32_t> expect_sint(const std::string& use);
|
||||||
bool expect_sint(const std::string& use, int32_t* out);
|
|
||||||
/// Parses a signed integer from the next token in the stream, erroring if
|
/// Parses a signed integer from the next token in the stream, erroring if
|
||||||
/// the next token is not a signed integer or is negative.
|
/// the next token is not a signed integer or is negative.
|
||||||
/// Always consumes the next token.
|
/// Always consumes the next token.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @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 the parsed integer.
|
||||||
/// @returns true if the signed integer was parsed without error
|
Expect<uint32_t> expect_positive_sint(const std::string& use);
|
||||||
bool expect_positive_sint(const std::string& use, uint32_t* out);
|
|
||||||
/// Parses a non-zero signed integer from the next token in the stream,
|
/// 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.
|
/// erroring if the next token is not a signed integer or is less than 1.
|
||||||
/// Always consumes the next token.
|
/// Always consumes the next token.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @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 the parsed integer.
|
||||||
/// @returns true if the signed integer was parsed without error
|
Expect<uint32_t> expect_nonzero_positive_sint(const std::string& use);
|
||||||
bool expect_nonzero_positive_sint(const std::string& use, uint32_t* out);
|
|
||||||
/// Errors if the next token is not an identifier.
|
/// Errors if the next token is not an identifier.
|
||||||
/// Always consumes the next token.
|
/// Always consumes the next token.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @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 the parsed identifier.
|
||||||
/// @param source if not nullptr, the next token's source is written to this
|
Expect<std::string> expect_ident(const std::string& use);
|
||||||
/// 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,
|
|
||||||
Source* source = nullptr);
|
|
||||||
/// Parses a lexical block starting with the token |start| and ending with
|
/// Parses a lexical block starting with the token |start| and ending with
|
||||||
/// the token |end|. |body| is called to parse the lexical block body between
|
/// the token |end|. |body| is called to parse the lexical block body between
|
||||||
/// the |start| and |end| tokens.
|
/// the |start| and |end| tokens.
|
||||||
|
@ -508,10 +566,10 @@ class ParserImpl {
|
||||||
/// @param end the token that ends the lexical block
|
/// @param end the token that ends the lexical block
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @param body a function or lambda that is called to parse the lexical block
|
/// @param body a function or lambda that is called to parse the lexical block
|
||||||
/// body, with the signature T().
|
/// body, with the signature: `Expect<Result>()`.
|
||||||
/// @return the value returned by |body| if no errors are raised, otherwise
|
/// @return the value returned by |body| if no errors are raised, otherwise
|
||||||
/// a zero-initialized |T|.
|
/// a zero-initialized |T|.
|
||||||
template <typename F, typename T = ResultType<F>>
|
template <typename F, typename T = ReturnType<F>>
|
||||||
T expect_block(Token::Type start,
|
T expect_block(Token::Type start,
|
||||||
Token::Type end,
|
Token::Type end,
|
||||||
const std::string& use,
|
const std::string& use,
|
||||||
|
@ -521,36 +579,53 @@ class ParserImpl {
|
||||||
/// and |end| arguments, respectively.
|
/// and |end| arguments, respectively.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @param body a function or lambda that is called to parse the lexical block
|
/// @param body a function or lambda that is called to parse the lexical block
|
||||||
/// body, with the signature T().
|
/// body, with the signature: `Expect<Result>()`.
|
||||||
/// @return the value returned by |body| if no errors are raised, otherwise
|
/// @return the value returned by |body| if no errors are raised, otherwise
|
||||||
/// a zero-initialized |T|.
|
/// a zero-initialized |T|.
|
||||||
template <typename F, typename T = ResultType<F>>
|
template <typename F, typename T = ReturnType<F>>
|
||||||
T expect_paren_block(const std::string& use, F&& body);
|
T expect_paren_block(const std::string& use, F&& body);
|
||||||
/// A convenience function that calls |expect_block| passing
|
/// A convenience function that calls |expect_block| passing
|
||||||
/// |Token::Type::kBraceLeft| and |Token::Type::kBraceRight| for the |start|
|
/// |Token::Type::kBraceLeft| and |Token::Type::kBraceRight| for the |start|
|
||||||
/// and |end| arguments, respectively.
|
/// and |end| arguments, respectively.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @param body a function or lambda that is called to parse the lexical block
|
/// @param body a function or lambda that is called to parse the lexical block
|
||||||
/// body, with the signature T().
|
/// body, with the signature: `Expect<Result>()`.
|
||||||
/// @return the value returned by |body| if no errors are raised, otherwise
|
/// @return the value returned by |body| if no errors are raised, otherwise
|
||||||
/// a zero-initialized |T|.
|
/// a zero-initialized |T|.
|
||||||
template <typename F, typename T = ResultType<F>>
|
template <typename F, typename T = ReturnType<F>>
|
||||||
T expect_brace_block(const std::string& use, F&& body);
|
T expect_brace_block(const std::string& use, F&& body);
|
||||||
|
|
||||||
|
// Versions of expect_block(), expect_paren_block_old(),
|
||||||
|
// expect_brace_block_old() that do not take an Expect for T.
|
||||||
|
// These will be removed in the near future.
|
||||||
|
// TODO(ben-clayton) - migrate remaining uses of these.
|
||||||
|
template <typename F, typename T = ReturnType<F>>
|
||||||
|
T expect_block_old(Token::Type start,
|
||||||
|
Token::Type end,
|
||||||
|
const std::string& use,
|
||||||
|
F&& body);
|
||||||
|
template <typename F, typename T = ReturnType<F>>
|
||||||
|
T expect_paren_block_old(const std::string& use, F&& body);
|
||||||
|
template <typename F, typename T = ReturnType<F>>
|
||||||
|
T expect_brace_block_old(const std::string& use, F&& body);
|
||||||
|
|
||||||
/// Downcasts all the decorations in |list| to the type |T|, raising a parser
|
/// Downcasts all the decorations in |list| to the type |T|, raising a parser
|
||||||
/// error if any of the decorations aren't of the type |T|.
|
/// error if any of the decorations aren't of the type |T|.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<std::unique_ptr<T>> cast_decorations(ast::DecorationList& in);
|
Expect<std::vector<std::unique_ptr<T>>> cast_decorations(
|
||||||
|
ast::DecorationList& in);
|
||||||
/// Reports an error if the decoration list |list| is not empty.
|
/// Reports an error if the decoration list |list| is not empty.
|
||||||
/// Used to ensure that all decorations are consumed.
|
/// Used to ensure that all decorations are consumed.
|
||||||
bool expect_decorations_consumed(const ast::DecorationList& list);
|
bool expect_decorations_consumed(const ast::DecorationList& list);
|
||||||
|
|
||||||
ast::type::Type* expect_type_decl_pointer();
|
Expect<ast::type::Type*> expect_type_decl_pointer();
|
||||||
ast::type::Type* expect_type_decl_vector(Token t);
|
Expect<ast::type::Type*> expect_type_decl_vector(Token t);
|
||||||
ast::type::Type* expect_type_decl_array(ast::ArrayDecorationList decos);
|
Expect<ast::type::Type*> expect_type_decl_array(
|
||||||
ast::type::Type* expect_type_decl_matrix(Token t);
|
ast::ArrayDecorationList decos);
|
||||||
|
Expect<ast::type::Type*> expect_type_decl_matrix(Token t);
|
||||||
|
|
||||||
std::unique_ptr<ast::ConstructorExpression> expect_const_expr_internal(
|
Expect<std::unique_ptr<ast::ConstructorExpression>>
|
||||||
uint32_t depth);
|
expect_const_expr_internal(uint32_t depth);
|
||||||
|
|
||||||
Context& ctx_;
|
Context& ctx_;
|
||||||
diag::List diags_;
|
diag::List diags_;
|
||||||
|
|
|
@ -30,26 +30,29 @@ TEST_F(ParserImplTest, ArgumentExpressionList_Parses) {
|
||||||
auto* p = parser("a");
|
auto* p = parser("a");
|
||||||
auto e = p->expect_argument_expression_list();
|
auto e = p->expect_argument_expression_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.size(), 1u);
|
ASSERT_EQ(e.value.size(), 1u);
|
||||||
ASSERT_TRUE(e[0]->IsIdentifier());
|
ASSERT_TRUE(e.value[0]->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
||||||
auto* p = parser("a, -33, 1+2");
|
auto* p = parser("a, -33, 1+2");
|
||||||
auto e = p->expect_argument_expression_list();
|
auto e = p->expect_argument_expression_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_EQ(e.size(), 3u);
|
ASSERT_EQ(e.value.size(), 3u);
|
||||||
ASSERT_TRUE(e[0]->IsIdentifier());
|
ASSERT_TRUE(e.value[0]->IsIdentifier());
|
||||||
ASSERT_TRUE(e[1]->IsConstructor());
|
ASSERT_TRUE(e.value[1]->IsConstructor());
|
||||||
ASSERT_TRUE(e[2]->IsBinary());
|
ASSERT_TRUE(e.value[2]->IsBinary());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ArgumentExpressionList_HandlesMissingExpression) {
|
TEST_F(ParserImplTest, ArgumentExpressionList_HandlesMissingExpression) {
|
||||||
auto* p = parser("a, ");
|
auto* p = parser("a, ");
|
||||||
auto e = p->expect_argument_expression_list();
|
auto e = p->expect_argument_expression_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:4: unable to parse argument expression after comma");
|
EXPECT_EQ(p->error(), "1:4: unable to parse argument expression after comma");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +60,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_HandlesInvalidExpression) {
|
||||||
auto* p = parser("if(a) {}");
|
auto* p = parser("if(a) {}");
|
||||||
auto e = p->expect_argument_expression_list();
|
auto e = p->expect_argument_expression_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:1: unable to parse argument expression");
|
EXPECT_EQ(p->error(), "1:1: unable to parse argument expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,22 +28,25 @@ TEST_F(ParserImplTest, BodyStmt) {
|
||||||
})");
|
})");
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 2u);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e->get(0)->IsDiscard());
|
ASSERT_EQ(e.value->size(), 2u);
|
||||||
EXPECT_TRUE(e->get(1)->IsReturn());
|
EXPECT_TRUE(e.value->get(0)->IsDiscard());
|
||||||
|
EXPECT_TRUE(e.value->get(1)->IsReturn());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, BodyStmt_Empty) {
|
TEST_F(ParserImplTest, BodyStmt_Empty) {
|
||||||
auto* p = parser("{}");
|
auto* p = parser("{}");
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_EQ(e->size(), 0u);
|
ASSERT_FALSE(e.errored);
|
||||||
|
EXPECT_EQ(e.value->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
|
TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
|
||||||
auto* p = parser("{fn main() -> void {}}");
|
auto* p = parser("{fn main() -> void {}}");
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:2: expected '}'");
|
EXPECT_EQ(p->error(), "1:2: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +54,7 @@ TEST_F(ParserImplTest, BodyStmt_MissingRightParen) {
|
||||||
auto* p = parser("{return;");
|
auto* p = parser("{return;");
|
||||||
auto e = p->expect_body_stmt();
|
auto e = p->expect_body_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected '}'");
|
EXPECT_EQ(p->error(), "1:9: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,11 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
|
||||||
auto* p = parser("vec2<f32>(1., 2.)");
|
auto* p = parser("vec2<f32>(1., 2.)");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
|
||||||
|
|
||||||
auto* t = e->AsConstructor()->AsTypeConstructor();
|
auto* t = e.value->AsConstructor()->AsTypeConstructor();
|
||||||
ASSERT_TRUE(t->type()->IsVector());
|
ASSERT_TRUE(t->type()->IsVector());
|
||||||
EXPECT_EQ(t->type()->AsVector()->size(), 2u);
|
EXPECT_EQ(t->type()->AsVector()->size(), 2u);
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
|
||||||
auto* p = parser("vec2<f32>(1., 2.");
|
auto* p = parser("vec2<f32>(1., 2.");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:17: expected ')' for type constructor");
|
EXPECT_EQ(p->error(), "1:17: expected ')' for type constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +67,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingLeftParen) {
|
||||||
auto* p = parser("vec2<f32> 1., 2.)");
|
auto* p = parser("vec2<f32> 1., 2.)");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
|
EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +76,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_HangingComma) {
|
||||||
auto* p = parser("vec2<f32>(1.,)");
|
auto* p = parser("vec2<f32>(1.,)");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: unable to parse const literal");
|
EXPECT_EQ(p->error(), "1:14: unable to parse const literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +85,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingComma) {
|
||||||
auto* p = parser("vec2<f32>(1. 2.");
|
auto* p = parser("vec2<f32>(1. 2.");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: expected ')' for type constructor");
|
EXPECT_EQ(p->error(), "1:14: expected ')' for type constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +94,8 @@ TEST_F(ParserImplTest, ConstExpr_MissingExpr) {
|
||||||
auto* p = parser("vec2<f32>()");
|
auto* p = parser("vec2<f32>()");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:11: unable to parse const literal");
|
EXPECT_EQ(p->error(), "1:11: unable to parse const literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +103,8 @@ TEST_F(ParserImplTest, ConstExpr_InvalidExpr) {
|
||||||
auto* p = parser("vec2<f32>(1., if(a) {})");
|
auto* p = parser("vec2<f32>(1., if(a) {})");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
|
EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +112,11 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
|
||||||
auto* p = parser("true");
|
auto* p = parser("true");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsScalarConstructor());
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
auto* c = e->AsConstructor()->AsScalarConstructor();
|
ASSERT_TRUE(e.value->AsConstructor()->IsScalarConstructor());
|
||||||
|
auto* c = e.value->AsConstructor()->AsScalarConstructor();
|
||||||
ASSERT_TRUE(c->literal()->IsBool());
|
ASSERT_TRUE(c->literal()->IsBool());
|
||||||
EXPECT_TRUE(c->literal()->AsBool()->IsTrue());
|
EXPECT_TRUE(c->literal()->AsBool()->IsTrue());
|
||||||
}
|
}
|
||||||
|
@ -118,7 +125,8 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
|
||||||
auto* p = parser("invalid");
|
auto* p = parser("invalid");
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:1: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:1: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +142,8 @@ TEST_F(ParserImplTest, ConstExpr_Recursion) {
|
||||||
auto* p = parser(out.str());
|
auto* p = parser(out.str());
|
||||||
auto e = p->expect_const_expr();
|
auto e = p->expect_const_expr();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:517: max const_expr depth reached");
|
EXPECT_EQ(p->error(), "1:517: max const_expr depth reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,18 @@ class ForStmtTest : public ParserImplTest {
|
||||||
public:
|
public:
|
||||||
void TestForLoop(std::string loop_str, std::string for_str) {
|
void TestForLoop(std::string loop_str, std::string for_str) {
|
||||||
auto* p_loop = parser(loop_str);
|
auto* p_loop = parser(loop_str);
|
||||||
auto e_loop = p_loop->statements();
|
auto e_loop = p_loop->expect_statements();
|
||||||
ASSERT_FALSE(p_loop->has_error()) << p_loop->error();
|
EXPECT_FALSE(e_loop.errored);
|
||||||
ASSERT_NE(e_loop, nullptr);
|
EXPECT_FALSE(p_loop->has_error()) << p_loop->error();
|
||||||
|
ASSERT_NE(e_loop.value, nullptr);
|
||||||
|
|
||||||
auto* p_for = parser(for_str);
|
auto* p_for = parser(for_str);
|
||||||
auto e_for = p_for->statements();
|
auto e_for = p_for->expect_statements();
|
||||||
ASSERT_FALSE(p_for->has_error()) << p_for->error();
|
EXPECT_FALSE(e_for.errored);
|
||||||
ASSERT_NE(e_for, nullptr);
|
EXPECT_FALSE(p_for->has_error()) << p_for->error();
|
||||||
|
ASSERT_NE(e_for.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(e_loop->str(), e_for->str());
|
EXPECT_EQ(e_loop.value->str(), e_for.value->str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,253 +24,289 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Invalid) {
|
TEST_F(ParserImplTest, ImageStorageType_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kNone);
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), "1:1: invalid format for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R8Unorm) {
|
TEST_F(ParserImplTest, ImageStorageType_R8Unorm) {
|
||||||
auto* p = parser("r8unorm");
|
auto* p = parser("r8unorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR8Unorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR8Unorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R8Snorm) {
|
TEST_F(ParserImplTest, ImageStorageType_R8Snorm) {
|
||||||
auto* p = parser("r8snorm");
|
auto* p = parser("r8snorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR8Snorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR8Snorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R8Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_R8Uint) {
|
||||||
auto* p = parser("r8uint");
|
auto* p = parser("r8uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR8Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR8Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R8Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_R8Sint) {
|
||||||
auto* p = parser("r8sint");
|
auto* p = parser("r8sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR8Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR8Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R16Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_R16Uint) {
|
||||||
auto* p = parser("r16uint");
|
auto* p = parser("r16uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR16Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR16Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R16Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_R16Sint) {
|
||||||
auto* p = parser("r16sint");
|
auto* p = parser("r16sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR16Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR16Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R16Float) {
|
TEST_F(ParserImplTest, ImageStorageType_R16Float) {
|
||||||
auto* p = parser("r16float");
|
auto* p = parser("r16float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR16Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR16Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg8Unorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg8Unorm) {
|
||||||
auto* p = parser("rg8unorm");
|
auto* p = parser("rg8unorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg8Unorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg8Unorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg8Snorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg8Snorm) {
|
||||||
auto* p = parser("rg8snorm");
|
auto* p = parser("rg8snorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg8Snorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg8Snorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg8Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg8Uint) {
|
||||||
auto* p = parser("rg8uint");
|
auto* p = parser("rg8uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg8Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg8Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg8Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg8Sint) {
|
||||||
auto* p = parser("rg8sint");
|
auto* p = parser("rg8sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg8Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg8Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R32Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_R32Uint) {
|
||||||
auto* p = parser("r32uint");
|
auto* p = parser("r32uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR32Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR32Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R32Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_R32Sint) {
|
||||||
auto* p = parser("r32sint");
|
auto* p = parser("r32sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR32Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR32Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_R32Float) {
|
TEST_F(ParserImplTest, ImageStorageType_R32Float) {
|
||||||
auto* p = parser("r32float");
|
auto* p = parser("r32float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kR32Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kR32Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg16Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg16Uint) {
|
||||||
auto* p = parser("rg16uint");
|
auto* p = parser("rg16uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg16Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg16Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg16Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg16Sint) {
|
||||||
auto* p = parser("rg16sint");
|
auto* p = parser("rg16sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg16Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg16Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg16Float) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg16Float) {
|
||||||
auto* p = parser("rg16float");
|
auto* p = parser("rg16float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg16Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg16Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba8Unorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba8Unorm) {
|
||||||
auto* p = parser("rgba8unorm");
|
auto* p = parser("rgba8unorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba8Unorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba8Unorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba8UnormSrgb) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba8UnormSrgb) {
|
||||||
auto* p = parser("rgba8unorm_srgb");
|
auto* p = parser("rgba8unorm_srgb");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba8UnormSrgb);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba8UnormSrgb);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba8Snorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba8Snorm) {
|
||||||
auto* p = parser("rgba8snorm");
|
auto* p = parser("rgba8snorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba8Snorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba8Snorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba8Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba8Uint) {
|
||||||
auto* p = parser("rgba8uint");
|
auto* p = parser("rgba8uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba8Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba8Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba8Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba8Sint) {
|
||||||
auto* p = parser("rgba8sint");
|
auto* p = parser("rgba8sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba8Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba8Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Bgra8Unorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Bgra8Unorm) {
|
||||||
auto* p = parser("bgra8unorm");
|
auto* p = parser("bgra8unorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kBgra8Unorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kBgra8Unorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Bgra8UnormSrgb) {
|
TEST_F(ParserImplTest, ImageStorageType_Bgra8UnormSrgb) {
|
||||||
auto* p = parser("bgra8unorm_srgb");
|
auto* p = parser("bgra8unorm_srgb");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kBgra8UnormSrgb);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kBgra8UnormSrgb);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgb10A2Unorm) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgb10A2Unorm) {
|
||||||
auto* p = parser("rgb10a2unorm");
|
auto* p = parser("rgb10a2unorm");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgb10A2Unorm);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgb10A2Unorm);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg11B10Float) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg11B10Float) {
|
||||||
auto* p = parser("rg11b10float");
|
auto* p = parser("rg11b10float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg11B10Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg11B10Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg32Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg32Uint) {
|
||||||
auto* p = parser("rg32uint");
|
auto* p = parser("rg32uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg32Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg32Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg32Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg32Sint) {
|
||||||
auto* p = parser("rg32sint");
|
auto* p = parser("rg32sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg32Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg32Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rg32Float) {
|
TEST_F(ParserImplTest, ImageStorageType_Rg32Float) {
|
||||||
auto* p = parser("rg32float");
|
auto* p = parser("rg32float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRg32Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRg32Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba16Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba16Uint) {
|
||||||
auto* p = parser("rgba16uint");
|
auto* p = parser("rgba16uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba16Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba16Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba16Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba16Sint) {
|
||||||
auto* p = parser("rgba16sint");
|
auto* p = parser("rgba16sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba16Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba16Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba16Float) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba16Float) {
|
||||||
auto* p = parser("rgba16float");
|
auto* p = parser("rgba16float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba16Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba16Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba32Uint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba32Uint) {
|
||||||
auto* p = parser("rgba32uint");
|
auto* p = parser("rgba32uint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba32Uint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba32Uint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba32Sint) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba32Sint) {
|
||||||
auto* p = parser("rgba32sint");
|
auto* p = parser("rgba32sint");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba32Sint);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba32Sint);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ImageStorageType_Rgba32Float) {
|
TEST_F(ParserImplTest, ImageStorageType_Rgba32Float) {
|
||||||
auto* p = parser("rgba32float");
|
auto* p = parser("rgba32float");
|
||||||
auto t = p->image_storage_type();
|
auto t = p->expect_image_storage_type("test");
|
||||||
EXPECT_EQ(t, ast::type::ImageFormat::kRgba32Float);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::ImageFormat::kRgba32Float);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,16 +34,17 @@ TEST_F(ParserImplTest, ParamList_Single) {
|
||||||
auto* p = parser("a : i32");
|
auto* p = parser("a : i32");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_EQ(e.size(), 1u);
|
ASSERT_FALSE(e.errored);
|
||||||
|
EXPECT_EQ(e.value.size(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(e[0]->name(), "a");
|
EXPECT_EQ(e.value[0]->name(), "a");
|
||||||
EXPECT_EQ(e[0]->type(), i32);
|
EXPECT_EQ(e.value[0]->type(), i32);
|
||||||
EXPECT_TRUE(e[0]->is_const());
|
EXPECT_TRUE(e.value[0]->is_const());
|
||||||
|
|
||||||
ASSERT_EQ(e[0]->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.begin.column, 1u);
|
ASSERT_EQ(e.value[0]->source().range.begin.column, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.end.line, 1u);
|
ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.end.column, 2u);
|
ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParamList_Multiple) {
|
TEST_F(ParserImplTest, ParamList_Multiple) {
|
||||||
|
@ -54,47 +55,50 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
|
||||||
auto* p = parser("a : i32, b: f32, c: vec2<f32>");
|
auto* p = parser("a : i32, b: f32, c: vec2<f32>");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_EQ(e.size(), 3u);
|
ASSERT_FALSE(e.errored);
|
||||||
|
EXPECT_EQ(e.value.size(), 3u);
|
||||||
|
|
||||||
EXPECT_EQ(e[0]->name(), "a");
|
EXPECT_EQ(e.value[0]->name(), "a");
|
||||||
EXPECT_EQ(e[0]->type(), i32);
|
EXPECT_EQ(e.value[0]->type(), i32);
|
||||||
EXPECT_TRUE(e[0]->is_const());
|
EXPECT_TRUE(e.value[0]->is_const());
|
||||||
|
|
||||||
ASSERT_EQ(e[0]->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.begin.column, 1u);
|
ASSERT_EQ(e.value[0]->source().range.begin.column, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.end.line, 1u);
|
ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e[0]->source().range.end.column, 2u);
|
ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
|
||||||
|
|
||||||
EXPECT_EQ(e[1]->name(), "b");
|
EXPECT_EQ(e.value[1]->name(), "b");
|
||||||
EXPECT_EQ(e[1]->type(), f32);
|
EXPECT_EQ(e.value[1]->type(), f32);
|
||||||
EXPECT_TRUE(e[1]->is_const());
|
EXPECT_TRUE(e.value[1]->is_const());
|
||||||
|
|
||||||
ASSERT_EQ(e[1]->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value[1]->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e[1]->source().range.begin.column, 10u);
|
ASSERT_EQ(e.value[1]->source().range.begin.column, 10u);
|
||||||
ASSERT_EQ(e[1]->source().range.end.line, 1u);
|
ASSERT_EQ(e.value[1]->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e[1]->source().range.end.column, 11u);
|
ASSERT_EQ(e.value[1]->source().range.end.column, 11u);
|
||||||
|
|
||||||
EXPECT_EQ(e[2]->name(), "c");
|
EXPECT_EQ(e.value[2]->name(), "c");
|
||||||
EXPECT_EQ(e[2]->type(), vec2);
|
EXPECT_EQ(e.value[2]->type(), vec2);
|
||||||
EXPECT_TRUE(e[2]->is_const());
|
EXPECT_TRUE(e.value[2]->is_const());
|
||||||
|
|
||||||
ASSERT_EQ(e[2]->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value[2]->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e[2]->source().range.begin.column, 18u);
|
ASSERT_EQ(e.value[2]->source().range.begin.column, 18u);
|
||||||
ASSERT_EQ(e[2]->source().range.end.line, 1u);
|
ASSERT_EQ(e.value[2]->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e[2]->source().range.end.column, 19u);
|
ASSERT_EQ(e.value[2]->source().range.end.column, 19u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParamList_Empty) {
|
TEST_F(ParserImplTest, ParamList_Empty) {
|
||||||
auto* p = parser("");
|
auto* p = parser("");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(e.size(), 0u);
|
ASSERT_FALSE(e.errored);
|
||||||
|
EXPECT_EQ(e.value.size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParamList_HangingComma) {
|
TEST_F(ParserImplTest, ParamList_HangingComma) {
|
||||||
auto* p = parser("a : i32,");
|
auto* p = parser("a : i32,");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected identifier for parameter");
|
EXPECT_EQ(p->error(), "1:9: expected identifier for parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,17 @@ TEST_F(ParserImplTest, ParenRhsStmt) {
|
||||||
auto* p = parser("(a + b)");
|
auto* p = parser("(a + b)");
|
||||||
auto e = p->expect_paren_rhs_stmt();
|
auto e = p->expect_paren_rhs_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ParenRhsStmt_MissingLeftParen) {
|
TEST_F(ParserImplTest, ParenRhsStmt_MissingLeftParen) {
|
||||||
auto* p = parser("true)");
|
auto* p = parser("true)");
|
||||||
auto e = p->expect_paren_rhs_stmt();
|
auto e = p->expect_paren_rhs_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:1: expected '('");
|
EXPECT_EQ(p->error(), "1:1: expected '('");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +43,8 @@ TEST_F(ParserImplTest, ParenRhsStmt_MissingRightParen) {
|
||||||
auto* p = parser("(true");
|
auto* p = parser("(true");
|
||||||
auto e = p->expect_paren_rhs_stmt();
|
auto e = p->expect_paren_rhs_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected ')'");
|
EXPECT_EQ(p->error(), "1:6: expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +52,8 @@ TEST_F(ParserImplTest, ParenRhsStmt_InvalidExpression) {
|
||||||
auto* p = parser("(if (a() {})");
|
auto* p = parser("(if (a() {})");
|
||||||
auto e = p->expect_paren_rhs_stmt();
|
auto e = p->expect_paren_rhs_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +61,8 @@ TEST_F(ParserImplTest, ParenRhsStmt_MissingExpression) {
|
||||||
auto* p = parser("()");
|
auto* p = parser("()");
|
||||||
auto e = p->expect_paren_rhs_stmt();
|
auto e = p->expect_paren_rhs_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_TRUE(e.errored);
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,15 +36,14 @@ TEST_P(PipelineStageTest, Parses) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
|
|
||||||
ast::PipelineStage stage;
|
auto stage = p->expect_pipeline_stage();
|
||||||
Source source;
|
|
||||||
std::tie(stage, source) = p->expect_pipeline_stage();
|
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_EQ(stage, params.result);
|
ASSERT_FALSE(stage.errored);
|
||||||
EXPECT_EQ(source.range.begin.line, 1u);
|
EXPECT_EQ(stage.value, params.result);
|
||||||
EXPECT_EQ(source.range.begin.column, 1u);
|
EXPECT_EQ(stage.source.range.begin.line, 1u);
|
||||||
EXPECT_EQ(source.range.end.line, 1u);
|
EXPECT_EQ(stage.source.range.begin.column, 1u);
|
||||||
EXPECT_EQ(source.range.end.column, 1u + params.input.size());
|
EXPECT_EQ(stage.source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(stage.source.range.end.column, 1u + params.input.size());
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
EXPECT_TRUE(t.IsEof());
|
EXPECT_TRUE(t.IsEof());
|
||||||
|
@ -59,16 +58,10 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PipelineStage_NoMatch) {
|
TEST_F(ParserImplTest, PipelineStage_NoMatch) {
|
||||||
auto* p = parser("not-a-stage");
|
auto* p = parser("not-a-stage");
|
||||||
ast::PipelineStage stage;
|
auto stage = p->expect_pipeline_stage();
|
||||||
Source source;
|
|
||||||
std::tie(stage, source) = p->expect_pipeline_stage();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(stage.errored);
|
||||||
ASSERT_EQ(p->error(), "1:1: invalid value for stage decoration");
|
ASSERT_EQ(p->error(), "1:1: invalid value for stage decoration");
|
||||||
ASSERT_EQ(stage, ast::PipelineStage::kNone);
|
|
||||||
EXPECT_EQ(source.range.begin.line, 1u);
|
|
||||||
EXPECT_EQ(source.range.begin.column, 1u);
|
|
||||||
EXPECT_EQ(source.range.end.line, 1u);
|
|
||||||
EXPECT_EQ(source.range.end.column, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,18 +24,20 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statements) {
|
TEST_F(ParserImplTest, Statements) {
|
||||||
auto* p = parser("discard; return;");
|
auto* p = parser("discard; return;");
|
||||||
auto e = p->statements();
|
auto e = p->expect_statements();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->size(), 2u);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e->get(0)->IsDiscard());
|
ASSERT_EQ(e.value->size(), 2u);
|
||||||
EXPECT_TRUE(e->get(1)->IsReturn());
|
EXPECT_TRUE(e.value->get(0)->IsDiscard());
|
||||||
|
EXPECT_TRUE(e.value->get(1)->IsReturn());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statements_Empty) {
|
TEST_F(ParserImplTest, Statements_Empty) {
|
||||||
auto* p = parser("");
|
auto* p = parser("");
|
||||||
auto e = p->statements();
|
auto e = p->expect_statements();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->size(), 0u);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -38,8 +38,9 @@ TEST_P(StorageClassTest, Parses) {
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
|
|
||||||
auto sc = p->expect_storage_class("test");
|
auto sc = p->expect_storage_class("test");
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(sc.errored);
|
||||||
EXPECT_EQ(sc, params.result);
|
EXPECT_FALSE(p->has_error());
|
||||||
|
EXPECT_EQ(sc.value, params.result);
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
EXPECT_TRUE(t.IsEof());
|
EXPECT_TRUE(t.IsEof());
|
||||||
|
@ -62,8 +63,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TEST_F(ParserImplTest, StorageClass_NoMatch) {
|
TEST_F(ParserImplTest, StorageClass_NoMatch) {
|
||||||
auto* p = parser("not-a-storage-class");
|
auto* p = parser("not-a-storage-class");
|
||||||
auto sc = p->expect_storage_class("test");
|
auto sc = p->expect_storage_class("test");
|
||||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
EXPECT_EQ(sc.errored, true);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:1: invalid storage class for test");
|
EXPECT_EQ(p->error(), "1:1: invalid storage class for test");
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
|
|
|
@ -29,9 +29,10 @@ TEST_F(ParserImplTest, StructBodyDecl_Parses) {
|
||||||
auto* p = parser("{a : i32;}");
|
auto* p = parser("{a : i32;}");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(m.size(), 1u);
|
ASSERT_FALSE(m.errored);
|
||||||
|
ASSERT_EQ(m.value.size(), 1u);
|
||||||
|
|
||||||
const auto& mem = m[0];
|
const auto& mem = m.value[0];
|
||||||
EXPECT_EQ(mem->name(), "a");
|
EXPECT_EQ(mem->name(), "a");
|
||||||
EXPECT_EQ(mem->type(), i32);
|
EXPECT_EQ(mem->type(), i32);
|
||||||
EXPECT_EQ(mem->decorations().size(), 0u);
|
EXPECT_EQ(mem->decorations().size(), 0u);
|
||||||
|
@ -41,7 +42,8 @@ TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
|
||||||
auto* p = parser("{}");
|
auto* p = parser("{}");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(m.size(), 0u);
|
ASSERT_FALSE(m.errored);
|
||||||
|
ASSERT_EQ(m.value.size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_InvalidMember) {
|
TEST_F(ParserImplTest, StructBodyDecl_InvalidMember) {
|
||||||
|
@ -51,6 +53,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidMember) {
|
||||||
})");
|
})");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(m.errored);
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"3:12: expected signed integer literal for offset decoration");
|
"3:12: expected signed integer literal for offset decoration");
|
||||||
}
|
}
|
||||||
|
@ -59,6 +62,7 @@ TEST_F(ParserImplTest, StructBodyDecl_MissingClosingBracket) {
|
||||||
auto* p = parser("{a : i32;");
|
auto* p = parser("{a : i32;");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(m.errored);
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '}' for struct declaration");
|
EXPECT_EQ(p->error(), "1:10: expected '}' for struct declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +74,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidToken) {
|
||||||
} )");
|
} )");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(m.errored);
|
||||||
EXPECT_EQ(p->error(), "4:3: expected identifier for struct member");
|
EXPECT_EQ(p->error(), "4:3: expected identifier for struct member");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,16 +32,17 @@ TEST_F(ParserImplTest, StructMember_Parses) {
|
||||||
EXPECT_EQ(decos.size(), 0u);
|
EXPECT_EQ(decos.size(), 0u);
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_NE(m, nullptr);
|
ASSERT_FALSE(m.errored);
|
||||||
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(m->name(), "a");
|
EXPECT_EQ(m.value->name(), "a");
|
||||||
EXPECT_EQ(m->type(), i32);
|
EXPECT_EQ(m.value->type(), i32);
|
||||||
EXPECT_EQ(m->decorations().size(), 0u);
|
EXPECT_EQ(m.value->decorations().size(), 0u);
|
||||||
|
|
||||||
ASSERT_EQ(m->source().range.begin.line, 1u);
|
ASSERT_EQ(m.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(m->source().range.begin.column, 1u);
|
ASSERT_EQ(m.value->source().range.begin.column, 1u);
|
||||||
ASSERT_EQ(m->source().range.end.line, 1u);
|
ASSERT_EQ(m.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(m->source().range.end.column, 2u);
|
ASSERT_EQ(m.value->source().range.end.column, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
||||||
|
@ -52,18 +53,19 @@ TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
||||||
EXPECT_EQ(decos.size(), 1u);
|
EXPECT_EQ(decos.size(), 1u);
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_NE(m, nullptr);
|
ASSERT_FALSE(m.errored);
|
||||||
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(m->name(), "a");
|
EXPECT_EQ(m.value->name(), "a");
|
||||||
EXPECT_EQ(m->type(), i32);
|
EXPECT_EQ(m.value->type(), i32);
|
||||||
EXPECT_EQ(m->decorations().size(), 1u);
|
EXPECT_EQ(m.value->decorations().size(), 1u);
|
||||||
EXPECT_TRUE(m->decorations()[0]->IsOffset());
|
EXPECT_TRUE(m.value->decorations()[0]->IsOffset());
|
||||||
EXPECT_EQ(m->decorations()[0]->AsOffset()->offset(), 2u);
|
EXPECT_EQ(m.value->decorations()[0]->AsOffset()->offset(), 2u);
|
||||||
|
|
||||||
ASSERT_EQ(m->source().range.begin.line, 1u);
|
ASSERT_EQ(m.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(m->source().range.begin.column, 15u);
|
ASSERT_EQ(m.value->source().range.begin.column, 15u);
|
||||||
ASSERT_EQ(m->source().range.end.line, 1u);
|
ASSERT_EQ(m.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(m->source().range.end.column, 16u);
|
ASSERT_EQ(m.value->source().range.end.column, 16u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
|
TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
|
||||||
|
@ -75,20 +77,21 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
|
||||||
EXPECT_EQ(decos.size(), 2u);
|
EXPECT_EQ(decos.size(), 2u);
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_NE(m, nullptr);
|
ASSERT_FALSE(m.errored);
|
||||||
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(m->name(), "a");
|
EXPECT_EQ(m.value->name(), "a");
|
||||||
EXPECT_EQ(m->type(), i32);
|
EXPECT_EQ(m.value->type(), i32);
|
||||||
EXPECT_EQ(m->decorations().size(), 2u);
|
EXPECT_EQ(m.value->decorations().size(), 2u);
|
||||||
EXPECT_TRUE(m->decorations()[0]->IsOffset());
|
EXPECT_TRUE(m.value->decorations()[0]->IsOffset());
|
||||||
EXPECT_EQ(m->decorations()[0]->AsOffset()->offset(), 2u);
|
EXPECT_EQ(m.value->decorations()[0]->AsOffset()->offset(), 2u);
|
||||||
EXPECT_TRUE(m->decorations()[1]->IsOffset());
|
EXPECT_TRUE(m.value->decorations()[1]->IsOffset());
|
||||||
EXPECT_EQ(m->decorations()[1]->AsOffset()->offset(), 4u);
|
EXPECT_EQ(m.value->decorations()[1]->AsOffset()->offset(), 4u);
|
||||||
|
|
||||||
ASSERT_EQ(m->source().range.begin.line, 2u);
|
ASSERT_EQ(m.value->source().range.begin.line, 2u);
|
||||||
ASSERT_EQ(m->source().range.begin.column, 15u);
|
ASSERT_EQ(m.value->source().range.begin.column, 15u);
|
||||||
ASSERT_EQ(m->source().range.end.line, 2u);
|
ASSERT_EQ(m.value->source().range.end.line, 2u);
|
||||||
ASSERT_EQ(m->source().range.end.column, 16u);
|
ASSERT_EQ(m.value->source().range.end.column, 16u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
||||||
|
@ -96,7 +99,8 @@ TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(m, nullptr);
|
ASSERT_TRUE(m.errored);
|
||||||
|
ASSERT_EQ(m.value, nullptr);
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:10: expected signed integer literal for offset decoration");
|
"1:10: expected signed integer literal for offset decoration");
|
||||||
}
|
}
|
||||||
|
@ -106,7 +110,8 @@ TEST_F(ParserImplTest, StructMember_InvalidVariable) {
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(m, nullptr);
|
ASSERT_TRUE(m.errored);
|
||||||
|
ASSERT_EQ(m.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:19: unknown constructed type 'B'");
|
EXPECT_EQ(p->error(), "1:19: unknown constructed type 'B'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +120,8 @@ TEST_F(ParserImplTest, StructMember_MissingSemicolon) {
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
auto m = p->expect_struct_member(decos);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(m, nullptr);
|
ASSERT_TRUE(m.errored);
|
||||||
|
ASSERT_EQ(m.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ';' for struct member");
|
EXPECT_EQ(p->error(), "1:8: expected ';' for struct member");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,34 +25,38 @@ TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
||||||
auto* p = parser("my_var : f32");
|
auto* p = parser("my_var : f32");
|
||||||
auto decl = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(decl.name, "my_var");
|
ASSERT_FALSE(decl.errored);
|
||||||
ASSERT_NE(decl.type, nullptr);
|
ASSERT_EQ(decl->name, "my_var");
|
||||||
ASSERT_TRUE(decl.type->IsF32());
|
ASSERT_NE(decl->type, nullptr);
|
||||||
|
ASSERT_TRUE(decl->type->IsF32());
|
||||||
|
|
||||||
ASSERT_EQ(decl.source.range.begin.line, 1u);
|
ASSERT_EQ(decl->source.range.begin.line, 1u);
|
||||||
ASSERT_EQ(decl.source.range.begin.column, 1u);
|
ASSERT_EQ(decl->source.range.begin.column, 1u);
|
||||||
ASSERT_EQ(decl.source.range.end.line, 1u);
|
ASSERT_EQ(decl->source.range.end.line, 1u);
|
||||||
ASSERT_EQ(decl.source.range.end.column, 7u);
|
ASSERT_EQ(decl->source.range.end.column, 7u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
||||||
auto* p = parser(": f32");
|
auto* p = parser(": f32");
|
||||||
auto decl = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(decl.errored);
|
||||||
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
|
||||||
auto* p = parser("my_var f32");
|
auto* p = parser("my_var f32");
|
||||||
auto r = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(decl.errored);
|
||||||
ASSERT_EQ(p->error(), "1:8: expected ':' for test");
|
ASSERT_EQ(p->error(), "1:8: expected ':' for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
|
||||||
auto* p = parser("my_var :");
|
auto* p = parser("my_var :");
|
||||||
auto r = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(decl.errored);
|
||||||
ASSERT_EQ(p->error(), "1:9: invalid type for test");
|
ASSERT_EQ(p->error(), "1:9: invalid type for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,13 +64,15 @@ TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent) {
|
||||||
auto* p = parser("123 : f32");
|
auto* p = parser("123 : f32");
|
||||||
auto decl = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(decl.errored);
|
||||||
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_InvalidType) {
|
TEST_F(ParserImplTest, VariableIdentDecl_InvalidType) {
|
||||||
auto* p = parser("my_var : invalid");
|
auto* p = parser("my_var : invalid");
|
||||||
auto r = p->expect_variable_ident_decl("test");
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_TRUE(decl.errored);
|
||||||
ASSERT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
ASSERT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue