wsgl parser: Add ParserImpl::Maybe<T>
And use it for the non-ParserImpl::expect_xxx() methods. Another step towards supporting multiple error messages, as the caller can now test to see if the specific call errored, or didn't match, instead of using a global error state. Makes reading the control flow conditionals a bit easier too. Change-Id: Ie8627b8499ec9079167965da2a566401cd6bd903 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32102 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
653c4042e2
commit
ab5dfee240
File diff suppressed because it is too large
Load Diff
|
@ -80,10 +80,11 @@ 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
|
/// Failure holds enumerator values used for the constructing an Expect and
|
||||||
/// errored state.
|
/// Match in an errored state.
|
||||||
struct Failure {
|
struct Failure {
|
||||||
enum Errored { kErrored };
|
enum Errored { kErrored };
|
||||||
|
enum NoMatch { kNoMatch };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -135,6 +136,74 @@ class ParserImpl {
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Maybe is the return type of the parser methods that attempts to match a
|
||||||
|
/// grammar and return a parsed value of type T, or may parse part of the
|
||||||
|
/// grammar and then hit a parse error.
|
||||||
|
/// In the case of a successful grammar match, the Maybe will have |matched|
|
||||||
|
/// set to true.
|
||||||
|
/// In the case of a parse error the called method will have called
|
||||||
|
/// |add_error()| and the Maybe will have |errored| set to true.
|
||||||
|
template <typename T>
|
||||||
|
struct Maybe {
|
||||||
|
inline Maybe(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 Maybe(U&& val, const Source& s = {}) // NOLINT
|
||||||
|
: value(std::forward<U>(val)), source(s), matched(true) {}
|
||||||
|
|
||||||
|
/// Constructor for parse error state.
|
||||||
|
inline Maybe(Failure::Errored) : errored(true) {} // NOLINT
|
||||||
|
|
||||||
|
/// Constructor for the no-match state.
|
||||||
|
inline Maybe(Failure::NoMatch) {} // NOLINT
|
||||||
|
|
||||||
|
/// Constructor from an Expect.
|
||||||
|
template <typename U>
|
||||||
|
inline Maybe(const Expect<U>& e) // NOLINT
|
||||||
|
: value(e.value),
|
||||||
|
source(e.value),
|
||||||
|
errored(e.errored),
|
||||||
|
matched(!e.errored) {}
|
||||||
|
|
||||||
|
/// Move from an Expect.
|
||||||
|
template <typename U>
|
||||||
|
inline Maybe(Expect<U>&& e) // NOLINT
|
||||||
|
: value(std::move(e.value)),
|
||||||
|
source(std::move(e.source)),
|
||||||
|
errored(e.errored),
|
||||||
|
matched(!e.errored) {}
|
||||||
|
|
||||||
|
/// Copy constructor
|
||||||
|
inline Maybe(const Maybe&) = default;
|
||||||
|
/// Move constructor
|
||||||
|
inline Maybe(Maybe&&) = default;
|
||||||
|
/// Assignment operator
|
||||||
|
/// @return this Maybe
|
||||||
|
inline Maybe& operator=(const Maybe&) = default;
|
||||||
|
/// Assignment move operator
|
||||||
|
/// @return this Maybe
|
||||||
|
inline Maybe& operator=(Maybe&&) = default;
|
||||||
|
|
||||||
|
/// @return a pointer to |value|. |errored| must be false to call.
|
||||||
|
inline T* operator->() {
|
||||||
|
assert(!errored);
|
||||||
|
return &value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The 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;
|
||||||
|
/// True if there was a error parsing.
|
||||||
|
bool matched = 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 {
|
||||||
|
@ -223,14 +292,14 @@ class ParserImpl {
|
||||||
/// `variable_decoration_list*` provided as |decos|.
|
/// `variable_decoration_list*` provided as |decos|.
|
||||||
/// @returns the variable parsed or nullptr
|
/// @returns the variable parsed or nullptr
|
||||||
/// @param decos the list of decorations for the variable declaration.
|
/// @param decos the list of decorations for the variable declaration.
|
||||||
std::unique_ptr<ast::Variable> global_variable_decl(
|
Maybe<std::unique_ptr<ast::Variable>> global_variable_decl(
|
||||||
ast::DecorationList& decos);
|
ast::DecorationList& decos);
|
||||||
/// Parses a `global_constant_decl` grammar element
|
/// Parses a `global_constant_decl` grammar element
|
||||||
/// @returns the const object or nullptr
|
/// @returns the const object or nullptr
|
||||||
std::unique_ptr<ast::Variable> global_constant_decl();
|
Maybe<std::unique_ptr<ast::Variable>> global_constant_decl();
|
||||||
/// Parses a `variable_decl` grammar element
|
/// Parses a `variable_decl` grammar element
|
||||||
/// @returns the parsed variable or nullptr otherwise
|
/// @returns the parsed variable or nullptr otherwise
|
||||||
std::unique_ptr<ast::Variable> variable_decl();
|
Maybe<std::unique_ptr<ast::Variable>> variable_decl();
|
||||||
/// Parses a `variable_ident_decl` grammar element, erroring on parse
|
/// Parses a `variable_ident_decl` grammar element, erroring on parse
|
||||||
/// 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.
|
||||||
|
@ -238,13 +307,13 @@ class ParserImpl {
|
||||||
Expect<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();
|
Maybe<ast::StorageClass> variable_storage_decoration();
|
||||||
/// Parses a `type_alias` grammar element
|
/// Parses a `type_alias` grammar element
|
||||||
/// @returns the type alias or nullptr on error
|
/// @returns the type alias or nullptr on error
|
||||||
ast::type::Type* type_alias();
|
Maybe<ast::type::Type*> type_alias();
|
||||||
/// 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();
|
Maybe<ast::type::Type*> type_decl();
|
||||||
/// Parses a `storage_class` grammar element, erroring on parse failure.
|
/// 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
|
||||||
|
@ -253,7 +322,7 @@ class ParserImpl {
|
||||||
/// `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
|
||||||
/// @param decos the list of decorations for the struct declaration.
|
/// @param decos the list of decorations for the struct declaration.
|
||||||
std::unique_ptr<ast::type::StructType> struct_decl(
|
Maybe<std::unique_ptr<ast::type::StructType>> struct_decl(
|
||||||
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
|
||||||
|
@ -269,39 +338,40 @@ class ParserImpl {
|
||||||
/// `function_decoration_decl*` provided as |decos|.
|
/// `function_decoration_decl*` provided as |decos|.
|
||||||
/// @param decos the list of decorations for the function declaration.
|
/// @param decos the list of decorations for the function declaration.
|
||||||
/// @returns the parsed function, nullptr otherwise
|
/// @returns the parsed function, nullptr otherwise
|
||||||
std::unique_ptr<ast::Function> function_decl(ast::DecorationList& decos);
|
Maybe<std::unique_ptr<ast::Function>> function_decl(
|
||||||
|
ast::DecorationList& decos);
|
||||||
/// Parses a `texture_sampler_types` grammar element
|
/// Parses a `texture_sampler_types` grammar element
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
ast::type::Type* texture_sampler_types();
|
Maybe<ast::type::Type*> texture_sampler_types();
|
||||||
/// Parses a `sampler_type` grammar element
|
/// Parses a `sampler_type` grammar element
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
ast::type::Type* sampler_type();
|
Maybe<ast::type::Type*> sampler_type();
|
||||||
/// Parses a `multisampled_texture_type` grammar element
|
/// Parses a `multisampled_texture_type` grammar element
|
||||||
/// @returns returns the multisample texture dimension or kNone if none
|
/// @returns returns the multisample texture dimension or kNone if none
|
||||||
/// matched.
|
/// matched.
|
||||||
ast::type::TextureDimension multisampled_texture_type();
|
Maybe<ast::type::TextureDimension> multisampled_texture_type();
|
||||||
/// Parses a `sampled_texture_type` grammar element
|
/// Parses a `sampled_texture_type` grammar element
|
||||||
/// @returns returns the sample texture dimension or kNone if none matched.
|
/// @returns returns the sample texture dimension or kNone if none matched.
|
||||||
ast::type::TextureDimension sampled_texture_type();
|
Maybe<ast::type::TextureDimension> sampled_texture_type();
|
||||||
/// Parses a `storage_texture_type` grammar element
|
/// Parses a `storage_texture_type` grammar element
|
||||||
/// @returns returns the storage texture dimension and the storage access.
|
/// @returns returns the storage texture dimension and the storage access.
|
||||||
/// Returns kNone and kRead if none matched.
|
/// Returns kNone and kRead if none matched.
|
||||||
std::pair<ast::type::TextureDimension, ast::AccessControl>
|
Maybe<std::pair<ast::type::TextureDimension, ast::AccessControl>>
|
||||||
storage_texture_type();
|
storage_texture_type();
|
||||||
/// Parses a `depth_texture_type` grammar element
|
/// Parses a `depth_texture_type` grammar element
|
||||||
/// @returns the parsed Type or nullptr if none matched.
|
/// @returns the parsed Type or nullptr if none matched.
|
||||||
ast::type::Type* depth_texture_type();
|
Maybe<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.
|
/// @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.
|
||||||
Expect<ast::type::ImageFormat> expect_image_storage_type(
|
Expect<ast::type::ImageFormat> expect_image_storage_type(
|
||||||
const std::string& use);
|
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();
|
Maybe<ast::type::Type*> function_type_decl();
|
||||||
/// Parses a `function_header` grammar element
|
/// Parses a `function_header` grammar element
|
||||||
/// @returns the parsed function nullptr otherwise
|
/// @returns the parsed function nullptr otherwise
|
||||||
std::unique_ptr<ast::Function> function_header();
|
Maybe<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
|
||||||
Expect<ast::VariableList> expect_param_list();
|
Expect<ast::VariableList> expect_param_list();
|
||||||
|
@ -324,64 +394,64 @@ class ParserImpl {
|
||||||
Expect<std::unique_ptr<ast::BlockStatement>> expect_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();
|
Maybe<std::unique_ptr<ast::Statement>> statement();
|
||||||
/// Parses a `break_stmt` grammar element
|
/// Parses a `break_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::BreakStatement> break_stmt();
|
Maybe<std::unique_ptr<ast::BreakStatement>> break_stmt();
|
||||||
/// Parses a `return_stmt` grammar element
|
/// Parses a `return_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::ReturnStatement> return_stmt();
|
Maybe<std::unique_ptr<ast::ReturnStatement>> return_stmt();
|
||||||
/// Parses a `continue_stmt` grammar element
|
/// Parses a `continue_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::ContinueStatement> continue_stmt();
|
Maybe<std::unique_ptr<ast::ContinueStatement>> continue_stmt();
|
||||||
/// Parses a `variable_stmt` grammar element
|
/// Parses a `variable_stmt` grammar element
|
||||||
/// @returns the parsed variable or nullptr
|
/// @returns the parsed variable or nullptr
|
||||||
std::unique_ptr<ast::VariableDeclStatement> variable_stmt();
|
Maybe<std::unique_ptr<ast::VariableDeclStatement>> variable_stmt();
|
||||||
/// Parses a `if_stmt` grammar element
|
/// Parses a `if_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::IfStatement> if_stmt();
|
Maybe<std::unique_ptr<ast::IfStatement>> if_stmt();
|
||||||
/// Parses a `elseif_stmt` grammar element
|
/// Parses a `elseif_stmt` grammar element
|
||||||
/// @returns the parsed elements
|
/// @returns the parsed elements
|
||||||
ast::ElseStatementList elseif_stmt();
|
Maybe<ast::ElseStatementList> elseif_stmt();
|
||||||
/// Parses a `else_stmt` grammar element
|
/// Parses a `else_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::ElseStatement> else_stmt();
|
Maybe<std::unique_ptr<ast::ElseStatement>> else_stmt();
|
||||||
/// Parses a `switch_stmt` grammar element
|
/// Parses a `switch_stmt` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::SwitchStatement> switch_stmt();
|
Maybe<std::unique_ptr<ast::SwitchStatement>> switch_stmt();
|
||||||
/// Parses a `switch_body` grammar element
|
/// Parses a `switch_body` grammar element
|
||||||
/// @returns the parsed statement or nullptr
|
/// @returns the parsed statement or nullptr
|
||||||
std::unique_ptr<ast::CaseStatement> switch_body();
|
Maybe<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
|
||||||
Expect<ast::CaseSelectorList> expect_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();
|
Maybe<std::unique_ptr<ast::BlockStatement>> case_body();
|
||||||
/// Parses a `func_call_stmt` grammar element
|
/// Parses a `func_call_stmt` grammar element
|
||||||
/// @returns the parsed function call or nullptr
|
/// @returns the parsed function call or nullptr
|
||||||
std::unique_ptr<ast::CallStatement> func_call_stmt();
|
Maybe<std::unique_ptr<ast::CallStatement>> func_call_stmt();
|
||||||
/// Parses a `loop_stmt` grammar element
|
/// Parses a `loop_stmt` grammar element
|
||||||
/// @returns the parsed loop or nullptr
|
/// @returns the parsed loop or nullptr
|
||||||
std::unique_ptr<ast::LoopStatement> loop_stmt();
|
Maybe<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
|
||||||
Expect<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();
|
Maybe<std::unique_ptr<ast::Statement>> for_stmt();
|
||||||
/// Parses a `continuing_stmt` grammar element
|
/// Parses a `continuing_stmt` grammar element
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
std::unique_ptr<ast::BlockStatement> continuing_stmt();
|
Maybe<std::unique_ptr<ast::BlockStatement>> continuing_stmt();
|
||||||
/// Parses a `const_literal` grammar element
|
/// Parses a `const_literal` grammar element
|
||||||
/// @returns the const literal parsed or nullptr if none found
|
/// @returns the const literal parsed or nullptr if none found
|
||||||
std::unique_ptr<ast::Literal> const_literal();
|
Maybe<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
|
||||||
Expect<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();
|
Maybe<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
|
||||||
|
@ -389,14 +459,14 @@ class ParserImpl {
|
||||||
/// 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
|
||||||
std::unique_ptr<ast::Expression> postfix_expr(
|
Maybe<std::unique_ptr<ast::Expression>> postfix_expr(
|
||||||
std::unique_ptr<ast::Expression> prefix);
|
std::unique_ptr<ast::Expression> prefix);
|
||||||
/// Parses a `postfix_expression` grammar elment
|
/// Parses a `postfix_expression` grammar elment
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> postfix_expression();
|
Maybe<std::unique_ptr<ast::Expression>> postfix_expression();
|
||||||
/// Parses a `unary_expression` grammar element
|
/// Parses a `unary_expression` grammar element
|
||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
std::unique_ptr<ast::Expression> unary_expression();
|
Maybe<std::unique_ptr<ast::Expression>> unary_expression();
|
||||||
/// Parses the recursive part of the `multiplicative_expression`, erroring on
|
/// Parses the recursive part of the `multiplicative_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -405,7 +475,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> multiplicative_expression();
|
Maybe<std::unique_ptr<ast::Expression>> multiplicative_expression();
|
||||||
/// Parses the recursive part of the `additive_expression`, erroring on parse
|
/// Parses the recursive part of the `additive_expression`, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -414,7 +484,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> additive_expression();
|
Maybe<std::unique_ptr<ast::Expression>> additive_expression();
|
||||||
/// Parses the recursive part of the `shift_expression`, erroring on parse
|
/// Parses the recursive part of the `shift_expression`, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -423,7 +493,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> shift_expression();
|
Maybe<std::unique_ptr<ast::Expression>> shift_expression();
|
||||||
/// Parses the recursive part of the `relational_expression`, erroring on
|
/// Parses the recursive part of the `relational_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -432,7 +502,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> relational_expression();
|
Maybe<std::unique_ptr<ast::Expression>> relational_expression();
|
||||||
/// Parses the recursive part of the `equality_expression`, erroring on parse
|
/// Parses the recursive part of the `equality_expression`, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -441,7 +511,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> equality_expression();
|
Maybe<std::unique_ptr<ast::Expression>> equality_expression();
|
||||||
/// Parses the recursive part of the `and_expression`, erroring on parse
|
/// Parses the recursive part of the `and_expression`, erroring on parse
|
||||||
/// failure.
|
/// failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -450,7 +520,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> and_expression();
|
Maybe<std::unique_ptr<ast::Expression>> and_expression();
|
||||||
/// Parses the recursive part of the `exclusive_or_expression`, erroring on
|
/// Parses the recursive part of the `exclusive_or_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -459,7 +529,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> exclusive_or_expression();
|
Maybe<std::unique_ptr<ast::Expression>> exclusive_or_expression();
|
||||||
/// Parses the recursive part of the `inclusive_or_expression`, erroring on
|
/// Parses the recursive part of the `inclusive_or_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -468,7 +538,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> inclusive_or_expression();
|
Maybe<std::unique_ptr<ast::Expression>> inclusive_or_expression();
|
||||||
/// Parses the recursive part of the `logical_and_expression`, erroring on
|
/// Parses the recursive part of the `logical_and_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -477,7 +547,7 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> logical_and_expression();
|
Maybe<std::unique_ptr<ast::Expression>> logical_and_expression();
|
||||||
/// Parses the recursive part of the `logical_or_expression`, erroring on
|
/// Parses the recursive part of the `logical_or_expression`, erroring on
|
||||||
/// parse failure.
|
/// parse failure.
|
||||||
/// @param lhs the left side of the expression
|
/// @param lhs the left side of the expression
|
||||||
|
@ -486,18 +556,18 @@ class ParserImpl {
|
||||||
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
|
||||||
std::unique_ptr<ast::Expression> logical_or_expression();
|
Maybe<std::unique_ptr<ast::Expression>> logical_or_expression();
|
||||||
/// Parses a `assignment_stmt` grammar element
|
/// Parses a `assignment_stmt` grammar element
|
||||||
/// @returns the parsed assignment or nullptr
|
/// @returns the parsed assignment or nullptr
|
||||||
std::unique_ptr<ast::AssignmentStatement> assignment_stmt();
|
Maybe<std::unique_ptr<ast::AssignmentStatement>> assignment_stmt();
|
||||||
/// Parses one or more bracketed decoration lists.
|
/// Parses one or more bracketed decoration lists.
|
||||||
/// @return the parsed decoration list, or an empty list on error.
|
/// @return the parsed decoration list, or an empty list on error.
|
||||||
ast::DecorationList decoration_list();
|
Maybe<ast::DecorationList> decoration_list();
|
||||||
/// Parses a list of decorations between `ATTR_LEFT` and `ATTR_RIGHT`
|
/// Parses a list of decorations between `ATTR_LEFT` and `ATTR_RIGHT`
|
||||||
/// brackets.
|
/// brackets.
|
||||||
/// @param decos the list to append newly parsed decorations to.
|
/// @param decos the list to append newly parsed decorations to.
|
||||||
/// @return true if any decorations were be parsed, otherwise false.
|
/// @return true if any decorations were be parsed, otherwise false.
|
||||||
bool decoration_bracketed_list(ast::DecorationList& decos);
|
Maybe<bool> decoration_bracketed_list(ast::DecorationList& decos);
|
||||||
/// Parses a single decoration of the following types:
|
/// Parses a single decoration of the following types:
|
||||||
/// * `struct_decoration`
|
/// * `struct_decoration`
|
||||||
/// * `struct_member_decoration`
|
/// * `struct_member_decoration`
|
||||||
|
@ -506,7 +576,7 @@ class ParserImpl {
|
||||||
/// * `global_const_decoration`
|
/// * `global_const_decoration`
|
||||||
/// * `function_decoration`
|
/// * `function_decoration`
|
||||||
/// @return the parsed decoration, or nullptr.
|
/// @return the parsed decoration, or nullptr.
|
||||||
std::unique_ptr<ast::Decoration> decoration();
|
Maybe<std::unique_ptr<ast::Decoration>> decoration();
|
||||||
/// Parses a single decoration, reporting an error if the next token does not
|
/// Parses a single decoration, reporting an error if the next token does not
|
||||||
/// 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.
|
||||||
|
@ -568,7 +638,7 @@ class ParserImpl {
|
||||||
/// @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: `Expect<Result>()`.
|
/// 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|.
|
/// an Expect with error state.
|
||||||
template <typename F, typename T = ReturnType<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,
|
||||||
|
@ -581,7 +651,7 @@ class ParserImpl {
|
||||||
/// @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: `Expect<Result>()`.
|
/// 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|.
|
/// an Expect with error state.
|
||||||
template <typename F, typename T = ReturnType<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
|
||||||
|
@ -591,24 +661,10 @@ class ParserImpl {
|
||||||
/// @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: `Expect<Result>()`.
|
/// 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|.
|
/// an Expect with error state.
|
||||||
template <typename F, typename T = ReturnType<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>
|
||||||
|
@ -627,6 +683,9 @@ class ParserImpl {
|
||||||
Expect<std::unique_ptr<ast::ConstructorExpression>>
|
Expect<std::unique_ptr<ast::ConstructorExpression>>
|
||||||
expect_const_expr_internal(uint32_t depth);
|
expect_const_expr_internal(uint32_t depth);
|
||||||
|
|
||||||
|
Maybe<std::unique_ptr<ast::Statement>> for_header_initializer();
|
||||||
|
Maybe<std::unique_ptr<ast::Statement>> for_header_continuing();
|
||||||
|
|
||||||
Context& ctx_;
|
Context& ctx_;
|
||||||
diag::List diags_;
|
diag::List diags_;
|
||||||
std::unique_ptr<Lexer> lexer_;
|
std::unique_ptr<Lexer> lexer_;
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
||||||
auto* p = parser("a + true");
|
auto* p = parser("a + true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,11 +51,13 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
||||||
auto* p = parser("a - true");
|
auto* p = parser("a - true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -70,24 +74,30 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} + true");
|
auto* p = parser("if (a) {} + true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
||||||
auto* p = parser("true + if (a) {}");
|
auto* p = parser("true + if (a) {}");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of + expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of + expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, AndExpression_Parses) {
|
TEST_F(ParserImplTest, AndExpression_Parses) {
|
||||||
auto* p = parser("a & true");
|
auto* p = parser("a & true");
|
||||||
auto e = p->and_expression();
|
auto e = p->and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kAnd, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kAnd, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,24 +51,30 @@ TEST_F(ParserImplTest, AndExpression_Parses) {
|
||||||
TEST_F(ParserImplTest, AndExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, AndExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} & true");
|
auto* p = parser("if (a) {} & true");
|
||||||
auto e = p->and_expression();
|
auto e = p->and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AndExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, AndExpression_InvalidRHS) {
|
||||||
auto* p = parser("true & if (a) {}");
|
auto* p = parser("true & if (a) {}");
|
||||||
auto e = p->and_expression();
|
auto e = p->and_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of & expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of & expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AndExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, AndExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->and_expression();
|
auto e = p->and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -31,21 +31,23 @@ namespace {
|
||||||
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
||||||
auto* p = parser("a = 123");
|
auto* p = parser("a = 123");
|
||||||
auto e = p->assignment_stmt();
|
auto e = p->assignment_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsAssign());
|
ASSERT_TRUE(e.value->IsAssign());
|
||||||
ASSERT_NE(e->lhs(), nullptr);
|
ASSERT_NE(e.value->lhs(), nullptr);
|
||||||
ASSERT_NE(e->rhs(), nullptr);
|
ASSERT_NE(e.value->rhs(), nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->lhs()->IsIdentifier());
|
ASSERT_TRUE(e.value->lhs()->IsIdentifier());
|
||||||
auto* ident = e->lhs()->AsIdentifier();
|
auto* ident = e.value->lhs()->AsIdentifier();
|
||||||
EXPECT_EQ(ident->name(), "a");
|
EXPECT_EQ(ident->name(), "a");
|
||||||
|
|
||||||
ASSERT_TRUE(e->rhs()->IsConstructor());
|
ASSERT_TRUE(e.value->rhs()->IsConstructor());
|
||||||
ASSERT_TRUE(e->rhs()->AsConstructor()->IsScalarConstructor());
|
ASSERT_TRUE(e.value->rhs()->AsConstructor()->IsScalarConstructor());
|
||||||
|
|
||||||
auto* init = e->rhs()->AsConstructor()->AsScalarConstructor();
|
auto* init = e.value->rhs()->AsConstructor()->AsScalarConstructor();
|
||||||
ASSERT_NE(init->literal(), nullptr);
|
ASSERT_NE(init->literal(), nullptr);
|
||||||
ASSERT_TRUE(init->literal()->IsSint());
|
ASSERT_TRUE(init->literal()->IsSint());
|
||||||
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
|
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
|
||||||
|
@ -54,22 +56,24 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
||||||
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
||||||
auto* p = parser("a.b.c[2].d = 123");
|
auto* p = parser("a.b.c[2].d = 123");
|
||||||
auto e = p->assignment_stmt();
|
auto e = p->assignment_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsAssign());
|
ASSERT_TRUE(e.value->IsAssign());
|
||||||
ASSERT_NE(e->lhs(), nullptr);
|
ASSERT_NE(e.value->lhs(), nullptr);
|
||||||
ASSERT_NE(e->rhs(), nullptr);
|
ASSERT_NE(e.value->rhs(), nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->rhs()->IsConstructor());
|
ASSERT_TRUE(e.value->rhs()->IsConstructor());
|
||||||
ASSERT_TRUE(e->rhs()->AsConstructor()->IsScalarConstructor());
|
ASSERT_TRUE(e.value->rhs()->AsConstructor()->IsScalarConstructor());
|
||||||
auto* init = e->rhs()->AsConstructor()->AsScalarConstructor();
|
auto* init = e.value->rhs()->AsConstructor()->AsScalarConstructor();
|
||||||
ASSERT_NE(init->literal(), nullptr);
|
ASSERT_NE(init->literal(), nullptr);
|
||||||
ASSERT_TRUE(init->literal()->IsSint());
|
ASSERT_TRUE(init->literal()->IsSint());
|
||||||
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
|
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
|
||||||
|
|
||||||
ASSERT_TRUE(e->lhs()->IsMemberAccessor());
|
ASSERT_TRUE(e.value->lhs()->IsMemberAccessor());
|
||||||
auto* mem = e->lhs()->AsMemberAccessor();
|
auto* mem = e.value->lhs()->AsMemberAccessor();
|
||||||
|
|
||||||
ASSERT_TRUE(mem->member()->IsIdentifier());
|
ASSERT_TRUE(mem->member()->IsIdentifier());
|
||||||
auto* ident = mem->member()->AsIdentifier();
|
auto* ident = mem->member()->AsIdentifier();
|
||||||
|
@ -106,23 +110,29 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
||||||
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
|
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
|
||||||
auto* p = parser("a.b.c[2].d 123");
|
auto* p = parser("a.b.c[2].d 123");
|
||||||
auto e = p->assignment_stmt();
|
auto e = p->assignment_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:12: missing = for assignment");
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_EQ(p->error(), "1:12: expected '=' for assignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AssignmentStmt_InvalidLHS) {
|
TEST_F(ParserImplTest, AssignmentStmt_InvalidLHS) {
|
||||||
auto* p = parser("if (true) {} = 123");
|
auto* p = parser("if (true) {} = 123");
|
||||||
auto e = p->assignment_stmt();
|
auto e = p->assignment_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AssignmentStmt_InvalidRHS) {
|
TEST_F(ParserImplTest, AssignmentStmt_InvalidRHS) {
|
||||||
auto* p = parser("a.b.c[2].d = if (true) {}");
|
auto* p = parser("a.b.c[2].d = if (true) {}");
|
||||||
auto e = p->assignment_stmt();
|
auto e = p->assignment_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:14: unable to parse right side of assignment");
|
EXPECT_EQ(p->error(), "1:14: unable to parse right side of assignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,10 @@ namespace {
|
||||||
TEST_F(ParserImplTest, BreakStmt) {
|
TEST_F(ParserImplTest, BreakStmt) {
|
||||||
auto* p = parser("break");
|
auto* p = parser("break");
|
||||||
auto e = p->break_stmt();
|
auto e = p->break_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->IsBreak());
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsBreak());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,10 +28,12 @@ TEST_F(ParserImplTest, Statement_Call) {
|
||||||
auto* p = parser("a();");
|
auto* p = parser("a();");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e.value->IsCall());
|
||||||
auto* c = e->AsCall()->expr();
|
auto* c = e.value->AsCall()->expr();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
@ -44,10 +46,12 @@ TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
auto* p = parser("a(1, b, 2 + 3 / b);");
|
auto* p = parser("a(1, b, 2 + 3 / b);");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e.value->IsCall());
|
||||||
auto* c = e->AsCall()->expr();
|
auto* c = e.value->AsCall()->expr();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
@ -62,21 +66,27 @@ TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
TEST_F(ParserImplTest, Statement_Call_Missing_RightParen) {
|
TEST_F(ParserImplTest, Statement_Call_Missing_RightParen) {
|
||||||
auto* p = parser("a(");
|
auto* p = parser("a(");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(p->error(), "1:3: expected ')' for call statement");
|
EXPECT_EQ(p->error(), "1:3: expected ')' for call statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Call_Missing_Semi) {
|
TEST_F(ParserImplTest, Statement_Call_Missing_Semi) {
|
||||||
auto* p = parser("a()");
|
auto* p = parser("a()");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(p->error(), "1:4: expected ';' for function call");
|
EXPECT_EQ(p->error(), "1:4: expected ';' for function call");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Call_Bad_ArgList) {
|
TEST_F(ParserImplTest, Statement_Call_Bad_ArgList) {
|
||||||
auto* p = parser("a(b c);");
|
auto* p = parser("a(b c);");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(p->error(), "1:5: expected ')' for call statement");
|
EXPECT_EQ(p->error(), "1:5: expected ')' for call statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ TEST_F(ParserImplTest, CaseBody_Empty) {
|
||||||
auto* p = parser("");
|
auto* p = parser("");
|
||||||
auto e = p->case_body();
|
auto e = p->case_body();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_EQ(e->size(), 0u);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_EQ(e.value->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_Statements) {
|
TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||||
|
@ -35,31 +37,39 @@ TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||||
|
|
||||||
auto e = p->case_body();
|
auto e = p->case_body();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 2u);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e->get(0)->IsVariableDecl());
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_TRUE(e->get(1)->IsAssign());
|
ASSERT_EQ(e.value->size(), 2u);
|
||||||
|
EXPECT_TRUE(e.value->get(0)->IsVariableDecl());
|
||||||
|
EXPECT_TRUE(e.value->get(1)->IsAssign());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
|
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
|
||||||
auto* p = parser("a =");
|
auto* p = parser("a =");
|
||||||
auto e = p->case_body();
|
auto e = p->case_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_Fallthrough) {
|
TEST_F(ParserImplTest, CaseBody_Fallthrough) {
|
||||||
auto* p = parser("fallthrough;");
|
auto* p = parser("fallthrough;");
|
||||||
auto e = p->case_body();
|
auto e = p->case_body();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 1u);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e->get(0)->IsFallthrough());
|
EXPECT_TRUE(e.matched);
|
||||||
|
ASSERT_EQ(e.value->size(), 1u);
|
||||||
|
EXPECT_TRUE(e.value->get(0)->IsFallthrough());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
|
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
|
||||||
auto* p = parser("fallthrough");
|
auto* p = parser("fallthrough");
|
||||||
auto e = p->case_body();
|
auto e = p->case_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:12: expected ';' for fallthrough statement");
|
EXPECT_EQ(p->error(), "1:12: expected ';' for fallthrough statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,59 +28,73 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ConstLiteral_Int) {
|
TEST_F(ParserImplTest, ConstLiteral_Int) {
|
||||||
auto* p = parser("-234");
|
auto* p = parser("-234");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(c.matched);
|
||||||
ASSERT_NE(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
ASSERT_TRUE(c->IsSint());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(c->AsSint()->value(), -234);
|
ASSERT_NE(c.value, nullptr);
|
||||||
|
ASSERT_TRUE(c.value->IsSint());
|
||||||
|
EXPECT_EQ(c.value->AsSint()->value(), -234);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_Uint) {
|
TEST_F(ParserImplTest, ConstLiteral_Uint) {
|
||||||
auto* p = parser("234u");
|
auto* p = parser("234u");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(c.matched);
|
||||||
ASSERT_NE(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
ASSERT_TRUE(c->IsUint());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(c->AsUint()->value(), 234u);
|
ASSERT_NE(c.value, nullptr);
|
||||||
|
ASSERT_TRUE(c.value->IsUint());
|
||||||
|
EXPECT_EQ(c.value->AsUint()->value(), 234u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_Float) {
|
TEST_F(ParserImplTest, ConstLiteral_Float) {
|
||||||
auto* p = parser("234.e12");
|
auto* p = parser("234.e12");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(c.matched);
|
||||||
ASSERT_NE(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
ASSERT_TRUE(c->IsFloat());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_FLOAT_EQ(c->AsFloat()->value(), 234e12f);
|
ASSERT_NE(c.value, nullptr);
|
||||||
|
ASSERT_TRUE(c.value->IsFloat());
|
||||||
|
EXPECT_FLOAT_EQ(c.value->AsFloat()->value(), 234e12f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_InvalidFloat) {
|
TEST_F(ParserImplTest, ConstLiteral_InvalidFloat) {
|
||||||
auto* p = parser("1.2e+256");
|
auto* p = parser("1.2e+256");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_EQ(c, nullptr);
|
EXPECT_FALSE(c.matched);
|
||||||
|
EXPECT_FALSE(c.errored);
|
||||||
|
ASSERT_EQ(c.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_True) {
|
TEST_F(ParserImplTest, ConstLiteral_True) {
|
||||||
auto* p = parser("true");
|
auto* p = parser("true");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(c.matched);
|
||||||
ASSERT_NE(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
ASSERT_TRUE(c->IsBool());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_TRUE(c->AsBool()->IsTrue());
|
ASSERT_NE(c.value, nullptr);
|
||||||
|
ASSERT_TRUE(c.value->IsBool());
|
||||||
|
EXPECT_TRUE(c.value->AsBool()->IsTrue());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_False) {
|
TEST_F(ParserImplTest, ConstLiteral_False) {
|
||||||
auto* p = parser("false");
|
auto* p = parser("false");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(c.matched);
|
||||||
ASSERT_NE(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
ASSERT_TRUE(c->IsBool());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_TRUE(c->AsBool()->IsFalse());
|
ASSERT_NE(c.value, nullptr);
|
||||||
|
ASSERT_TRUE(c.value->IsBool());
|
||||||
|
EXPECT_TRUE(c.value->AsBool()->IsFalse());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
|
TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
|
||||||
auto* p = parser("another-token");
|
auto* p = parser("another-token");
|
||||||
auto c = p->const_literal();
|
auto c = p->const_literal();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(c.matched);
|
||||||
ASSERT_EQ(c, nullptr);
|
EXPECT_FALSE(c.errored);
|
||||||
|
EXPECT_FALSE(p->has_error());
|
||||||
|
ASSERT_EQ(c.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,9 +25,10 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ContinueStmt) {
|
TEST_F(ParserImplTest, ContinueStmt) {
|
||||||
auto* p = parser("continue");
|
auto* p = parser("continue");
|
||||||
auto e = p->continue_stmt();
|
auto e = p->continue_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->IsContinue());
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsContinue());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,16 +24,20 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ContinuingStmt) {
|
TEST_F(ParserImplTest, ContinuingStmt) {
|
||||||
auto* p = parser("continuing { discard; }");
|
auto* p = parser("continuing { discard; }");
|
||||||
auto e = p->continuing_stmt();
|
auto e = p->continuing_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e->size(), 1u);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->get(0)->IsDiscard());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value->size(), 1u);
|
||||||
|
ASSERT_TRUE(e.value->get(0)->IsDiscard());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
||||||
auto* p = parser("continuing { discard }");
|
auto* p = parser("continuing { discard }");
|
||||||
auto e = p->continuing_stmt();
|
auto e = p->continuing_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:22: expected ';' for discard statement");
|
EXPECT_EQ(p->error(), "1:22: expected ';' for discard statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,48 +24,58 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DepthTextureType_Invalid) {
|
TEST_F(ParserImplTest, DepthTextureType_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto* t = p->depth_texture_type();
|
auto t = p->depth_texture_type();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DepthTextureType_2d) {
|
TEST_F(ParserImplTest, DepthTextureType_2d) {
|
||||||
auto* p = parser("texture_depth_2d");
|
auto* p = parser("texture_depth_2d");
|
||||||
auto* t = p->depth_texture_type();
|
auto t = p->depth_texture_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsDepth());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsDepth());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DepthTextureType_2dArray) {
|
TEST_F(ParserImplTest, DepthTextureType_2dArray) {
|
||||||
auto* p = parser("texture_depth_2d_array");
|
auto* p = parser("texture_depth_2d_array");
|
||||||
auto* t = p->depth_texture_type();
|
auto t = p->depth_texture_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsDepth());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2dArray);
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsDepth());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2dArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DepthTextureType_Cube) {
|
TEST_F(ParserImplTest, DepthTextureType_Cube) {
|
||||||
auto* p = parser("texture_depth_cube");
|
auto* p = parser("texture_depth_cube");
|
||||||
auto* t = p->depth_texture_type();
|
auto t = p->depth_texture_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsDepth());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::kCube);
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsDepth());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::kCube);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DepthTextureType_CubeArray) {
|
TEST_F(ParserImplTest, DepthTextureType_CubeArray) {
|
||||||
auto* p = parser("texture_depth_cube_array");
|
auto* p = parser("texture_depth_cube_array");
|
||||||
auto* t = p->depth_texture_type();
|
auto t = p->depth_texture_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsDepth());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::kCubeArray);
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsDepth());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(),
|
||||||
|
ast::type::TextureDimension::kCubeArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,26 +25,32 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ElseStmt) {
|
TEST_F(ParserImplTest, ElseStmt) {
|
||||||
auto* p = parser("else { a = b; c = d; }");
|
auto* p = parser("else { a = b; c = d; }");
|
||||||
auto e = p->else_stmt();
|
auto e = p->else_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsElse());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->condition(), nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
ASSERT_TRUE(e.value->IsElse());
|
||||||
|
ASSERT_EQ(e.value->condition(), nullptr);
|
||||||
|
EXPECT_EQ(e.value->body()->size(), 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
|
TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
|
||||||
auto* p = parser("else { fn main() -> void {}}");
|
auto* p = parser("else { fn main() -> void {}}");
|
||||||
auto e = p->else_stmt();
|
auto e = p->else_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '}'");
|
EXPECT_EQ(p->error(), "1:8: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ElseStmt_MissingBody) {
|
TEST_F(ParserImplTest, ElseStmt_MissingBody) {
|
||||||
auto* p = parser("else");
|
auto* p = parser("else");
|
||||||
auto e = p->else_stmt();
|
auto e = p->else_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:5: expected '{'");
|
EXPECT_EQ(p->error(), "1:5: expected '{'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,43 +25,51 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ElseIfStmt) {
|
TEST_F(ParserImplTest, ElseIfStmt) {
|
||||||
auto* p = parser("elseif (a == 4) { a = b; c = d; }");
|
auto* p = parser("elseif (a == 4) { a = b; c = d; }");
|
||||||
auto e = p->elseif_stmt();
|
auto e = p->elseif_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e.size(), 1u);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value.size(), 1u);
|
||||||
|
|
||||||
ASSERT_TRUE(e[0]->IsElse());
|
ASSERT_TRUE(e.value[0]->IsElse());
|
||||||
ASSERT_NE(e[0]->condition(), nullptr);
|
ASSERT_NE(e.value[0]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e[0]->condition()->IsBinary());
|
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
||||||
EXPECT_EQ(e[0]->body()->size(), 2u);
|
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
|
TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
|
||||||
auto* p = parser("elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }");
|
auto* p = parser("elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }");
|
||||||
auto e = p->elseif_stmt();
|
auto e = p->elseif_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e.size(), 2u);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value.size(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(e[0]->IsElse());
|
ASSERT_TRUE(e.value[0]->IsElse());
|
||||||
ASSERT_NE(e[0]->condition(), nullptr);
|
ASSERT_NE(e.value[0]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e[0]->condition()->IsBinary());
|
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
||||||
EXPECT_EQ(e[0]->body()->size(), 2u);
|
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(e[1]->IsElse());
|
ASSERT_TRUE(e.value[1]->IsElse());
|
||||||
ASSERT_NE(e[1]->condition(), nullptr);
|
ASSERT_NE(e.value[1]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e[1]->condition()->IsIdentifier());
|
ASSERT_TRUE(e.value[1]->condition()->IsIdentifier());
|
||||||
EXPECT_EQ(e[1]->body()->size(), 1u);
|
EXPECT_EQ(e.value[1]->body()->size(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
|
TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
|
||||||
auto* p = parser("elseif (true) { fn main() -> void {}}");
|
auto* p = parser("elseif (true) { fn main() -> void {}}");
|
||||||
auto e = p->elseif_stmt();
|
auto e = p->elseif_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:17: expected '}'");
|
EXPECT_EQ(p->error(), "1:17: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ElseIfStmt_MissingBody) {
|
TEST_F(ParserImplTest, ElseIfStmt_MissingBody) {
|
||||||
auto* p = parser("elseif (true)");
|
auto* p = parser("elseif (true)");
|
||||||
auto e = p->elseif_stmt();
|
auto e = p->elseif_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:14: expected '{'");
|
EXPECT_EQ(p->error(), "1:14: expected '{'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
|
TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
|
||||||
auto* p = parser("a == true");
|
auto* p = parser("a == true");
|
||||||
auto e = p->equality_expression();
|
auto e = p->equality_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kEqual, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kEqual, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,11 +51,13 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
|
||||||
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
|
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
|
||||||
auto* p = parser("a != true");
|
auto* p = parser("a != true");
|
||||||
auto e = p->equality_expression();
|
auto e = p->equality_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -70,24 +74,30 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
|
||||||
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} == true");
|
auto* p = parser("if (a) {} == true");
|
||||||
auto e = p->equality_expression();
|
auto e = p->equality_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, EqualityExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, EqualityExpression_InvalidRHS) {
|
||||||
auto* p = parser("true == if (a) {}");
|
auto* p = parser("true == if (a) {}");
|
||||||
auto e = p->equality_expression();
|
auto e = p->equality_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of == expression");
|
EXPECT_EQ(p->error(), "1:9: unable to parse right side of == expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, EqualityExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, EqualityExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->equality_expression();
|
auto e = p->equality_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -56,21 +56,21 @@ TEST_F(ParserImplErrorTest, ArrayIndexExprInvalidExpr) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, ArrayIndexExprMissingRBracket) {
|
TEST_F(ParserImplErrorTest, ArrayIndexExprMissingRBracket) {
|
||||||
EXPECT("fn f() -> void { x = y[1; }",
|
EXPECT("fn f() -> void { x = y[1; }",
|
||||||
"test.wgsl:1:25 error: missing ] for array accessor\n"
|
"test.wgsl:1:25 error: expected ']' for array accessor\n"
|
||||||
"fn f() -> void { x = y[1; }\n"
|
"fn f() -> void { x = y[1; }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment) {
|
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment) {
|
||||||
EXPECT("fn f() -> void { a; }",
|
EXPECT("fn f() -> void { a; }",
|
||||||
"test.wgsl:1:19 error: missing = for assignment\n"
|
"test.wgsl:1:19 error: expected '=' for assignment\n"
|
||||||
"fn f() -> void { a; }\n"
|
"fn f() -> void { a; }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment2) {
|
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment2) {
|
||||||
EXPECT("fn f() -> void { a : i32; }",
|
EXPECT("fn f() -> void { a : i32; }",
|
||||||
"test.wgsl:1:20 error: missing = for assignment\n"
|
"test.wgsl:1:20 error: expected '=' for assignment\n"
|
||||||
"fn f() -> void { a : i32; }\n"
|
"fn f() -> void { a : i32; }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -91,14 +91,14 @@ TEST_F(ParserImplErrorTest, AssignmentStmtInvalidRHS) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, BitcastExprMissingLessThan) {
|
TEST_F(ParserImplErrorTest, BitcastExprMissingLessThan) {
|
||||||
EXPECT("fn f() -> void { x = bitcast(y); }",
|
EXPECT("fn f() -> void { x = bitcast(y); }",
|
||||||
"test.wgsl:1:29 error: missing < for bitcast expression\n"
|
"test.wgsl:1:29 error: expected '<' for bitcast expression\n"
|
||||||
"fn f() -> void { x = bitcast(y); }\n"
|
"fn f() -> void { x = bitcast(y); }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) {
|
TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) {
|
||||||
EXPECT("fn f() -> void { x = bitcast<u32(y); }",
|
EXPECT("fn f() -> void { x = bitcast<u32(y); }",
|
||||||
"test.wgsl:1:33 error: missing > for bitcast expression\n"
|
"test.wgsl:1:33 error: expected '>' for bitcast expression\n"
|
||||||
"fn f() -> void { x = bitcast<u32(y); }\n"
|
"fn f() -> void { x = bitcast<u32(y); }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ TEST_F(ParserImplErrorTest, FunctionDeclMissingRParen) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) {
|
TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) {
|
||||||
EXPECT("fn f() void {}",
|
EXPECT("fn f() void {}",
|
||||||
"test.wgsl:1:8 error: missing -> for function declaration\n"
|
"test.wgsl:1:8 error: expected '->' for function declaration\n"
|
||||||
"fn f() void {}\n"
|
"fn f() void {}\n"
|
||||||
" ^^^^\n");
|
" ^^^^\n");
|
||||||
}
|
}
|
||||||
|
@ -995,14 +995,14 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarInvalidIdentifier) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingLessThan) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingLessThan) {
|
||||||
EXPECT("var i : mat4x4;",
|
EXPECT("var i : mat4x4;",
|
||||||
"test.wgsl:1:15 error: missing < for matrix\n"
|
"test.wgsl:1:15 error: expected '<' for matrix\n"
|
||||||
"var i : mat4x4;\n"
|
"var i : mat4x4;\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) {
|
||||||
EXPECT("var i : mat4x4<u32;",
|
EXPECT("var i : mat4x4<u32;",
|
||||||
"test.wgsl:1:19 error: missing > for matrix\n"
|
"test.wgsl:1:19 error: expected '>' for matrix\n"
|
||||||
"var i : mat4x4<u32;\n"
|
"var i : mat4x4<u32;\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
|
TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
|
||||||
auto* p = parser("a ^ true");
|
auto* p = parser("a ^ true");
|
||||||
auto e = p->exclusive_or_expression();
|
auto e = p->exclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kXor, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kXor, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,24 +51,30 @@ TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
|
||||||
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} ^ true");
|
auto* p = parser("if (a) {} ^ true");
|
||||||
auto e = p->exclusive_or_expression();
|
auto e = p->exclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidRHS) {
|
||||||
auto* p = parser("true ^ if (a) {}");
|
auto* p = parser("true ^ if (a) {}");
|
||||||
auto e = p->exclusive_or_expression();
|
auto e = p->exclusive_or_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of ^ expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of ^ expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ExclusiveOrExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, ExclusiveOrExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->exclusive_or_expression();
|
auto e = p->exclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -161,8 +161,10 @@ class ForStmtErrorTest : public ParserImplTest {
|
||||||
auto* p_for = parser(for_str);
|
auto* p_for = parser(for_str);
|
||||||
auto e_for = p_for->for_stmt();
|
auto e_for = p_for->for_stmt();
|
||||||
|
|
||||||
ASSERT_TRUE(p_for->has_error());
|
EXPECT_FALSE(e_for.matched);
|
||||||
ASSERT_EQ(e_for, nullptr);
|
EXPECT_TRUE(e_for.errored);
|
||||||
|
EXPECT_TRUE(p_for->has_error());
|
||||||
|
ASSERT_EQ(e_for.value, nullptr);
|
||||||
EXPECT_EQ(p_for->error(), error_str);
|
EXPECT_EQ(p_for->error(), error_str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,56 +26,64 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl) {
|
TEST_F(ParserImplTest, FunctionDecl) {
|
||||||
auto* p = parser("fn main(a : i32, b : f32) -> void { return; }");
|
auto* p = parser("fn main(a : i32, b : f32) -> void { return; }");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_NE(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_FALSE(f.errored);
|
||||||
|
EXPECT_TRUE(f.matched);
|
||||||
|
ASSERT_NE(f.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(f->name(), "main");
|
EXPECT_EQ(f.value->name(), "main");
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
|
|
||||||
ASSERT_EQ(f->params().size(), 2u);
|
ASSERT_EQ(f.value->params().size(), 2u);
|
||||||
EXPECT_EQ(f->params()[0]->name(), "a");
|
EXPECT_EQ(f.value->params()[0]->name(), "a");
|
||||||
EXPECT_EQ(f->params()[1]->name(), "b");
|
EXPECT_EQ(f.value->params()[1]->name(), "b");
|
||||||
|
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f.value->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->IsReturn());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
|
TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
|
||||||
auto* p = parser("[[workgroup_size(2, 3, 4)]] fn main() -> void { return; }");
|
auto* p = parser("[[workgroup_size(2, 3, 4)]] fn main() -> void { return; }");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_TRUE(decos.matched);
|
||||||
ASSERT_NE(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_FALSE(f.errored);
|
||||||
|
EXPECT_TRUE(f.matched);
|
||||||
|
ASSERT_NE(f.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(f->name(), "main");
|
EXPECT_EQ(f.value->name(), "main");
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
ASSERT_EQ(f->params().size(), 0u);
|
ASSERT_EQ(f.value->params().size(), 0u);
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
|
|
||||||
auto& decos = f->decorations();
|
auto& decorations = f.value->decorations();
|
||||||
ASSERT_EQ(decos.size(), 1u);
|
ASSERT_EQ(decorations.size(), 1u);
|
||||||
ASSERT_TRUE(decos[0]->IsWorkgroup());
|
ASSERT_TRUE(decorations[0]->IsWorkgroup());
|
||||||
|
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
uint32_t y = 0;
|
uint32_t y = 0;
|
||||||
uint32_t z = 0;
|
uint32_t z = 0;
|
||||||
std::tie(x, y, z) = decos[0]->AsWorkgroup()->values();
|
std::tie(x, y, z) = decorations[0]->AsWorkgroup()->values();
|
||||||
EXPECT_EQ(x, 2u);
|
EXPECT_EQ(x, 2u);
|
||||||
EXPECT_EQ(y, 3u);
|
EXPECT_EQ(y, 3u);
|
||||||
EXPECT_EQ(z, 4u);
|
EXPECT_EQ(z, 4u);
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f.value->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->IsReturn());
|
||||||
}
|
}
|
||||||
|
@ -84,38 +92,42 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleEntries) {
|
||||||
auto* p = parser(R"(
|
auto* p = parser(R"(
|
||||||
[[workgroup_size(2, 3, 4), workgroup_size(5, 6, 7)]]
|
[[workgroup_size(2, 3, 4), workgroup_size(5, 6, 7)]]
|
||||||
fn main() -> void { return; })");
|
fn main() -> void { return; })");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_TRUE(decos.matched);
|
||||||
ASSERT_NE(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_FALSE(f.errored);
|
||||||
|
EXPECT_TRUE(f.matched);
|
||||||
|
ASSERT_NE(f.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(f->name(), "main");
|
EXPECT_EQ(f.value->name(), "main");
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
ASSERT_EQ(f->params().size(), 0u);
|
ASSERT_EQ(f.value->params().size(), 0u);
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
|
|
||||||
auto& decos = f->decorations();
|
auto& decorations = f.value->decorations();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
ASSERT_EQ(decorations.size(), 2u);
|
||||||
|
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
uint32_t y = 0;
|
uint32_t y = 0;
|
||||||
uint32_t z = 0;
|
uint32_t z = 0;
|
||||||
ASSERT_TRUE(decos[0]->IsWorkgroup());
|
ASSERT_TRUE(decorations[0]->IsWorkgroup());
|
||||||
std::tie(x, y, z) = decos[0]->AsWorkgroup()->values();
|
std::tie(x, y, z) = decorations[0]->AsWorkgroup()->values();
|
||||||
EXPECT_EQ(x, 2u);
|
EXPECT_EQ(x, 2u);
|
||||||
EXPECT_EQ(y, 3u);
|
EXPECT_EQ(y, 3u);
|
||||||
EXPECT_EQ(z, 4u);
|
EXPECT_EQ(z, 4u);
|
||||||
|
|
||||||
ASSERT_TRUE(decos[1]->IsWorkgroup());
|
ASSERT_TRUE(decorations[1]->IsWorkgroup());
|
||||||
std::tie(x, y, z) = decos[1]->AsWorkgroup()->values();
|
std::tie(x, y, z) = decorations[1]->AsWorkgroup()->values();
|
||||||
EXPECT_EQ(x, 5u);
|
EXPECT_EQ(x, 5u);
|
||||||
EXPECT_EQ(y, 6u);
|
EXPECT_EQ(y, 6u);
|
||||||
EXPECT_EQ(z, 7u);
|
EXPECT_EQ(z, 7u);
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f.value->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->IsReturn());
|
||||||
}
|
}
|
||||||
|
@ -126,19 +138,23 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleLists) {
|
||||||
[[workgroup_size(5, 6, 7)]]
|
[[workgroup_size(5, 6, 7)]]
|
||||||
fn main() -> void { return; })");
|
fn main() -> void { return; })");
|
||||||
auto decorations = p->decoration_list();
|
auto decorations = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decorations.errored);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_TRUE(decorations.matched);
|
||||||
ASSERT_NE(f, nullptr);
|
auto f = p->function_decl(decorations.value);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_FALSE(f.errored);
|
||||||
|
EXPECT_TRUE(f.matched);
|
||||||
|
ASSERT_NE(f.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(f->name(), "main");
|
EXPECT_EQ(f.value->name(), "main");
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
ASSERT_EQ(f->params().size(), 0u);
|
ASSERT_EQ(f.value->params().size(), 0u);
|
||||||
ASSERT_NE(f->return_type(), nullptr);
|
ASSERT_NE(f.value->return_type(), nullptr);
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
|
|
||||||
auto& decos = f->decorations();
|
auto& decos = f.value->decorations();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
ASSERT_EQ(decos.size(), 2u);
|
||||||
|
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
|
@ -156,38 +172,50 @@ fn main() -> void { return; })");
|
||||||
EXPECT_EQ(y, 6u);
|
EXPECT_EQ(y, 6u);
|
||||||
EXPECT_EQ(z, 7u);
|
EXPECT_EQ(z, 7u);
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f.value->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->IsReturn());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
|
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
|
||||||
auto* p = parser("fn main() -> { }");
|
auto* p = parser("fn main() -> { }");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_FALSE(f.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
|
EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_InvalidBody) {
|
TEST_F(ParserImplTest, FunctionDecl_InvalidBody) {
|
||||||
auto* p = parser("fn main() -> void { return }");
|
auto* p = parser("fn main() -> void { return }");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_FALSE(f.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:28: expected ';' for return statement");
|
EXPECT_EQ(p->error(), "1:28: expected ';' for return statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
|
TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
|
||||||
auto* p = parser("fn main() -> void return; }");
|
auto* p = parser("fn main() -> void return; }");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto f = p->function_decl(decorations);
|
ASSERT_FALSE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
auto f = p->function_decl(decos.value);
|
||||||
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_FALSE(f.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:19: expected '{'");
|
EXPECT_EQ(p->error(), "1:19: expected '{'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_Parses) {
|
TEST_F(ParserImplTest, FunctionDecorationList_Parses) {
|
||||||
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)]]");
|
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_TRUE(decos.matched);
|
||||||
|
ASSERT_EQ(decos.value.size(), 2u);
|
||||||
|
|
||||||
auto deco_0 = ast::As<ast::FunctionDecoration>(std::move(decos[0]));
|
auto deco_0 = ast::As<ast::FunctionDecoration>(std::move(decos.value[0]));
|
||||||
auto deco_1 = ast::As<ast::FunctionDecoration>(std::move(decos[1]));
|
auto deco_1 = ast::As<ast::FunctionDecoration>(std::move(decos.value[1]));
|
||||||
ASSERT_NE(deco_0, nullptr);
|
ASSERT_NE(deco_0, nullptr);
|
||||||
ASSERT_NE(deco_1, nullptr);
|
ASSERT_NE(deco_1, nullptr);
|
||||||
|
|
||||||
|
@ -49,47 +51,59 @@ TEST_F(ParserImplTest, FunctionDecorationList_Parses) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_Empty) {
|
TEST_F(ParserImplTest, FunctionDecorationList_Empty) {
|
||||||
auto* p = parser("[[]]");
|
auto* p = parser("[[]]");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:3: empty decoration list");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:3: empty decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_Invalid) {
|
TEST_F(ParserImplTest, FunctionDecorationList_Invalid) {
|
||||||
auto* p = parser("[[invalid]]");
|
auto* p = parser("[[invalid]]");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(decos.empty());
|
EXPECT_TRUE(decos.errored);
|
||||||
ASSERT_EQ(p->error(), "1:3: expected decoration");
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:3: expected decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_ExtraComma) {
|
TEST_F(ParserImplTest, FunctionDecorationList_ExtraComma) {
|
||||||
auto* p = parser("[[workgroup_size(2), ]]");
|
auto* p = parser("[[workgroup_size(2), ]]");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:22: expected decoration");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:22: expected decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_MissingComma) {
|
TEST_F(ParserImplTest, FunctionDecorationList_MissingComma) {
|
||||||
auto* p = parser("[[workgroup_size(2) workgroup_size(2)]]");
|
auto* p = parser("[[workgroup_size(2) workgroup_size(2)]]");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:21: expected ',' for decoration list");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:21: expected ',' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_BadDecoration) {
|
TEST_F(ParserImplTest, FunctionDecorationList_BadDecoration) {
|
||||||
auto* p = parser("[[workgroup_size()]]");
|
auto* p = parser("[[workgroup_size()]]");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:18: expected signed integer literal for workgroup_size x parameter");
|
"1:18: expected signed integer literal for workgroup_size x parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecorationList_MissingRightAttr) {
|
TEST_F(ParserImplTest, FunctionDecorationList_MissingRightAttr) {
|
||||||
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)");
|
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)");
|
||||||
ast::DecorationList decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:45: expected ']]' for decoration list");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:45: expected ']]' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -26,9 +26,11 @@ namespace {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup) {
|
||||||
auto* p = parser("workgroup_size(4)");
|
auto* p = parser("workgroup_size(4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr) << p->error();
|
EXPECT_TRUE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
|
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(func_deco, nullptr);
|
ASSERT_NE(func_deco, nullptr);
|
||||||
ASSERT_TRUE(func_deco->IsWorkgroup());
|
ASSERT_TRUE(func_deco->IsWorkgroup());
|
||||||
|
|
||||||
|
@ -44,9 +46,11 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_2Param) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_2Param) {
|
||||||
auto* p = parser("workgroup_size(4, 5)");
|
auto* p = parser("workgroup_size(4, 5)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr) << p->error();
|
EXPECT_TRUE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
|
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(func_deco, nullptr) << p->error();
|
ASSERT_NE(func_deco, nullptr) << p->error();
|
||||||
ASSERT_TRUE(func_deco->IsWorkgroup());
|
ASSERT_TRUE(func_deco->IsWorkgroup());
|
||||||
|
|
||||||
|
@ -62,9 +66,11 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_2Param) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_3Param) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_3Param) {
|
||||||
auto* p = parser("workgroup_size(4, 5, 6)");
|
auto* p = parser("workgroup_size(4, 5, 6)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr) << p->error();
|
EXPECT_TRUE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
|
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(func_deco, nullptr);
|
ASSERT_NE(func_deco, nullptr);
|
||||||
ASSERT_TRUE(func_deco->IsWorkgroup());
|
ASSERT_TRUE(func_deco->IsWorkgroup());
|
||||||
|
|
||||||
|
@ -80,16 +86,20 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_3Param) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_TooManyValues) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_TooManyValues) {
|
||||||
auto* p = parser("workgroup_size(1, 2, 3, 4)");
|
auto* p = parser("workgroup_size(1, 2, 3, 4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
|
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_X_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_X_Value) {
|
||||||
auto* p = parser("workgroup_size(-2, 5, 6)");
|
auto* p = parser("workgroup_size(-2, 5, 6)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:16: workgroup_size x parameter must be greater than 0");
|
"1:16: workgroup_size x parameter must be greater than 0");
|
||||||
}
|
}
|
||||||
|
@ -97,8 +107,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_X_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Y_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Y_Value) {
|
||||||
auto* p = parser("workgroup_size(4, 0, 6)");
|
auto* p = parser("workgroup_size(4, 0, 6)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:19: workgroup_size y parameter must be greater than 0");
|
"1:19: workgroup_size y parameter must be greater than 0");
|
||||||
}
|
}
|
||||||
|
@ -106,8 +118,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Y_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Z_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Z_Value) {
|
||||||
auto* p = parser("workgroup_size(4, 5, -3)");
|
auto* p = parser("workgroup_size(4, 5, -3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:22: workgroup_size z parameter must be greater than 0");
|
"1:22: workgroup_size z parameter must be greater than 0");
|
||||||
}
|
}
|
||||||
|
@ -115,24 +129,30 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Z_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingLeftParam) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingLeftParam) {
|
||||||
auto* p = parser("workgroup_size 4, 5, 6)");
|
auto* p = parser("workgroup_size 4, 5, 6)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: expected '(' for workgroup_size decoration");
|
EXPECT_EQ(p->error(), "1:16: expected '(' for workgroup_size decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingRightParam) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingRightParam) {
|
||||||
auto* p = parser("workgroup_size(4, 5, 6");
|
auto* p = parser("workgroup_size(4, 5, 6");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
|
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingValues) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingValues) {
|
||||||
auto* p = parser("workgroup_size()");
|
auto* p = parser("workgroup_size()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:16: expected signed integer literal for workgroup_size x parameter");
|
"1:16: expected signed integer literal for workgroup_size x parameter");
|
||||||
|
@ -141,8 +161,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingValues) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Value) {
|
||||||
auto* p = parser("workgroup_size(, 2, 3)");
|
auto* p = parser("workgroup_size(, 2, 3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:16: expected signed integer literal for workgroup_size x parameter");
|
"1:16: expected signed integer literal for workgroup_size x parameter");
|
||||||
|
@ -151,16 +173,20 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Comma) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Comma) {
|
||||||
auto* p = parser("workgroup_size(1 2, 3)");
|
auto* p = parser("workgroup_size(1 2, 3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:18: expected ')' for workgroup_size decoration");
|
EXPECT_EQ(p->error(), "1:18: expected ')' for workgroup_size decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Value) {
|
||||||
auto* p = parser("workgroup_size(1, , 3)");
|
auto* p = parser("workgroup_size(1, , 3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:19: expected signed integer literal for workgroup_size y parameter");
|
"1:19: expected signed integer literal for workgroup_size y parameter");
|
||||||
|
@ -169,16 +195,20 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Comma) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Comma) {
|
||||||
auto* p = parser("workgroup_size(1, 2 3)");
|
auto* p = parser("workgroup_size(1, 2 3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:21: expected ')' for workgroup_size decoration");
|
EXPECT_EQ(p->error(), "1:21: expected ')' for workgroup_size decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Value) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Value) {
|
||||||
auto* p = parser("workgroup_size(1, 2, )");
|
auto* p = parser("workgroup_size(1, 2, )");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:22: expected signed integer literal for workgroup_size z parameter");
|
"1:22: expected signed integer literal for workgroup_size z parameter");
|
||||||
|
@ -187,8 +217,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Value) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Invalid) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Invalid) {
|
||||||
auto* p = parser("workgroup_size(nan)");
|
auto* p = parser("workgroup_size(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:16: expected signed integer literal for workgroup_size x parameter");
|
"1:16: expected signed integer literal for workgroup_size x parameter");
|
||||||
|
@ -197,8 +229,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Invalid) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Invalid) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Invalid) {
|
||||||
auto* p = parser("workgroup_size(2, nan)");
|
auto* p = parser("workgroup_size(2, nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:19: expected signed integer literal for workgroup_size y parameter");
|
"1:19: expected signed integer literal for workgroup_size y parameter");
|
||||||
|
@ -207,8 +241,10 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Invalid) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Invalid) {
|
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Invalid) {
|
||||||
auto* p = parser("workgroup_size(2, 3, nan)");
|
auto* p = parser("workgroup_size(2, 3, nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
p->error(),
|
p->error(),
|
||||||
"1:22: expected signed integer literal for workgroup_size z parameter");
|
"1:22: expected signed integer literal for workgroup_size z parameter");
|
||||||
|
@ -217,9 +253,11 @@ TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Invalid) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Stage) {
|
TEST_F(ParserImplTest, FunctionDecoration_Stage) {
|
||||||
auto* p = parser("stage(compute)");
|
auto* p = parser("stage(compute)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr) << p->error();
|
EXPECT_TRUE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
|
auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(func_deco, nullptr);
|
ASSERT_NE(func_deco, nullptr);
|
||||||
ASSERT_TRUE(func_deco->IsStage());
|
ASSERT_TRUE(func_deco->IsStage());
|
||||||
EXPECT_EQ(func_deco->AsStage()->value(), ast::PipelineStage::kCompute);
|
EXPECT_EQ(func_deco->AsStage()->value(), ast::PipelineStage::kCompute);
|
||||||
|
@ -228,32 +266,40 @@ TEST_F(ParserImplTest, FunctionDecoration_Stage) {
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingValue) {
|
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingValue) {
|
||||||
auto* p = parser("stage()");
|
auto* p = parser("stage()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
|
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingInvalid) {
|
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingInvalid) {
|
||||||
auto* p = parser("stage(nan)");
|
auto* p = parser("stage(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
|
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingLeftParen) {
|
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingLeftParen) {
|
||||||
auto* p = parser("stage compute)");
|
auto* p = parser("stage compute)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected '(' for stage decoration");
|
EXPECT_EQ(p->error(), "1:7: expected '(' for stage decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingRightParen) {
|
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingRightParen) {
|
||||||
auto* p = parser("stage(compute");
|
auto* p = parser("stage(compute");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:14: expected ')' for stage decoration");
|
EXPECT_EQ(p->error(), "1:14: expected ')' for stage decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,76 +27,94 @@ TEST_F(ParserImplTest, FunctionHeader) {
|
||||||
auto* p = parser("fn main(a : i32, b: f32) -> void");
|
auto* p = parser("fn main(a : i32, b: f32) -> void");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(f, nullptr);
|
EXPECT_TRUE(f.matched);
|
||||||
|
EXPECT_FALSE(f.errored);
|
||||||
|
ASSERT_NE(f.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(f->name(), "main");
|
EXPECT_EQ(f.value->name(), "main");
|
||||||
ASSERT_EQ(f->params().size(), 2u);
|
ASSERT_EQ(f.value->params().size(), 2u);
|
||||||
EXPECT_EQ(f->params()[0]->name(), "a");
|
EXPECT_EQ(f.value->params()[0]->name(), "a");
|
||||||
EXPECT_EQ(f->params()[1]->name(), "b");
|
EXPECT_EQ(f.value->params()[1]->name(), "b");
|
||||||
EXPECT_TRUE(f->return_type()->IsVoid());
|
EXPECT_TRUE(f.value->return_type()->IsVoid());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
|
||||||
auto* p = parser("fn () ->");
|
auto* p = parser("fn () ->");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
|
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_InvalidIdent) {
|
TEST_F(ParserImplTest, FunctionHeader_InvalidIdent) {
|
||||||
auto* p = parser("fn 133main() -> i32");
|
auto* p = parser("fn 133main() -> i32");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
|
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingParenLeft) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingParenLeft) {
|
||||||
auto* p = parser("fn main) -> i32");
|
auto* p = parser("fn main) -> i32");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '(' for function declaration");
|
EXPECT_EQ(p->error(), "1:8: expected '(' for function declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
|
TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
|
||||||
auto* p = parser("fn main(a :i32,) -> i32");
|
auto* p = parser("fn main(a :i32,) -> i32");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:16: expected identifier for parameter");
|
EXPECT_EQ(p->error(), "1:16: expected identifier for parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
|
||||||
auto* p = parser("fn main( -> i32");
|
auto* p = parser("fn main( -> i32");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: expected ')' for function declaration");
|
EXPECT_EQ(p->error(), "1:10: expected ')' for function declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingArrow) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingArrow) {
|
||||||
auto* p = parser("fn main() i32");
|
auto* p = parser("fn main() i32");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
EXPECT_EQ(p->error(), "1:11: missing -> for function declaration");
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
|
EXPECT_EQ(p->error(), "1:11: expected '->' for function declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_InvalidReturnType) {
|
TEST_F(ParserImplTest, FunctionHeader_InvalidReturnType) {
|
||||||
auto* p = parser("fn main() -> invalid");
|
auto* p = parser("fn main() -> invalid");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:14: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingReturnType) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingReturnType) {
|
||||||
auto* p = parser("fn main() ->");
|
auto* p = parser("fn main() ->");
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(f.matched);
|
||||||
ASSERT_EQ(f, nullptr);
|
EXPECT_TRUE(f.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
|
EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,11 @@ TEST_F(ParserImplTest, FunctionTypeDecl_Void) {
|
||||||
auto* v = tm()->Get(std::make_unique<ast::type::VoidType>());
|
auto* v = tm()->Get(std::make_unique<ast::type::VoidType>());
|
||||||
|
|
||||||
auto* p = parser("void");
|
auto* p = parser("void");
|
||||||
auto* e = p->function_type_decl();
|
auto e = p->function_type_decl();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e, v);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
|
TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
|
||||||
|
@ -41,16 +43,20 @@ TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
|
||||||
auto* vec2 = tm()->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
auto* vec2 = tm()->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
||||||
|
|
||||||
auto* p = parser("vec2<f32>");
|
auto* p = parser("vec2<f32>");
|
||||||
auto* e = p->function_type_decl();
|
auto e = p->function_type_decl();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e, vec2);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value, vec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionTypeDecl_InvalidType) {
|
TEST_F(ParserImplTest, FunctionTypeDecl_InvalidType) {
|
||||||
auto* p = parser("vec2<invalid>");
|
auto* p = parser("vec2<invalid>");
|
||||||
auto* e = p->function_type_decl();
|
auto e = p->function_type_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:6: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,52 +26,62 @@ namespace {
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl) {
|
TEST_F(ParserImplTest, GlobalConstantDecl) {
|
||||||
auto* p = parser("const a : f32 = 1.");
|
auto* p = parser("const a : f32 = 1.");
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
EXPECT_TRUE(e->is_const());
|
EXPECT_TRUE(e.value->is_const());
|
||||||
EXPECT_EQ(e->name(), "a");
|
EXPECT_EQ(e.value->name(), "a");
|
||||||
ASSERT_NE(e->type(), nullptr);
|
ASSERT_NE(e.value->type(), nullptr);
|
||||||
EXPECT_TRUE(e->type()->IsF32());
|
EXPECT_TRUE(e.value->type()->IsF32());
|
||||||
|
|
||||||
EXPECT_EQ(e->source().range.begin.line, 1u);
|
EXPECT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.begin.column, 7u);
|
EXPECT_EQ(e.value->source().range.begin.column, 7u);
|
||||||
EXPECT_EQ(e->source().range.end.line, 1u);
|
EXPECT_EQ(e.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.end.column, 8u);
|
EXPECT_EQ(e.value->source().range.end.column, 8u);
|
||||||
|
|
||||||
ASSERT_NE(e->constructor(), nullptr);
|
ASSERT_NE(e.value->constructor(), nullptr);
|
||||||
EXPECT_TRUE(e->constructor()->IsConstructor());
|
EXPECT_TRUE(e.value->constructor()->IsConstructor());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
|
||||||
auto* p = parser("const a: f32 1.");
|
auto* p = parser("const a: f32 1.");
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: expected '=' for constant declaration");
|
EXPECT_EQ(p->error(), "1:14: expected '=' for constant declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
||||||
auto* p = parser("const a: invalid = 1.");
|
auto* p = parser("const a: invalid = 1.");
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
||||||
auto* p = parser("const a: f32 = if (a) {}");
|
auto* p = parser("const a: f32 = if (a) {}");
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:16: unable to parse const literal");
|
EXPECT_EQ(p->error(), "1:16: unable to parse const literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
||||||
auto* p = parser("const a: f32 =");
|
auto* p = parser("const a: f32 =");
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,130 +25,161 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
|
||||||
auto* p = parser("var<out> a : f32");
|
auto* p = parser("var<out> a : f32");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
auto e = p->global_variable_decl(decos.value);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(e->name(), "a");
|
EXPECT_EQ(e.value->name(), "a");
|
||||||
EXPECT_TRUE(e->type()->IsF32());
|
EXPECT_TRUE(e.value->type()->IsF32());
|
||||||
EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
|
EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
|
||||||
|
|
||||||
EXPECT_EQ(e->source().range.begin.line, 1u);
|
EXPECT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.begin.column, 10u);
|
EXPECT_EQ(e.value->source().range.begin.column, 10u);
|
||||||
EXPECT_EQ(e->source().range.end.line, 1u);
|
EXPECT_EQ(e.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.end.column, 11u);
|
EXPECT_EQ(e.value->source().range.end.column, 11u);
|
||||||
|
|
||||||
ASSERT_EQ(e->constructor(), nullptr);
|
ASSERT_EQ(e.value->constructor(), nullptr);
|
||||||
ASSERT_FALSE(e->IsDecorated());
|
ASSERT_FALSE(e.value->IsDecorated());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
|
||||||
auto* p = parser("var<out> a : f32 = 1.");
|
auto* p = parser("var<out> a : f32 = 1.");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
auto e = p->global_variable_decl(decos.value);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(e->name(), "a");
|
EXPECT_EQ(e.value->name(), "a");
|
||||||
EXPECT_TRUE(e->type()->IsF32());
|
EXPECT_TRUE(e.value->type()->IsF32());
|
||||||
EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
|
EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
|
||||||
|
|
||||||
EXPECT_EQ(e->source().range.begin.line, 1u);
|
EXPECT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.begin.column, 10u);
|
EXPECT_EQ(e.value->source().range.begin.column, 10u);
|
||||||
EXPECT_EQ(e->source().range.end.line, 1u);
|
EXPECT_EQ(e.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.end.column, 11u);
|
EXPECT_EQ(e.value->source().range.end.column, 11u);
|
||||||
|
|
||||||
ASSERT_NE(e->constructor(), nullptr);
|
ASSERT_NE(e.value->constructor(), nullptr);
|
||||||
ASSERT_TRUE(e->constructor()->IsConstructor());
|
ASSERT_TRUE(e.value->constructor()->IsConstructor());
|
||||||
ASSERT_TRUE(e->constructor()->AsConstructor()->IsScalarConstructor());
|
ASSERT_TRUE(e.value->constructor()->AsConstructor()->IsScalarConstructor());
|
||||||
|
|
||||||
ASSERT_FALSE(e->IsDecorated());
|
ASSERT_FALSE(e.value->IsDecorated());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
|
||||||
auto* p = parser("[[binding(2), set(1)]] var<out> a : f32");
|
auto* p = parser("[[binding(2), set(1)]] var<out> a : f32");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_TRUE(decos.matched);
|
||||||
|
auto e = p->global_variable_decl(decos.value);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsDecorated());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsDecorated());
|
||||||
|
|
||||||
EXPECT_EQ(e->name(), "a");
|
EXPECT_EQ(e.value->name(), "a");
|
||||||
ASSERT_NE(e->type(), nullptr);
|
ASSERT_NE(e.value->type(), nullptr);
|
||||||
EXPECT_TRUE(e->type()->IsF32());
|
EXPECT_TRUE(e.value->type()->IsF32());
|
||||||
EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
|
EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
|
||||||
|
|
||||||
EXPECT_EQ(e->source().range.begin.line, 1u);
|
EXPECT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.begin.column, 33u);
|
EXPECT_EQ(e.value->source().range.begin.column, 33u);
|
||||||
EXPECT_EQ(e->source().range.end.line, 1u);
|
EXPECT_EQ(e.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.end.column, 34u);
|
EXPECT_EQ(e.value->source().range.end.column, 34u);
|
||||||
|
|
||||||
ASSERT_EQ(e->constructor(), nullptr);
|
ASSERT_EQ(e.value->constructor(), nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsDecorated());
|
ASSERT_TRUE(e.value->IsDecorated());
|
||||||
auto* v = e->AsDecorated();
|
auto* v = e.value->AsDecorated();
|
||||||
|
|
||||||
auto& decos = v->decorations();
|
auto& decorations = v->decorations();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
ASSERT_EQ(decorations.size(), 2u);
|
||||||
ASSERT_TRUE(decos[0]->IsBinding());
|
ASSERT_TRUE(decorations[0]->IsBinding());
|
||||||
ASSERT_TRUE(decos[1]->IsSet());
|
ASSERT_TRUE(decorations[1]->IsSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration_MulitpleGroups) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration_MulitpleGroups) {
|
||||||
auto* p = parser("[[binding(2)]] [[set(1)]] var<out> a : f32");
|
auto* p = parser("[[binding(2)]] [[set(1)]] var<out> a : f32");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_TRUE(decos.matched);
|
||||||
|
|
||||||
|
auto e = p->global_variable_decl(decos.value);
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsDecorated());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsDecorated());
|
||||||
|
|
||||||
EXPECT_EQ(e->name(), "a");
|
EXPECT_EQ(e.value->name(), "a");
|
||||||
ASSERT_NE(e->type(), nullptr);
|
ASSERT_NE(e.value->type(), nullptr);
|
||||||
EXPECT_TRUE(e->type()->IsF32());
|
EXPECT_TRUE(e.value->type()->IsF32());
|
||||||
EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
|
EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
|
||||||
|
|
||||||
EXPECT_EQ(e->source().range.begin.line, 1u);
|
EXPECT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.begin.column, 36u);
|
EXPECT_EQ(e.value->source().range.begin.column, 36u);
|
||||||
EXPECT_EQ(e->source().range.end.line, 1u);
|
EXPECT_EQ(e.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(e->source().range.end.column, 37u);
|
EXPECT_EQ(e.value->source().range.end.column, 37u);
|
||||||
|
|
||||||
ASSERT_EQ(e->constructor(), nullptr);
|
ASSERT_EQ(e.value->constructor(), nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsDecorated());
|
ASSERT_TRUE(e.value->IsDecorated());
|
||||||
auto* v = e->AsDecorated();
|
auto* v = e.value->AsDecorated();
|
||||||
|
|
||||||
auto& decos = v->decorations();
|
auto& decorations = v->decorations();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
ASSERT_EQ(decorations.size(), 2u);
|
||||||
ASSERT_TRUE(decos[0]->IsBinding());
|
ASSERT_TRUE(decorations[0]->IsBinding());
|
||||||
ASSERT_TRUE(decos[1]->IsSet());
|
ASSERT_TRUE(decorations[1]->IsSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidDecoration) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidDecoration) {
|
||||||
auto* p = parser("[[binding()]] var<out> a : f32");
|
auto* p = parser("[[binding()]] var<out> a : f32");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_TRUE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
|
auto e = p->global_variable_decl(decos.value);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:11: expected signed integer literal for binding decoration");
|
"1:11: expected signed integer literal for binding decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
||||||
auto* p = parser("var<out> a : f32 = if (a) {}");
|
auto* p = parser("var<out> a : f32 = if (a) {}");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
auto e = p->global_variable_decl(decos.value);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:20: unable to parse const literal");
|
EXPECT_EQ(p->error(), "1:20: unable to parse const literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
||||||
auto* p = parser("var<invalid> a : f32;");
|
auto* p = parser("var<invalid> a : f32;");
|
||||||
auto decorations = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto e = p->global_variable_decl(decorations);
|
EXPECT_FALSE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
auto e = p->global_variable_decl(decos.value);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,82 +26,98 @@ namespace {
|
||||||
TEST_F(ParserImplTest, IfStmt) {
|
TEST_F(ParserImplTest, IfStmt) {
|
||||||
auto* p = parser("if (a == 4) { a = b; c = d; }");
|
auto* p = parser("if (a == 4) { a = b; c = d; }");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsIf());
|
ASSERT_TRUE(e.value->IsIf());
|
||||||
ASSERT_NE(e->condition(), nullptr);
|
ASSERT_NE(e.value->condition(), nullptr);
|
||||||
ASSERT_TRUE(e->condition()->IsBinary());
|
ASSERT_TRUE(e.value->condition()->IsBinary());
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
EXPECT_EQ(e.value->body()->size(), 2u);
|
||||||
EXPECT_EQ(e->else_statements().size(), 0u);
|
EXPECT_EQ(e.value->else_statements().size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_WithElse) {
|
TEST_F(ParserImplTest, IfStmt_WithElse) {
|
||||||
auto* p =
|
auto* p =
|
||||||
parser("if (a == 4) { a = b; c = d; } elseif(c) { d = 2; } else {}");
|
parser("if (a == 4) { a = b; c = d; } elseif(c) { d = 2; } else {}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsIf());
|
ASSERT_TRUE(e.value->IsIf());
|
||||||
ASSERT_NE(e->condition(), nullptr);
|
ASSERT_NE(e.value->condition(), nullptr);
|
||||||
ASSERT_TRUE(e->condition()->IsBinary());
|
ASSERT_TRUE(e.value->condition()->IsBinary());
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
EXPECT_EQ(e.value->body()->size(), 2u);
|
||||||
|
|
||||||
ASSERT_EQ(e->else_statements().size(), 2u);
|
ASSERT_EQ(e.value->else_statements().size(), 2u);
|
||||||
ASSERT_NE(e->else_statements()[0]->condition(), nullptr);
|
ASSERT_NE(e.value->else_statements()[0]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e->else_statements()[0]->condition()->IsIdentifier());
|
ASSERT_TRUE(e.value->else_statements()[0]->condition()->IsIdentifier());
|
||||||
EXPECT_EQ(e->else_statements()[0]->body()->size(), 1u);
|
EXPECT_EQ(e.value->else_statements()[0]->body()->size(), 1u);
|
||||||
|
|
||||||
ASSERT_EQ(e->else_statements()[1]->condition(), nullptr);
|
ASSERT_EQ(e.value->else_statements()[1]->condition(), nullptr);
|
||||||
EXPECT_EQ(e->else_statements()[1]->body()->size(), 0u);
|
EXPECT_EQ(e.value->else_statements()[1]->body()->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
||||||
auto* p = parser("if (a = 3) {}");
|
auto* p = parser("if (a = 3) {}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected ')'");
|
EXPECT_EQ(p->error(), "1:7: expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
|
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
|
||||||
auto* p = parser("if {}");
|
auto* p = parser("if {}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:4: expected '('");
|
EXPECT_EQ(p->error(), "1:4: expected '('");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidBody) {
|
TEST_F(ParserImplTest, IfStmt_InvalidBody) {
|
||||||
auto* p = parser("if (a) { fn main() -> void {}}");
|
auto* p = parser("if (a) { fn main() -> void {}}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '}'");
|
EXPECT_EQ(p->error(), "1:10: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
||||||
auto* p = parser("if (a)");
|
auto* p = parser("if (a)");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected '{'");
|
EXPECT_EQ(p->error(), "1:7: expected '{'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
||||||
auto* p = parser("if (a) {} elseif (a) { fn main() -> a{}}");
|
auto* p = parser("if (a) {} elseif (a) { fn main() -> a{}}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:24: expected '}'");
|
EXPECT_EQ(p->error(), "1:24: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
||||||
auto* p = parser("if (a) {} else { fn main() -> a{}}");
|
auto* p = parser("if (a) {} else { fn main() -> a{}}");
|
||||||
auto e = p->if_stmt();
|
auto e = p->if_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:18: expected '}'");
|
EXPECT_EQ(p->error(), "1:18: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
|
TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
|
||||||
auto* p = parser("a | true");
|
auto* p = parser("a | true");
|
||||||
auto e = p->inclusive_or_expression();
|
auto e = p->inclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kOr, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kOr, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,24 +51,30 @@ TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
|
||||||
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} | true");
|
auto* p = parser("if (a) {} | true");
|
||||||
auto e = p->inclusive_or_expression();
|
auto e = p->inclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidRHS) {
|
||||||
auto* p = parser("true | if (a) {}");
|
auto* p = parser("true | if (a) {}");
|
||||||
auto e = p->inclusive_or_expression();
|
auto e = p->inclusive_or_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of | expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of | expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, InclusiveOrExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, InclusiveOrExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->inclusive_or_expression();
|
auto e = p->inclusive_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
|
TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
|
||||||
auto* p = parser("a && true");
|
auto* p = parser("a && true");
|
||||||
auto e = p->logical_and_expression();
|
auto e = p->logical_and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,24 +51,30 @@ TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
|
||||||
TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} && true");
|
auto* p = parser("if (a) {} && true");
|
||||||
auto e = p->logical_and_expression();
|
auto e = p->logical_and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LogicalAndExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, LogicalAndExpression_InvalidRHS) {
|
||||||
auto* p = parser("true && if (a) {}");
|
auto* p = parser("true && if (a) {}");
|
||||||
auto e = p->logical_and_expression();
|
auto e = p->logical_and_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of && expression");
|
EXPECT_EQ(p->error(), "1:9: unable to parse right side of && expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LogicalAndExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, LogicalAndExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->logical_and_expression();
|
auto e = p->logical_and_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
|
TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
|
||||||
auto* p = parser("a || true");
|
auto* p = parser("a || true");
|
||||||
auto e = p->logical_or_expression();
|
auto e = p->logical_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,24 +51,30 @@ TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
|
||||||
TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} || true");
|
auto* p = parser("if (a) {} || true");
|
||||||
auto e = p->logical_or_expression();
|
auto e = p->logical_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LogicalOrExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, LogicalOrExpression_InvalidRHS) {
|
||||||
auto* p = parser("true || if (a) {}");
|
auto* p = parser("true || if (a) {}");
|
||||||
auto e = p->logical_or_expression();
|
auto e = p->logical_or_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of || expression");
|
EXPECT_EQ(p->error(), "1:9: unable to parse right side of || expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LogicalOrExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, LogicalOrExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->logical_or_expression();
|
auto e = p->logical_or_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,76 +24,92 @@ namespace {
|
||||||
TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
||||||
auto* p = parser("loop { discard; }");
|
auto* p = parser("loop { discard; }");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e.value->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsDiscard());
|
EXPECT_TRUE(e.value->body()->get(0)->IsDiscard());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing()->size(), 0u);
|
EXPECT_EQ(e.value->continuing()->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
||||||
auto* p = parser("loop { discard; continuing { discard; }}");
|
auto* p = parser("loop { discard; continuing { discard; }}");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e.value->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsDiscard());
|
EXPECT_TRUE(e.value->body()->get(0)->IsDiscard());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing()->size(), 1u);
|
EXPECT_EQ(e.value->continuing()->size(), 1u);
|
||||||
EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
|
EXPECT_TRUE(e.value->continuing()->get(0)->IsDiscard());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
||||||
auto* p = parser("loop { }");
|
auto* p = parser("loop { }");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->body()->size(), 0u);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->continuing()->size(), 0u);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_EQ(e.value->body()->size(), 0u);
|
||||||
|
ASSERT_EQ(e.value->continuing()->size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
||||||
auto* p = parser("loop { continuing { discard; }}");
|
auto* p = parser("loop { continuing { discard; }}");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->body()->size(), 0u);
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->continuing()->size(), 1u);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
|
ASSERT_EQ(e.value->body()->size(), 0u);
|
||||||
|
ASSERT_EQ(e.value->continuing()->size(), 1u);
|
||||||
|
EXPECT_TRUE(e.value->continuing()->get(0)->IsDiscard());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
|
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
|
||||||
auto* p = parser("loop discard; }");
|
auto* p = parser("loop discard; }");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
|
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_MissingBracketRight) {
|
TEST_F(ParserImplTest, LoopStmt_MissingBracketRight) {
|
||||||
auto* p = parser("loop { discard; ");
|
auto* p = parser("loop { discard; ");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:17: expected '}' for loop");
|
EXPECT_EQ(p->error(), "1:17: expected '}' for loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_InvalidStatements) {
|
TEST_F(ParserImplTest, LoopStmt_InvalidStatements) {
|
||||||
auto* p = parser("loop { discard }");
|
auto* p = parser("loop { discard }");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: expected ';' for discard statement");
|
EXPECT_EQ(p->error(), "1:16: expected ';' for discard statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_InvalidContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_InvalidContinuing) {
|
||||||
auto* p = parser("loop { continuing { discard }}");
|
auto* p = parser("loop { continuing { discard }}");
|
||||||
auto e = p->loop_stmt();
|
auto e = p->loop_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:29: expected ';' for discard statement");
|
EXPECT_EQ(p->error(), "1:29: expected ';' for discard statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
||||||
auto* p = parser("a * true");
|
auto* p = parser("a * true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,11 +51,13 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
||||||
auto* p = parser("a / true");
|
auto* p = parser("a / true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kDivide, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kDivide, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -70,11 +74,13 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
||||||
auto* p = parser("a % true");
|
auto* p = parser("a % true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kModulo, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kModulo, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -91,24 +97,30 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} * true");
|
auto* p = parser("if (a) {} * true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
||||||
auto* p = parser("true * if (a) {}");
|
auto* p = parser("true * if (a) {}");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of * expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of * expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -31,11 +31,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
|
TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
|
||||||
auto* p = parser("a[1]");
|
auto* p = parser("a[1]");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsArrayAccessor());
|
ASSERT_TRUE(e.value->IsArrayAccessor());
|
||||||
auto* ary = e->AsArrayAccessor();
|
auto* ary = e.value->AsArrayAccessor();
|
||||||
|
|
||||||
ASSERT_TRUE(ary->array()->IsIdentifier());
|
ASSERT_TRUE(ary->array()->IsIdentifier());
|
||||||
auto* ident = ary->array()->AsIdentifier();
|
auto* ident = ary->array()->AsIdentifier();
|
||||||
|
@ -51,11 +53,13 @@ TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
|
TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
|
||||||
auto* p = parser("a[1 + b / 4]");
|
auto* p = parser("a[1 + b / 4]");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsArrayAccessor());
|
ASSERT_TRUE(e.value->IsArrayAccessor());
|
||||||
auto* ary = e->AsArrayAccessor();
|
auto* ary = e.value->AsArrayAccessor();
|
||||||
|
|
||||||
ASSERT_TRUE(ary->array()->IsIdentifier());
|
ASSERT_TRUE(ary->array()->IsIdentifier());
|
||||||
auto* ident = ary->array()->AsIdentifier();
|
auto* ident = ary->array()->AsIdentifier();
|
||||||
|
@ -67,35 +71,43 @@ TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Array_MissingIndex) {
|
TEST_F(ParserImplTest, PostfixExpression_Array_MissingIndex) {
|
||||||
auto* p = parser("a[]");
|
auto* p = parser("a[]");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Array_MissingRightBrace) {
|
TEST_F(ParserImplTest, PostfixExpression_Array_MissingRightBrace) {
|
||||||
auto* p = parser("a[1");
|
auto* p = parser("a[1");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:4: missing ] for array accessor");
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), "1:4: expected ']' for array accessor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Array_InvalidIndex) {
|
TEST_F(ParserImplTest, PostfixExpression_Array_InvalidIndex) {
|
||||||
auto* p = parser("a[if(a() {})]");
|
auto* p = parser("a[if(a() {})]");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
|
TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
|
||||||
auto* p = parser("a()");
|
auto* p = parser("a()");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e.value->IsCall());
|
||||||
auto* c = e->AsCall();
|
auto* c = e.value->AsCall();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
@ -107,11 +119,13 @@ TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
|
TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
|
||||||
auto* p = parser("test(1, b, 2 + 3 / b)");
|
auto* p = parser("test(1, b, 2 + 3 / b)");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e.value->IsCall());
|
||||||
auto* c = e->AsCall();
|
auto* c = e.value->AsCall();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
@ -126,35 +140,43 @@ TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Call_InvalidArg) {
|
TEST_F(ParserImplTest, PostfixExpression_Call_InvalidArg) {
|
||||||
auto* p = parser("a(if(a) {})");
|
auto* p = parser("a(if(a) {})");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: unable to parse argument expression");
|
EXPECT_EQ(p->error(), "1:3: unable to parse argument expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Call_HangingComma) {
|
TEST_F(ParserImplTest, PostfixExpression_Call_HangingComma) {
|
||||||
auto* p = parser("a(b, )");
|
auto* p = parser("a(b, )");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: unable to parse argument expression after comma");
|
EXPECT_EQ(p->error(), "1:6: unable to parse argument expression after comma");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_Call_MissingRightParen) {
|
TEST_F(ParserImplTest, PostfixExpression_Call_MissingRightParen) {
|
||||||
auto* p = parser("a(");
|
auto* p = parser("a(");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: expected ')' for call expression");
|
EXPECT_EQ(p->error(), "1:3: expected ')' for call expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
|
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
|
||||||
auto* p = parser("a.b");
|
auto* p = parser("a.b");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsMemberAccessor());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsMemberAccessor());
|
||||||
|
|
||||||
auto* m = e->AsMemberAccessor();
|
auto* m = e.value->AsMemberAccessor();
|
||||||
ASSERT_TRUE(m->structure()->IsIdentifier());
|
ASSERT_TRUE(m->structure()->IsIdentifier());
|
||||||
EXPECT_EQ(m->structure()->AsIdentifier()->name(), "a");
|
EXPECT_EQ(m->structure()->AsIdentifier()->name(), "a");
|
||||||
|
|
||||||
|
@ -165,25 +187,31 @@ TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
|
||||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
|
TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
|
||||||
auto* p = parser("a.if");
|
auto* p = parser("a.if");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
|
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor_MissingIdent) {
|
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor_MissingIdent) {
|
||||||
auto* p = parser("a.");
|
auto* p = parser("a.");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
|
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PostfixExpression_NonMatch_returnLHS) {
|
TEST_F(ParserImplTest, PostfixExpression_NonMatch_returnLHS) {
|
||||||
auto* p = parser("a b");
|
auto* p = parser("a b");
|
||||||
auto e = p->postfix_expression();
|
auto e = p->postfix_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -35,21 +35,25 @@ namespace {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Ident) {
|
TEST_F(ParserImplTest, PrimaryExpression_Ident) {
|
||||||
auto* p = parser("a");
|
auto* p = parser("a");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
auto* ident = e->AsIdentifier();
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
|
auto* ident = e.value->AsIdentifier();
|
||||||
EXPECT_EQ(ident->name(), "a");
|
EXPECT_EQ(ident->name(), "a");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
||||||
auto* p = parser("vec4<i32>(1, 2, 3, 4))");
|
auto* p = parser("vec4<i32>(1, 2, 3, 4))");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
ASSERT_NE(e.value, nullptr);
|
||||||
auto* ty = e->AsConstructor()->AsTypeConstructor();
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
|
ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
|
||||||
|
auto* ty = e.value->AsConstructor()->AsTypeConstructor();
|
||||||
|
|
||||||
ASSERT_EQ(ty->values().size(), 4u);
|
ASSERT_EQ(ty->values().size(), 4u);
|
||||||
const auto& val = ty->values();
|
const auto& val = ty->values();
|
||||||
|
@ -81,11 +85,13 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
|
||||||
auto* p = parser("vec4<i32>()");
|
auto* p = parser("vec4<i32>()");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
ASSERT_NE(e.value, nullptr);
|
||||||
auto* ty = e->AsConstructor()->AsTypeConstructor();
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
|
ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
|
||||||
|
auto* ty = e.value->AsConstructor()->AsTypeConstructor();
|
||||||
|
|
||||||
ASSERT_EQ(ty->values().size(), 0u);
|
ASSERT_EQ(ty->values().size(), 0u);
|
||||||
}
|
}
|
||||||
|
@ -93,43 +99,53 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
||||||
auto* p = parser("vec4<if>(2., 3., 4., 5.)");
|
auto* p = parser("vec4<if>(2., 3., 4., 5.)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
EXPECT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingLeftParen) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingLeftParen) {
|
||||||
auto* p = parser("vec4<f32> 2., 3., 4., 5.)");
|
auto* p = parser("vec4<f32> 2., 3., 4., 5.)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
|
EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingRightParen) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingRightParen) {
|
||||||
auto* p = parser("vec4<f32>(2., 3., 4., 5.");
|
auto* p = parser("vec4<f32>(2., 3., 4., 5.");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:25: expected ')' for type constructor");
|
EXPECT_EQ(p->error(), "1:25: expected ')' for type constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidValue) {
|
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidValue) {
|
||||||
auto* p = parser("i32(if(a) {})");
|
auto* p = parser("i32(if(a) {})");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:5: unable to parse argument expression");
|
EXPECT_EQ(p->error(), "1:5: unable to parse argument expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
|
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
|
||||||
auto* p = parser("true");
|
auto* p = parser("true");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsScalarConstructor());
|
ASSERT_NE(e.value, nullptr);
|
||||||
auto* init = e->AsConstructor()->AsScalarConstructor();
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
|
ASSERT_TRUE(e.value->AsConstructor()->IsScalarConstructor());
|
||||||
|
auto* init = e.value->AsConstructor()->AsScalarConstructor();
|
||||||
ASSERT_TRUE(init->literal()->IsBool());
|
ASSERT_TRUE(init->literal()->IsBool());
|
||||||
EXPECT_TRUE(init->literal()->AsBool()->IsTrue());
|
EXPECT_TRUE(init->literal()->AsBool()->IsTrue());
|
||||||
}
|
}
|
||||||
|
@ -137,32 +153,40 @@ TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
|
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
|
||||||
auto* p = parser("(a == b)");
|
auto* p = parser("(a == b)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsBinary());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingRightParen) {
|
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingRightParen) {
|
||||||
auto* p = parser("(a == b");
|
auto* p = parser("(a == b");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ')'");
|
EXPECT_EQ(p->error(), "1:8: expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingExpr) {
|
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingExpr) {
|
||||||
auto* p = parser("()");
|
auto* p = parser("()");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
|
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
|
||||||
auto* p = parser("(if (a) {})");
|
auto* p = parser("(if (a) {})");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +195,14 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
||||||
|
|
||||||
auto* p = parser("f32(1)");
|
auto* p = parser("f32(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsConstructor());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsConstructor());
|
||||||
|
ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
|
||||||
|
|
||||||
auto* c = e->AsConstructor()->AsTypeConstructor();
|
auto* c = e.value->AsConstructor()->AsTypeConstructor();
|
||||||
ASSERT_EQ(c->type(), f32_type);
|
ASSERT_EQ(c->type(), f32_type);
|
||||||
ASSERT_EQ(c->values().size(), 1u);
|
ASSERT_EQ(c->values().size(), 1u);
|
||||||
|
|
||||||
|
@ -189,11 +215,13 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
|
||||||
|
|
||||||
auto* p = parser("bitcast<f32>(1)");
|
auto* p = parser("bitcast<f32>(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsBitcast());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsBitcast());
|
||||||
|
|
||||||
auto* c = e->AsBitcast();
|
auto* c = e.value->AsBitcast();
|
||||||
ASSERT_EQ(c->type(), f32_type);
|
ASSERT_EQ(c->type(), f32_type);
|
||||||
|
|
||||||
ASSERT_TRUE(c->expr()->IsConstructor());
|
ASSERT_TRUE(c->expr()->IsConstructor());
|
||||||
|
@ -203,56 +231,70 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) {
|
||||||
auto* p = parser("bitcast<f32(1)");
|
auto* p = parser("bitcast<f32(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_EQ(p->error(), "1:12: expected '>' for bitcast expression");
|
||||||
EXPECT_EQ(p->error(), "1:12: missing > for bitcast expression");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingType) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingType) {
|
||||||
auto* p = parser("bitcast<>(1)");
|
auto* p = parser("bitcast<>(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:9: missing type for bitcast expression");
|
EXPECT_EQ(p->error(), "1:9: missing type for bitcast expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_InvalidType) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_InvalidType) {
|
||||||
auto* p = parser("bitcast<invalid>(1)");
|
auto* p = parser("bitcast<invalid>(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingLeftParen) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingLeftParen) {
|
||||||
auto* p = parser("bitcast<f32>1)");
|
auto* p = parser("bitcast<f32>1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:13: expected '('");
|
EXPECT_EQ(p->error(), "1:13: expected '('");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingRightParen) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingRightParen) {
|
||||||
auto* p = parser("bitcast<f32>(1");
|
auto* p = parser("bitcast<f32>(1");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:15: expected ')'");
|
EXPECT_EQ(p->error(), "1:15: expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingExpression) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingExpression) {
|
||||||
auto* p = parser("bitcast<f32>()");
|
auto* p = parser("bitcast<f32>()");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_bitcast_InvalidExpression) {
|
TEST_F(ParserImplTest, PrimaryExpression_bitcast_InvalidExpression) {
|
||||||
auto* p = parser("bitcast<f32>(if (a) {})");
|
auto* p = parser("bitcast<f32>(if (a) {})");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
|
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
|
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
|
||||||
auto* p = parser("a < true");
|
auto* p = parser("a < true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,11 +51,13 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
|
||||||
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
|
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
|
||||||
auto* p = parser("a > true");
|
auto* p = parser("a > true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -70,11 +74,13 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
|
||||||
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
|
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
|
||||||
auto* p = parser("a <= true");
|
auto* p = parser("a <= true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -91,11 +97,13 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
|
||||||
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
|
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
|
||||||
auto* p = parser("a >= true");
|
auto* p = parser("a >= true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -112,24 +120,28 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
|
||||||
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} < true");
|
auto* p = parser("if (a) {} < true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, RelationalExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, RelationalExpression_InvalidRHS) {
|
||||||
auto* p = parser("true < if (a) {}");
|
auto* p = parser("true < if (a) {}");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of < expression");
|
EXPECT_EQ(p->error(), "1:8: unable to parse right side of < expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, RelationalExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, RelationalExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->relational_expression();
|
auto e = p->relational_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,105 +25,134 @@ namespace {
|
||||||
TEST_F(ParserImplTest, SampledTextureType_Invalid) {
|
TEST_F(ParserImplTest, SampledTextureType_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::kNone);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_1d_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_1d_Old) {
|
||||||
auto* p = parser("texture_sampled_1d");
|
auto* p = parser("texture_sampled_1d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k1d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_1dArray_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_1dArray_Old) {
|
||||||
auto* p = parser("texture_sampled_1d_array");
|
auto* p = parser("texture_sampled_1d_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k1dArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_2d_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_2d_Old) {
|
||||||
auto* p = parser("texture_sampled_2d");
|
auto* p = parser("texture_sampled_2d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k2d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_2dArray_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_2dArray_Old) {
|
||||||
auto* p = parser("texture_sampled_2d_array");
|
auto* p = parser("texture_sampled_2d_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k2dArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_3d_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_3d_Old) {
|
||||||
auto* p = parser("texture_sampled_3d");
|
auto* p = parser("texture_sampled_3d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k3d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_Cube_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_Cube_Old) {
|
||||||
auto* p = parser("texture_sampled_cube");
|
auto* p = parser("texture_sampled_cube");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::kCube);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::kCube);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_kCubeArray_Old) {
|
TEST_F(ParserImplTest, SampledTextureType_kCubeArray_Old) {
|
||||||
auto* p = parser("texture_sampled_cube_array");
|
auto* p = parser("texture_sampled_cube_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::kCubeArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::kCubeArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_1d) {
|
TEST_F(ParserImplTest, SampledTextureType_1d) {
|
||||||
auto* p = parser("texture_1d");
|
auto* p = parser("texture_1d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k1d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_1dArray) {
|
TEST_F(ParserImplTest, SampledTextureType_1dArray) {
|
||||||
auto* p = parser("texture_1d_array");
|
auto* p = parser("texture_1d_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k1dArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_2d) {
|
TEST_F(ParserImplTest, SampledTextureType_2d) {
|
||||||
auto* p = parser("texture_2d");
|
auto* p = parser("texture_2d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k2d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_2dArray) {
|
TEST_F(ParserImplTest, SampledTextureType_2dArray) {
|
||||||
auto* p = parser("texture_2d_array");
|
auto* p = parser("texture_2d_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k2dArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_3d) {
|
TEST_F(ParserImplTest, SampledTextureType_3d) {
|
||||||
auto* p = parser("texture_3d");
|
auto* p = parser("texture_3d");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::k3d);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_Cube) {
|
TEST_F(ParserImplTest, SampledTextureType_Cube) {
|
||||||
auto* p = parser("texture_cube");
|
auto* p = parser("texture_cube");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::kCube);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::kCube);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SampledTextureType_kCubeArray) {
|
TEST_F(ParserImplTest, SampledTextureType_kCubeArray) {
|
||||||
auto* p = parser("texture_cube_array");
|
auto* p = parser("texture_cube_array");
|
||||||
auto t = p->sampled_texture_type();
|
auto t = p->sampled_texture_type();
|
||||||
EXPECT_EQ(t, ast::type::TextureDimension::kCubeArray);
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, ast::type::TextureDimension::kCubeArray);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,26 +24,32 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SamplerType_Invalid) {
|
TEST_F(ParserImplTest, SamplerType_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto* t = p->sampler_type();
|
auto t = p->sampler_type();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SamplerType_Sampler) {
|
TEST_F(ParserImplTest, SamplerType_Sampler) {
|
||||||
auto* p = parser("sampler");
|
auto* p = parser("sampler");
|
||||||
auto* t = p->sampler_type();
|
auto t = p->sampler_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsSampler());
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_FALSE(t->AsSampler()->IsComparison());
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsSampler());
|
||||||
|
EXPECT_FALSE(t.value->AsSampler()->IsComparison());
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SamplerType_ComparisonSampler) {
|
TEST_F(ParserImplTest, SamplerType_ComparisonSampler) {
|
||||||
auto* p = parser("sampler_comparison");
|
auto* p = parser("sampler_comparison");
|
||||||
auto* t = p->sampler_type();
|
auto t = p->sampler_type();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsSampler());
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_TRUE(t->AsSampler()->IsComparison());
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsSampler());
|
||||||
|
EXPECT_TRUE(t.value->AsSampler()->IsComparison());
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
|
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
|
||||||
auto* p = parser("a << true");
|
auto* p = parser("a << true");
|
||||||
auto e = p->shift_expression();
|
auto e = p->shift_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -49,11 +51,13 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
|
||||||
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
|
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
|
||||||
auto* p = parser("a >> true");
|
auto* p = parser("a >> true");
|
||||||
auto e = p->shift_expression();
|
auto e = p->shift_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsBinary());
|
ASSERT_TRUE(e.value->IsBinary());
|
||||||
auto* rel = e->AsBinary();
|
auto* rel = e.value->AsBinary();
|
||||||
EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op());
|
EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op());
|
||||||
|
|
||||||
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
ASSERT_TRUE(rel->lhs()->IsIdentifier());
|
||||||
|
@ -70,24 +74,30 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
|
||||||
TEST_F(ParserImplTest, ShiftExpression_InvalidLHS) {
|
TEST_F(ParserImplTest, ShiftExpression_InvalidLHS) {
|
||||||
auto* p = parser("if (a) {} << true");
|
auto* p = parser("if (a) {} << true");
|
||||||
auto e = p->shift_expression();
|
auto e = p->shift_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ShiftExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, ShiftExpression_InvalidRHS) {
|
||||||
auto* p = parser("true << if (a) {}");
|
auto* p = parser("true << if (a) {}");
|
||||||
auto e = p->shift_expression();
|
auto e = p->shift_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of << expression");
|
EXPECT_EQ(p->error(), "1:9: unable to parse right side of << expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ShiftExpression_NoOr_ReturnsLHS) {
|
TEST_F(ParserImplTest, ShiftExpression_NoOr_ReturnsLHS) {
|
||||||
auto* p = parser("a true");
|
auto* p = parser("a true");
|
||||||
auto e = p->shift_expression();
|
auto e = p->shift_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIdentifier());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -27,25 +27,25 @@ TEST_F(ParserImplTest, Statement) {
|
||||||
auto* p = parser("return;");
|
auto* p = parser("return;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_TRUE(e->IsReturn());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsReturn());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Semicolon) {
|
TEST_F(ParserImplTest, Statement_Semicolon) {
|
||||||
auto* p = parser(";");
|
auto* p = parser(";");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Return_NoValue) {
|
TEST_F(ParserImplTest, Statement_Return_NoValue) {
|
||||||
auto* p = parser("return;");
|
auto* p = parser("return;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsReturn());
|
ASSERT_TRUE(e.value->IsReturn());
|
||||||
auto* ret = e->AsReturn();
|
auto* ret = e.value->AsReturn();
|
||||||
ASSERT_EQ(ret->value(), nullptr);
|
ASSERT_EQ(ret->value(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +53,11 @@ TEST_F(ParserImplTest, Statement_Return_Value) {
|
||||||
auto* p = parser("return a + b * (.1 - .2);");
|
auto* p = parser("return a + b * (.1 - .2);");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsReturn());
|
EXPECT_TRUE(e.matched);
|
||||||
auto* ret = e->AsReturn();
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsReturn());
|
||||||
|
auto* ret = e.value->AsReturn();
|
||||||
ASSERT_NE(ret->value(), nullptr);
|
ASSERT_NE(ret->value(), nullptr);
|
||||||
EXPECT_TRUE(ret->value()->IsBinary());
|
EXPECT_TRUE(ret->value()->IsBinary());
|
||||||
}
|
}
|
||||||
|
@ -64,16 +65,20 @@ TEST_F(ParserImplTest, Statement_Return_Value) {
|
||||||
TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
|
TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
|
||||||
auto* p = parser("return");
|
auto* p = parser("return");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:7: expected ';' for return statement");
|
EXPECT_EQ(p->error(), "1:7: expected ';' for return statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Return_Invalid) {
|
TEST_F(ParserImplTest, Statement_Return_Invalid) {
|
||||||
auto* p = parser("return if(a) {};");
|
auto* p = parser("return if(a) {};");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ';' for return statement");
|
EXPECT_EQ(p->error(), "1:8: expected ';' for return statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,15 +86,18 @@ TEST_F(ParserImplTest, Statement_If) {
|
||||||
auto* p = parser("if (a) {}");
|
auto* p = parser("if (a) {}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsIf());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsIf());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_If_Invalid) {
|
TEST_F(ParserImplTest, Statement_If_Invalid) {
|
||||||
auto* p = parser("if (a) { fn main() -> {}}");
|
auto* p = parser("if (a) { fn main() -> {}}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '}'");
|
EXPECT_EQ(p->error(), "1:10: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,23 +105,28 @@ TEST_F(ParserImplTest, Statement_Variable) {
|
||||||
auto* p = parser("var a : i32 = 1;");
|
auto* p = parser("var a : i32 = 1;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsVariableDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
|
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
|
||||||
auto* p = parser("var a : i32 =;");
|
auto* p = parser("var a : i32 =;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: missing constructor for variable declaration");
|
EXPECT_EQ(p->error(), "1:14: missing constructor for variable declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Variable_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Variable_MissingSemicolon) {
|
||||||
auto* p = parser("var a : i32");
|
auto* p = parser("var a : i32");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:12: expected ';' for variable declaration");
|
EXPECT_EQ(p->error(), "1:12: expected ';' for variable declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,15 +134,18 @@ TEST_F(ParserImplTest, Statement_Switch) {
|
||||||
auto* p = parser("switch (a) {}");
|
auto* p = parser("switch (a) {}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsSwitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
|
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
|
||||||
auto* p = parser("switch (a) { case: {}}");
|
auto* p = parser("switch (a) { case: {}}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:18: unable to parse case selectors");
|
EXPECT_EQ(p->error(), "1:18: unable to parse case selectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,15 +153,18 @@ TEST_F(ParserImplTest, Statement_Loop) {
|
||||||
auto* p = parser("loop {}");
|
auto* p = parser("loop {}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsLoop());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
|
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
|
||||||
auto* p = parser("loop discard; }");
|
auto* p = parser("loop discard; }");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
|
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,23 +172,28 @@ TEST_F(ParserImplTest, Statement_Assignment) {
|
||||||
auto* p = parser("a = b;");
|
auto* p = parser("a = b;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_TRUE(e->IsAssign());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsAssign());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
|
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
|
||||||
auto* p = parser("a = if(b) {};");
|
auto* p = parser("a = if(b) {};");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:5: unable to parse right side of assignment");
|
EXPECT_EQ(p->error(), "1:5: unable to parse right side of assignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Assignment_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Assignment_MissingSemicolon) {
|
||||||
auto* p = parser("a = b");
|
auto* p = parser("a = b");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected ';' for assignment statement");
|
EXPECT_EQ(p->error(), "1:6: expected ';' for assignment statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,15 +201,18 @@ TEST_F(ParserImplTest, Statement_Break) {
|
||||||
auto* p = parser("break;");
|
auto* p = parser("break;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_TRUE(e->IsBreak());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsBreak());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
|
||||||
auto* p = parser("break");
|
auto* p = parser("break");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected ';' for break statement");
|
EXPECT_EQ(p->error(), "1:6: expected ';' for break statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,15 +220,18 @@ TEST_F(ParserImplTest, Statement_Continue) {
|
||||||
auto* p = parser("continue;");
|
auto* p = parser("continue;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_TRUE(e->IsContinue());
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsContinue());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
|
||||||
auto* p = parser("continue");
|
auto* p = parser("continue");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected ';' for continue statement");
|
EXPECT_EQ(p->error(), "1:9: expected ';' for continue statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,15 +239,19 @@ TEST_F(ParserImplTest, Statement_Discard) {
|
||||||
auto* p = parser("discard;");
|
auto* p = parser("discard;");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_NE(e, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsDiscard());
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
ASSERT_TRUE(e.value->IsDiscard());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
|
||||||
auto* p = parser("discard");
|
auto* p = parser("discard");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(e, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ';' for discard statement");
|
EXPECT_EQ(p->error(), "1:8: expected ';' for discard statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,16 +259,19 @@ TEST_F(ParserImplTest, Statement_Body) {
|
||||||
auto* p = parser("{ var i: i32; }");
|
auto* p = parser("{ var i: i32; }");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsBlock());
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e->AsBlock()->get(0)->IsVariableDecl());
|
ASSERT_TRUE(e.value->IsBlock());
|
||||||
|
EXPECT_TRUE(e.value->AsBlock()->get(0)->IsVariableDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
||||||
auto* p = parser("{ fn main() -> {}}");
|
auto* p = parser("{ fn main() -> {}}");
|
||||||
auto e = p->statement();
|
auto e = p->statement();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:3: expected '}'");
|
EXPECT_EQ(p->error(), "1:3: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,168 +25,208 @@ namespace {
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Invalid) {
|
TEST_F(ParserImplTest, StorageTextureType_Invalid) {
|
||||||
auto* p = parser("abc");
|
auto* p = parser("abc");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::kNone);
|
EXPECT_FALSE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Readonly1d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Readonly1d_Old) {
|
||||||
auto* p = parser("texture_ro_1d");
|
auto* p = parser("texture_ro_1d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Readonly1dArray_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Readonly1dArray_Old) {
|
||||||
auto* p = parser("texture_ro_1d_array");
|
auto* p = parser("texture_ro_1d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Readonly2d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Readonly2d_Old) {
|
||||||
auto* p = parser("texture_ro_2d");
|
auto* p = parser("texture_ro_2d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Readonly2dArray_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Readonly2dArray_Old) {
|
||||||
auto* p = parser("texture_ro_2d_array");
|
auto* p = parser("texture_ro_2d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Readonly3d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Readonly3d_Old) {
|
||||||
auto* p = parser("texture_ro_3d");
|
auto* p = parser("texture_ro_3d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Writeonly1d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Writeonly1d_Old) {
|
||||||
auto* p = parser("texture_wo_1d");
|
auto* p = parser("texture_wo_1d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Writeonly1dArray_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Writeonly1dArray_Old) {
|
||||||
auto* p = parser("texture_wo_1d_array");
|
auto* p = parser("texture_wo_1d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Writeonly2d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Writeonly2d_Old) {
|
||||||
auto* p = parser("texture_wo_2d");
|
auto* p = parser("texture_wo_2d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Writeonly2dArray_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Writeonly2dArray_Old) {
|
||||||
auto* p = parser("texture_wo_2d_array");
|
auto* p = parser("texture_wo_2d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_Writeonly3d_Old) {
|
TEST_F(ParserImplTest, StorageTextureType_Writeonly3d_Old) {
|
||||||
auto* p = parser("texture_wo_3d");
|
auto* p = parser("texture_wo_3d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_ro_1d) {
|
TEST_F(ParserImplTest, StorageTextureType_ro_1d) {
|
||||||
auto* p = parser("texture_storage_ro_1d");
|
auto* p = parser("texture_storage_ro_1d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_ro_1dArray) {
|
TEST_F(ParserImplTest, StorageTextureType_ro_1dArray) {
|
||||||
auto* p = parser("texture_storage_ro_1d_array");
|
auto* p = parser("texture_storage_ro_1d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_ro_2d) {
|
TEST_F(ParserImplTest, StorageTextureType_ro_2d) {
|
||||||
auto* p = parser("texture_storage_ro_2d");
|
auto* p = parser("texture_storage_ro_2d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_ro_2dArray) {
|
TEST_F(ParserImplTest, StorageTextureType_ro_2dArray) {
|
||||||
auto* p = parser("texture_storage_ro_2d_array");
|
auto* p = parser("texture_storage_ro_2d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_ro_3d) {
|
TEST_F(ParserImplTest, StorageTextureType_ro_3d) {
|
||||||
auto* p = parser("texture_storage_ro_3d");
|
auto* p = parser("texture_storage_ro_3d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_wo_1d) {
|
TEST_F(ParserImplTest, StorageTextureType_wo_1d) {
|
||||||
auto* p = parser("texture_storage_wo_1d");
|
auto* p = parser("texture_storage_wo_1d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_wo_1dArray) {
|
TEST_F(ParserImplTest, StorageTextureType_wo_1dArray) {
|
||||||
auto* p = parser("texture_storage_wo_1d_array");
|
auto* p = parser("texture_storage_wo_1d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_wo_2d) {
|
TEST_F(ParserImplTest, StorageTextureType_wo_2d) {
|
||||||
auto* p = parser("texture_storage_wo_2d");
|
auto* p = parser("texture_storage_wo_2d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_wo_2dArray) {
|
TEST_F(ParserImplTest, StorageTextureType_wo_2dArray) {
|
||||||
auto* p = parser("texture_storage_wo_2d_array");
|
auto* p = parser("texture_storage_wo_2d_array");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StorageTextureType_wo_3d) {
|
TEST_F(ParserImplTest, StorageTextureType_wo_3d) {
|
||||||
auto* p = parser("texture_storage_wo_3d");
|
auto* p = parser("texture_storage_wo_3d");
|
||||||
auto t = p->storage_texture_type();
|
auto t = p->storage_texture_type();
|
||||||
EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
|
EXPECT_FALSE(t.errored);
|
||||||
|
EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
|
||||||
|
EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -29,14 +29,19 @@ struct S {
|
||||||
[[offset(4)]] b : f32;
|
[[offset(4)]] b : f32;
|
||||||
})");
|
})");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 0u);
|
||||||
ASSERT_NE(s, nullptr);
|
|
||||||
ASSERT_EQ(s->name(), "S");
|
auto s = p->struct_decl(decos.value);
|
||||||
ASSERT_EQ(s->impl()->members().size(), 2u);
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
|
EXPECT_FALSE(s.errored);
|
||||||
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
|
EXPECT_TRUE(s.matched);
|
||||||
|
ASSERT_NE(s.value, nullptr);
|
||||||
|
ASSERT_EQ(s.value->name(), "S");
|
||||||
|
ASSERT_EQ(s.value->impl()->members().size(), 2u);
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
|
TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
|
||||||
|
@ -46,16 +51,21 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
|
||||||
b : f32;
|
b : f32;
|
||||||
})");
|
})");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 1u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_TRUE(decos.matched);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 1u);
|
||||||
ASSERT_NE(s, nullptr);
|
|
||||||
ASSERT_EQ(s->name(), "B");
|
auto s = p->struct_decl(decos.value);
|
||||||
ASSERT_EQ(s->impl()->members().size(), 2u);
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
|
EXPECT_FALSE(s.errored);
|
||||||
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
|
EXPECT_TRUE(s.matched);
|
||||||
ASSERT_EQ(s->impl()->decorations().size(), 1u);
|
ASSERT_NE(s.value, nullptr);
|
||||||
EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
|
ASSERT_EQ(s.value->name(), "B");
|
||||||
|
ASSERT_EQ(s.value->impl()->members().size(), 2u);
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
|
||||||
|
ASSERT_EQ(s.value->impl()->decorations().size(), 1u);
|
||||||
|
EXPECT_TRUE(s.value->impl()->decorations()[0]->IsBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
|
TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
|
||||||
|
@ -66,75 +76,115 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
|
||||||
b : f32;
|
b : f32;
|
||||||
})");
|
})");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_TRUE(decos.matched);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 2u);
|
||||||
ASSERT_NE(s, nullptr);
|
|
||||||
ASSERT_EQ(s->name(), "S");
|
auto s = p->struct_decl(decos.value);
|
||||||
ASSERT_EQ(s->impl()->members().size(), 2u);
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
|
EXPECT_FALSE(s.errored);
|
||||||
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
|
EXPECT_TRUE(s.matched);
|
||||||
ASSERT_EQ(s->impl()->decorations().size(), 2u);
|
ASSERT_NE(s.value, nullptr);
|
||||||
EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
|
ASSERT_EQ(s.value->name(), "S");
|
||||||
EXPECT_TRUE(s->impl()->decorations()[1]->IsBlock());
|
ASSERT_EQ(s.value->impl()->members().size(), 2u);
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
|
||||||
|
EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
|
||||||
|
ASSERT_EQ(s.value->impl()->decorations().size(), 2u);
|
||||||
|
EXPECT_TRUE(s.value->impl()->decorations()[0]->IsBlock());
|
||||||
|
EXPECT_TRUE(s.value->impl()->decorations()[1]->IsBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
|
TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
|
||||||
auto* p = parser("struct S {}");
|
auto* p = parser("struct S {}");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 0u);
|
||||||
ASSERT_NE(s, nullptr);
|
|
||||||
ASSERT_EQ(s->impl()->members().size(), 0u);
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_FALSE(p->has_error());
|
||||||
|
EXPECT_FALSE(s.errored);
|
||||||
|
EXPECT_TRUE(s.matched);
|
||||||
|
ASSERT_NE(s.value, nullptr);
|
||||||
|
ASSERT_EQ(s.value->impl()->members().size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_MissingIdent) {
|
TEST_F(ParserImplTest, StructDecl_MissingIdent) {
|
||||||
auto* p = parser("struct {}");
|
auto* p = parser("struct {}");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 0u);
|
||||||
ASSERT_EQ(s, nullptr);
|
|
||||||
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_TRUE(s.errored);
|
||||||
|
EXPECT_FALSE(s.matched);
|
||||||
|
EXPECT_EQ(s.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected identifier for struct declaration");
|
EXPECT_EQ(p->error(), "1:8: expected identifier for struct declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_MissingBracketLeft) {
|
TEST_F(ParserImplTest, StructDecl_MissingBracketLeft) {
|
||||||
auto* p = parser("struct S }");
|
auto* p = parser("struct S }");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 0u);
|
||||||
ASSERT_EQ(s, nullptr);
|
|
||||||
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_TRUE(s.errored);
|
||||||
|
EXPECT_FALSE(s.matched);
|
||||||
|
EXPECT_EQ(s.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '{' for struct declaration");
|
EXPECT_EQ(p->error(), "1:10: expected '{' for struct declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_InvalidStructBody) {
|
TEST_F(ParserImplTest, StructDecl_InvalidStructBody) {
|
||||||
auto* p = parser("struct S { a : B; }");
|
auto* p = parser("struct S { a : B; }");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 0u);
|
||||||
ASSERT_EQ(s, nullptr);
|
|
||||||
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_TRUE(s.errored);
|
||||||
|
EXPECT_FALSE(s.matched);
|
||||||
|
EXPECT_EQ(s.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: unknown constructed type 'B'");
|
EXPECT_EQ(p->error(), "1:16: unknown constructed type 'B'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_InvalidStructDecorationDecl) {
|
TEST_F(ParserImplTest, StructDecl_InvalidStructDecorationDecl) {
|
||||||
auto* p = parser("[[block struct S { a : i32; }");
|
auto* p = parser("[[block struct S { a : i32; }");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_TRUE(decos.errored);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(decos.matched);
|
||||||
ASSERT_EQ(s, nullptr);
|
|
||||||
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_FALSE(s.errored);
|
||||||
|
EXPECT_FALSE(s.matched);
|
||||||
|
EXPECT_EQ(s.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected ']]' for decoration list");
|
EXPECT_EQ(p->error(), "1:9: expected ']]' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecl_MissingStruct) {
|
TEST_F(ParserImplTest, StructDecl_MissingStruct) {
|
||||||
auto* p = parser("[[block]] S {}");
|
auto* p = parser("[[block]] S {}");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_EQ(decos.size(), 1u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto s = p->struct_decl(decos);
|
EXPECT_TRUE(decos.matched);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_EQ(decos.value.size(), 1u);
|
||||||
ASSERT_EQ(s, nullptr);
|
|
||||||
|
auto s = p->struct_decl(decos.value);
|
||||||
|
EXPECT_FALSE(s.errored);
|
||||||
|
EXPECT_FALSE(s.matched);
|
||||||
|
EXPECT_EQ(s.value, nullptr);
|
||||||
|
|
||||||
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,25 +24,31 @@ namespace {
|
||||||
TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
|
TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
|
||||||
auto* p = parser("[[block]]");
|
auto* p = parser("[[block]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(decos.size(), 1u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto struct_deco = ast::As<ast::StructDecoration>(std::move(decos[0]));
|
EXPECT_TRUE(decos.matched);
|
||||||
|
ASSERT_EQ(decos.value.size(), 1u);
|
||||||
|
auto struct_deco = ast::As<ast::StructDecoration>(std::move(decos.value[0]));
|
||||||
EXPECT_TRUE(struct_deco->IsBlock());
|
EXPECT_TRUE(struct_deco->IsBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
|
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
|
||||||
auto* p = parser("[[block");
|
auto* p = parser("[[block");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ']]' for decoration list");
|
EXPECT_EQ(p->error(), "1:8: expected ']]' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
|
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
|
||||||
auto* p = parser("[[invalid]]");
|
auto* p = parser("[[invalid]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(decos.size(), 0u);
|
EXPECT_TRUE(decos.errored);
|
||||||
EXPECT_TRUE(decos.empty());
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -40,8 +40,10 @@ TEST_P(StructDecorationTest, Parses) {
|
||||||
|
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
auto struct_deco = ast::As<ast::StructDecoration>(std::move(deco));
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
|
auto struct_deco = ast::As<ast::StructDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(struct_deco, nullptr);
|
ASSERT_NE(struct_deco, nullptr);
|
||||||
EXPECT_EQ(struct_deco->IsBlock(), params.is_block);
|
EXPECT_EQ(struct_deco->IsBlock(), params.is_block);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +54,9 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||||
TEST_F(ParserImplTest, StructDecoration_NoMatch) {
|
TEST_F(ParserImplTest, StructDecoration_NoMatch) {
|
||||||
auto* p = parser("not-a-stage");
|
auto* p = parser("not-a-stage");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_EQ(deco.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,40 +25,50 @@ namespace {
|
||||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyStr) {
|
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyStr) {
|
||||||
auto* p = parser("");
|
auto* p = parser("");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(decos.value.size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyBlock) {
|
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyBlock) {
|
||||||
auto* p = parser("[[]]");
|
auto* p = parser("[[]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(decos.size(), 0u);
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(decos.value.size(), 0u);
|
||||||
EXPECT_EQ(p->error(), "1:3: empty decoration list");
|
EXPECT_EQ(p->error(), "1:3: empty decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_Single) {
|
TEST_F(ParserImplTest, StructMemberDecorationDecl_Single) {
|
||||||
auto* p = parser("[[offset(4)]]");
|
auto* p = parser("[[offset(4)]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(decos.size(), 1u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto deco = ast::As<ast::StructMemberDecoration>(std::move(decos[0]));
|
EXPECT_TRUE(decos.matched);
|
||||||
|
ASSERT_EQ(decos.value.size(), 1u);
|
||||||
|
auto deco = ast::As<ast::StructMemberDecoration>(std::move(decos.value[0]));
|
||||||
ASSERT_NE(deco, nullptr);
|
ASSERT_NE(deco, nullptr);
|
||||||
EXPECT_TRUE(deco->IsOffset());
|
EXPECT_TRUE(deco->IsOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_InvalidDecoration) {
|
TEST_F(ParserImplTest, StructMemberDecorationDecl_InvalidDecoration) {
|
||||||
auto* p = parser("[[offset(nan)]]");
|
auto* p = parser("[[offset(nan)]]");
|
||||||
p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error()) << p->error();
|
EXPECT_TRUE(p->has_error()) << p->error();
|
||||||
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_MissingClose) {
|
TEST_F(ParserImplTest, StructMemberDecorationDecl_MissingClose) {
|
||||||
auto* p = parser("[[offset(4)");
|
auto* p = parser("[[offset(4)");
|
||||||
p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error()) << p->error();
|
EXPECT_TRUE(p->has_error()) << p->error();
|
||||||
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
EXPECT_EQ(p->error(), "1:12: expected ']]' for decoration list");
|
EXPECT_EQ(p->error(), "1:12: expected ']]' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
|
TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
|
||||||
auto* p = parser("offset(4)");
|
auto* p = parser("offset(4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
|
|
||||||
auto member_deco = ast::As<ast::StructMemberDecoration>(std::move(deco));
|
auto member_deco =
|
||||||
|
ast::As<ast::StructMemberDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(member_deco, nullptr);
|
ASSERT_NE(member_deco, nullptr);
|
||||||
ASSERT_TRUE(member_deco->IsOffset());
|
ASSERT_TRUE(member_deco->IsOffset());
|
||||||
|
|
||||||
|
@ -39,24 +42,30 @@ TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
|
||||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingLeftParen) {
|
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingLeftParen) {
|
||||||
auto* p = parser("offset 4)");
|
auto* p = parser("offset 4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '(' for offset decoration");
|
EXPECT_EQ(p->error(), "1:8: expected '(' for offset decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingRightParen) {
|
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingRightParen) {
|
||||||
auto* p = parser("offset(4");
|
auto* p = parser("offset(4");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected ')' for offset decoration");
|
EXPECT_EQ(p->error(), "1:9: expected ')' for offset decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingValue) {
|
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingValue) {
|
||||||
auto* p = parser("offset()");
|
auto* p = parser("offset()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:8: expected signed integer literal for offset decoration");
|
"1:8: expected signed integer literal for offset decoration");
|
||||||
}
|
}
|
||||||
|
@ -64,8 +73,10 @@ TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingValue) {
|
||||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingInvalid) {
|
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingInvalid) {
|
||||||
auto* p = parser("offset(nan)");
|
auto* p = parser("offset(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:8: expected signed integer literal for offset decoration");
|
"1:8: expected signed integer literal for offset decoration");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,11 @@ TEST_F(ParserImplTest, StructMember_Parses) {
|
||||||
|
|
||||||
auto* p = parser("a : i32;");
|
auto* p = parser("a : i32;");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
EXPECT_EQ(decos.size(), 0u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_EQ(decos.value.size(), 0u);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_NE(m.value, nullptr);
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
@ -50,8 +53,11 @@ TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
||||||
|
|
||||||
auto* p = parser("[[offset(2)]] a : i32;");
|
auto* p = parser("[[offset(2)]] a : i32;");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
EXPECT_EQ(decos.size(), 1u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_TRUE(decos.matched);
|
||||||
|
EXPECT_EQ(decos.value.size(), 1u);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_NE(m.value, nullptr);
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
@ -74,8 +80,11 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
|
||||||
auto* p = parser(R"([[offset(2)]]
|
auto* p = parser(R"([[offset(2)]]
|
||||||
[[offset(4)]] a : i32;)");
|
[[offset(4)]] a : i32;)");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
EXPECT_EQ(decos.size(), 2u);
|
EXPECT_FALSE(decos.errored);
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_TRUE(decos.matched);
|
||||||
|
EXPECT_EQ(decos.value.size(), 2u);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(m.errored);
|
ASSERT_FALSE(m.errored);
|
||||||
ASSERT_NE(m.value, nullptr);
|
ASSERT_NE(m.value, nullptr);
|
||||||
|
@ -97,7 +106,10 @@ TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
|
||||||
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
||||||
auto* p = parser("[[offset(nan)]] a : i32;");
|
auto* p = parser("[[offset(nan)]] a : i32;");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(m.errored);
|
ASSERT_TRUE(m.errored);
|
||||||
ASSERT_EQ(m.value, nullptr);
|
ASSERT_EQ(m.value, nullptr);
|
||||||
|
@ -108,7 +120,10 @@ TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
||||||
TEST_F(ParserImplTest, StructMember_InvalidVariable) {
|
TEST_F(ParserImplTest, StructMember_InvalidVariable) {
|
||||||
auto* p = parser("[[offset(4)]] a : B;");
|
auto* p = parser("[[offset(4)]] a : B;");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_TRUE(decos.matched);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(m.errored);
|
ASSERT_TRUE(m.errored);
|
||||||
ASSERT_EQ(m.value, nullptr);
|
ASSERT_EQ(m.value, nullptr);
|
||||||
|
@ -118,7 +133,10 @@ TEST_F(ParserImplTest, StructMember_InvalidVariable) {
|
||||||
TEST_F(ParserImplTest, StructMember_MissingSemicolon) {
|
TEST_F(ParserImplTest, StructMember_MissingSemicolon) {
|
||||||
auto* p = parser("a : i32");
|
auto* p = parser("a : i32");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
auto m = p->expect_struct_member(decos);
|
EXPECT_FALSE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
|
||||||
|
auto m = p->expect_struct_member(decos.value);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(m.errored);
|
ASSERT_TRUE(m.errored);
|
||||||
ASSERT_EQ(m.value, nullptr);
|
ASSERT_EQ(m.value, nullptr);
|
||||||
|
|
|
@ -25,110 +25,136 @@ namespace {
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case) {
|
TEST_F(ParserImplTest, SwitchBody_Case) {
|
||||||
auto* p = parser("case 1: { a = 4; }");
|
auto* p = parser("case 1: { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsCase());
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(e->IsDefault());
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_TRUE(e.value->IsCase());
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsAssign());
|
EXPECT_FALSE(e.value->IsDefault());
|
||||||
|
ASSERT_EQ(e.value->body()->size(), 1u);
|
||||||
|
EXPECT_TRUE(e.value->body()->get(0)->IsAssign());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
||||||
auto* p = parser("case a == 4: { a = 4; }");
|
auto* p = parser("case a == 4: { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: unable to parse case selectors");
|
EXPECT_EQ(p->error(), "1:6: unable to parse case selectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidSelector_bool) {
|
TEST_F(ParserImplTest, SwitchBody_Case_InvalidSelector_bool) {
|
||||||
auto* p = parser("case true: { a = 4; }");
|
auto* p = parser("case true: { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: invalid case selector must be an integer value");
|
EXPECT_EQ(p->error(), "1:6: invalid case selector must be an integer value");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingConstLiteral) {
|
TEST_F(ParserImplTest, SwitchBody_Case_MissingConstLiteral) {
|
||||||
auto* p = parser("case: { a = 4; }");
|
auto* p = parser("case: { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:5: unable to parse case selectors");
|
EXPECT_EQ(p->error(), "1:5: unable to parse case selectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingColon) {
|
TEST_F(ParserImplTest, SwitchBody_Case_MissingColon) {
|
||||||
auto* p = parser("case 1 { a = 4; }");
|
auto* p = parser("case 1 { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected ':' for case statement");
|
EXPECT_EQ(p->error(), "1:8: expected ':' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketLeft) {
|
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketLeft) {
|
||||||
auto* p = parser("case 1: a = 4; }");
|
auto* p = parser("case 1: a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected '{' for case statement");
|
EXPECT_EQ(p->error(), "1:9: expected '{' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketRight) {
|
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketRight) {
|
||||||
auto* p = parser("case 1: { a = 4; ");
|
auto* p = parser("case 1: { a = 4; ");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:18: expected '}' for case statement");
|
EXPECT_EQ(p->error(), "1:18: expected '}' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidCaseBody) {
|
TEST_F(ParserImplTest, SwitchBody_Case_InvalidCaseBody) {
|
||||||
auto* p = parser("case 1: { fn main() -> void {} }");
|
auto* p = parser("case 1: { fn main() -> void {} }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '}' for case statement");
|
EXPECT_EQ(p->error(), "1:11: expected '}' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default) {
|
TEST_F(ParserImplTest, SwitchBody_Default) {
|
||||||
auto* p = parser("default: { a = 4; }");
|
auto* p = parser("default: { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_TRUE(e->IsCase());
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e->IsDefault());
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_TRUE(e.value->IsCase());
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsAssign());
|
EXPECT_TRUE(e.value->IsDefault());
|
||||||
|
ASSERT_EQ(e.value->body()->size(), 1u);
|
||||||
|
EXPECT_TRUE(e.value->body()->get(0)->IsAssign());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
|
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
|
||||||
auto* p = parser("default { a = 4; }");
|
auto* p = parser("default { a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected ':' for case statement");
|
EXPECT_EQ(p->error(), "1:9: expected ':' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketLeft) {
|
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketLeft) {
|
||||||
auto* p = parser("default: a = 4; }");
|
auto* p = parser("default: a = 4; }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '{' for case statement");
|
EXPECT_EQ(p->error(), "1:10: expected '{' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketRight) {
|
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketRight) {
|
||||||
auto* p = parser("default: { a = 4; ");
|
auto* p = parser("default: { a = 4; ");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:19: expected '}' for case statement");
|
EXPECT_EQ(p->error(), "1:19: expected '}' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default_InvalidCaseBody) {
|
TEST_F(ParserImplTest, SwitchBody_Default_InvalidCaseBody) {
|
||||||
auto* p = parser("default: { fn main() -> void {} }");
|
auto* p = parser("default: { fn main() -> void {} }");
|
||||||
auto e = p->switch_body();
|
auto e = p->switch_body();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_FALSE(e.matched);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:12: expected '}' for case statement");
|
EXPECT_EQ(p->error(), "1:12: expected '}' for case statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,21 +29,25 @@ TEST_F(ParserImplTest, SwitchStmt_WithoutDefault) {
|
||||||
case 2: {}
|
case 2: {}
|
||||||
})");
|
})");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->body().size(), 2u);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_FALSE(e->body()[0]->IsDefault());
|
ASSERT_TRUE(e.value->IsSwitch());
|
||||||
EXPECT_FALSE(e->body()[1]->IsDefault());
|
ASSERT_EQ(e.value->body().size(), 2u);
|
||||||
|
EXPECT_FALSE(e.value->body()[0]->IsDefault());
|
||||||
|
EXPECT_FALSE(e.value->body()[1]->IsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_Empty) {
|
TEST_F(ParserImplTest, SwitchStmt_Empty) {
|
||||||
auto* p = parser("switch(a) { }");
|
auto* p = parser("switch(a) { }");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->body().size(), 0u);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsSwitch());
|
||||||
|
ASSERT_EQ(e.value->body().size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
||||||
|
@ -53,45 +57,55 @@ TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
||||||
case 2: {}
|
case 2: {}
|
||||||
})");
|
})");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsSwitch());
|
||||||
|
|
||||||
ASSERT_EQ(e->body().size(), 3u);
|
ASSERT_EQ(e.value->body().size(), 3u);
|
||||||
ASSERT_FALSE(e->body()[0]->IsDefault());
|
ASSERT_FALSE(e.value->body()[0]->IsDefault());
|
||||||
ASSERT_TRUE(e->body()[1]->IsDefault());
|
ASSERT_TRUE(e.value->body()[1]->IsDefault());
|
||||||
ASSERT_FALSE(e->body()[2]->IsDefault());
|
ASSERT_FALSE(e.value->body()[2]->IsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
|
TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
|
||||||
auto* p = parser("switch(a=b) {}");
|
auto* p = parser("switch(a=b) {}");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected ')'");
|
EXPECT_EQ(p->error(), "1:9: expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_MissingExpression) {
|
TEST_F(ParserImplTest, SwitchStmt_MissingExpression) {
|
||||||
auto* p = parser("switch {}");
|
auto* p = parser("switch {}");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '('");
|
EXPECT_EQ(p->error(), "1:8: expected '('");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_MissingBracketLeft) {
|
TEST_F(ParserImplTest, SwitchStmt_MissingBracketLeft) {
|
||||||
auto* p = parser("switch(a) }");
|
auto* p = parser("switch(a) }");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '{' for switch statement");
|
EXPECT_EQ(p->error(), "1:11: expected '{' for switch statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
|
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
|
||||||
auto* p = parser("switch(a) {");
|
auto* p = parser("switch(a) {");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:12: expected '}' for switch statement");
|
EXPECT_EQ(p->error(), "1:12: expected '}' for switch statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +114,10 @@ TEST_F(ParserImplTest, SwitchStmt_InvalidBody) {
|
||||||
case: {}
|
case: {}
|
||||||
})");
|
})");
|
||||||
auto e = p->switch_stmt();
|
auto e = p->switch_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "2:7: unable to parse case selectors");
|
EXPECT_EQ(p->error(), "2:7: unable to parse case selectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,325 +26,395 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_Invalid) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_Sampler) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_Sampler) {
|
||||||
auto* p = parser("sampler");
|
auto* p = parser("sampler");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsSampler());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_FALSE(t->AsSampler()->IsComparison());
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsSampler());
|
||||||
|
ASSERT_FALSE(t.value->AsSampler()->IsComparison());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) {
|
||||||
auto* p = parser("sampler_comparison");
|
auto* p = parser("sampler_comparison");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsSampler());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsSampler()->IsComparison());
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsSampler());
|
||||||
|
ASSERT_TRUE(t.value->AsSampler()->IsComparison());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) {
|
||||||
auto* p = parser("texture_depth_2d");
|
auto* p = parser("texture_depth_2d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsDepth());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsDepth());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32_Old) {
|
||||||
auto* p = parser("texture_sampled_1d<f32>");
|
auto* p = parser("texture_sampled_1d<f32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32_Old) {
|
||||||
auto* p = parser("texture_sampled_2d<i32>");
|
auto* p = parser("texture_sampled_2d<i32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsI32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32_Old) {
|
||||||
auto* p = parser("texture_sampled_3d<u32>");
|
auto* p = parser("texture_sampled_3d<u32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsU32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k3d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsU32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k3d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid_Old) {
|
||||||
auto* p = parser("texture_sampled_1d<abc>");
|
auto* p = parser("texture_sampled_1d<abc>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:20: unknown constructed type 'abc'");
|
EXPECT_EQ(p->error(), "1:20: unknown constructed type 'abc'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType_Old) {
|
||||||
auto* p = parser("texture_sampled_1d<>");
|
auto* p = parser("texture_sampled_1d<>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type");
|
EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan_Old) {
|
||||||
auto* p = parser("texture_sampled_1d");
|
auto* p = parser("texture_sampled_1d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:19: expected '<' for sampled texture type");
|
EXPECT_EQ(p->error(), "1:19: expected '<' for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_SampledTexture_MissingGreaterThan_Old) {
|
TextureSamplerTypes_SampledTexture_MissingGreaterThan_Old) {
|
||||||
auto* p = parser("texture_sampled_1d<u32");
|
auto* p = parser("texture_sampled_1d<u32");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:23: expected '>' for sampled texture type");
|
EXPECT_EQ(p->error(), "1:23: expected '>' for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) {
|
||||||
auto* p = parser("texture_1d<f32>");
|
auto* p = parser("texture_1d<f32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32) {
|
||||||
auto* p = parser("texture_2d<i32>");
|
auto* p = parser("texture_2d<i32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsI32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32) {
|
||||||
auto* p = parser("texture_3d<u32>");
|
auto* p = parser("texture_3d<u32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsU32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k3d);
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsU32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k3d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid) {
|
||||||
auto* p = parser("texture_1d<abc>");
|
auto* p = parser("texture_1d<abc>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:12: unknown constructed type 'abc'");
|
EXPECT_EQ(p->error(), "1:12: unknown constructed type 'abc'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) {
|
||||||
auto* p = parser("texture_1d<>");
|
auto* p = parser("texture_1d<>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:12: invalid subtype for sampled texture type");
|
EXPECT_EQ(p->error(), "1:12: invalid subtype for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) {
|
||||||
auto* p = parser("texture_1d");
|
auto* p = parser("texture_1d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '<' for sampled texture type");
|
EXPECT_EQ(p->error(), "1:11: expected '<' for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) {
|
||||||
auto* p = parser("texture_1d<u32");
|
auto* p = parser("texture_1d<u32");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:15: expected '>' for sampled texture type");
|
EXPECT_EQ(p->error(), "1:15: expected '>' for sampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_I32) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_I32) {
|
||||||
auto* p = parser("texture_multisampled_2d<i32>");
|
auto* p = parser("texture_multisampled_2d<i32>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsMultisampled());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsMultisampled()->type()->IsI32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
ASSERT_TRUE(t.value->AsTexture()->IsMultisampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsMultisampled()->type()->IsI32());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_Invalid) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_Invalid) {
|
||||||
auto* p = parser("texture_multisampled_2d<abc>");
|
auto* p = parser("texture_multisampled_2d<abc>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:25: unknown constructed type 'abc'");
|
EXPECT_EQ(p->error(), "1:25: unknown constructed type 'abc'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingType) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingType) {
|
||||||
auto* p = parser("texture_multisampled_2d<>");
|
auto* p = parser("texture_multisampled_2d<>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:25: invalid subtype for multisampled texture type");
|
EXPECT_EQ(p->error(), "1:25: invalid subtype for multisampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_MultisampledTexture_MissingLessThan) {
|
TextureSamplerTypes_MultisampledTexture_MissingLessThan) {
|
||||||
auto* p = parser("texture_multisampled_2d");
|
auto* p = parser("texture_multisampled_2d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:24: expected '<' for multisampled texture type");
|
EXPECT_EQ(p->error(), "1:24: expected '<' for multisampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_MultisampledTexture_MissingGreaterThan) {
|
TextureSamplerTypes_MultisampledTexture_MissingGreaterThan) {
|
||||||
auto* p = parser("texture_multisampled_2d<u32");
|
auto* p = parser("texture_multisampled_2d<u32");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:28: expected '>' for multisampled texture type");
|
EXPECT_EQ(p->error(), "1:28: expected '>' for multisampled texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm_Old) {
|
TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm_Old) {
|
||||||
auto* p = parser("texture_ro_1d<r8unorm>");
|
auto* p = parser("texture_ro_1d<r8unorm>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsStorage());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsStorage());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
|
||||||
ast::type::ImageFormat::kR8Unorm);
|
ast::type::ImageFormat::kR8Unorm);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
|
||||||
ast::AccessControl::kReadOnly);
|
ast::AccessControl::kReadOnly);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_StorageTexture_Writeonly2dR16Float_Old) {
|
TextureSamplerTypes_StorageTexture_Writeonly2dR16Float_Old) {
|
||||||
auto* p = parser("texture_wo_2d<r16float>");
|
auto* p = parser("texture_wo_2d<r16float>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsStorage());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsStorage());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
|
||||||
ast::type::ImageFormat::kR16Float);
|
ast::type::ImageFormat::kR16Float);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
|
||||||
ast::AccessControl::kWriteOnly);
|
ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType_Old) {
|
||||||
auto* p = parser("texture_ro_1d<abc>");
|
auto* p = parser("texture_ro_1d<abc>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
|
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType_Old) {
|
||||||
auto* p = parser("texture_wo_1d<>");
|
auto* p = parser("texture_wo_1d<>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
|
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan_Old) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan_Old) {
|
||||||
auto* p = parser("texture_ro_1d");
|
auto* p = parser("texture_ro_1d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:14: expected '<' for storage texture type");
|
EXPECT_EQ(p->error(), "1:14: expected '<' for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest,
|
TEST_F(ParserImplTest,
|
||||||
TextureSamplerTypes_StorageTexture_MissingGreaterThan_Old) {
|
TextureSamplerTypes_StorageTexture_MissingGreaterThan_Old) {
|
||||||
auto* p = parser("texture_wo_1d<r8unorm");
|
auto* p = parser("texture_wo_1d<r8unorm");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:22: expected '>' for storage texture type");
|
EXPECT_EQ(p->error(), "1:22: expected '>' for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm) {
|
||||||
auto* p = parser("texture_storage_ro_1d<r8unorm>");
|
auto* p = parser("texture_storage_ro_1d<r8unorm>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsStorage());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsStorage());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
|
||||||
ast::type::ImageFormat::kR8Unorm);
|
ast::type::ImageFormat::kR8Unorm);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
|
||||||
ast::AccessControl::kReadOnly);
|
ast::AccessControl::kReadOnly);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) {
|
||||||
auto* p = parser("texture_storage_wo_2d<r16float>");
|
auto* p = parser("texture_storage_wo_2d<r16float>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsStorage());
|
ASSERT_NE(t.value, nullptr);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsStorage());
|
||||||
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
|
||||||
ast::type::ImageFormat::kR16Float);
|
ast::type::ImageFormat::kR16Float);
|
||||||
EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
|
EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
|
||||||
ast::AccessControl::kWriteOnly);
|
ast::AccessControl::kWriteOnly);
|
||||||
EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType) {
|
||||||
auto* p = parser("texture_storage_ro_1d<abc>");
|
auto* p = parser("texture_storage_ro_1d<abc>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
|
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType) {
|
||||||
auto* p = parser("texture_storage_ro_1d<>");
|
auto* p = parser("texture_storage_ro_1d<>");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
|
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan) {
|
||||||
auto* p = parser("texture_storage_ro_1d");
|
auto* p = parser("texture_storage_ro_1d");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:22: expected '<' for storage texture type");
|
EXPECT_EQ(p->error(), "1:22: expected '<' for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingGreaterThan) {
|
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingGreaterThan) {
|
||||||
auto* p = parser("texture_storage_ro_1d<r8unorm");
|
auto* p = parser("texture_storage_ro_1d<r8unorm");
|
||||||
auto* t = p->texture_sampler_types();
|
auto t = p->texture_sampler_types();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.value, nullptr);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(t.errored);
|
||||||
EXPECT_EQ(p->error(), "1:30: expected '>' for storage texture type");
|
EXPECT_EQ(p->error(), "1:30: expected '>' for storage texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,13 @@ TEST_F(ParserImplTest, TypeDecl_ParsesType) {
|
||||||
auto* i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
auto* i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||||
|
|
||||||
auto* p = parser("type a = i32");
|
auto* p = parser("type a = i32");
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsAlias());
|
EXPECT_TRUE(t.matched);
|
||||||
auto* alias = t->AsAlias();
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsAlias());
|
||||||
|
auto* alias = t.value->AsAlias();
|
||||||
ASSERT_TRUE(alias->type()->IsI32());
|
ASSERT_TRUE(alias->type()->IsI32());
|
||||||
ASSERT_EQ(alias->type(), i32);
|
ASSERT_EQ(alias->type(), i32);
|
||||||
}
|
}
|
||||||
|
@ -45,11 +47,13 @@ TEST_F(ParserImplTest, TypeDecl_ParsesStruct_Ident) {
|
||||||
auto* p = parser("type a = B");
|
auto* p = parser("type a = B");
|
||||||
p->register_constructed("B", &str);
|
p->register_constructed("B", &str);
|
||||||
|
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsAlias());
|
EXPECT_TRUE(t.matched);
|
||||||
auto* alias = t->AsAlias();
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
ASSERT_TRUE(t.value->IsAlias());
|
||||||
|
auto* alias = t.value->AsAlias();
|
||||||
EXPECT_EQ(alias->name(), "a");
|
EXPECT_EQ(alias->name(), "a");
|
||||||
ASSERT_TRUE(alias->type()->IsStruct());
|
ASSERT_TRUE(alias->type()->IsStruct());
|
||||||
|
|
||||||
|
@ -59,33 +63,41 @@ TEST_F(ParserImplTest, TypeDecl_ParsesStruct_Ident) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
|
TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
|
||||||
auto* p = parser("type = i32");
|
auto* p = parser("type = i32");
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(t.errored);
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
|
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_InvalidIdent) {
|
TEST_F(ParserImplTest, TypeDecl_InvalidIdent) {
|
||||||
auto* p = parser("type 123 = i32");
|
auto* p = parser("type 123 = i32");
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(t.errored);
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
|
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_MissingEqual) {
|
TEST_F(ParserImplTest, TypeDecl_MissingEqual) {
|
||||||
auto* p = parser("type a i32");
|
auto* p = parser("type a i32");
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(t.errored);
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '=' for type alias");
|
EXPECT_EQ(p->error(), "1:8: expected '=' for type alias");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_InvalidType) {
|
TEST_F(ParserImplTest, TypeDecl_InvalidType) {
|
||||||
auto* p = parser("type a = B");
|
auto* p = parser("type a = B");
|
||||||
auto* t = p->type_alias();
|
auto t = p->type_alias();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(t.errored);
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_FALSE(t.matched);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'B'");
|
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'B'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,10 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Invalid) {
|
TEST_F(ParserImplTest, TypeDecl_Invalid) {
|
||||||
auto* p = parser("1234");
|
auto* p = parser("1234");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
EXPECT_EQ(t, nullptr);
|
EXPECT_EQ(t.errored, false);
|
||||||
|
EXPECT_EQ(t.matched, false);
|
||||||
|
EXPECT_EQ(t.value, nullptr);
|
||||||
EXPECT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +54,14 @@ TEST_F(ParserImplTest, TypeDecl_Identifier) {
|
||||||
|
|
||||||
p->register_constructed("A", alias_type);
|
p->register_constructed("A", alias_type);
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, alias_type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsAlias());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
|
EXPECT_EQ(t.value, alias_type);
|
||||||
|
ASSERT_TRUE(t.value->IsAlias());
|
||||||
|
|
||||||
auto* alias = t->AsAlias();
|
auto* alias = t.value->AsAlias();
|
||||||
EXPECT_EQ(alias->name(), "A");
|
EXPECT_EQ(alias->name(), "A");
|
||||||
EXPECT_EQ(alias->type(), int_type);
|
EXPECT_EQ(alias->type(), int_type);
|
||||||
}
|
}
|
||||||
|
@ -65,8 +69,10 @@ TEST_F(ParserImplTest, TypeDecl_Identifier) {
|
||||||
TEST_F(ParserImplTest, TypeDecl_Identifier_NotFound) {
|
TEST_F(ParserImplTest, TypeDecl_Identifier_NotFound) {
|
||||||
auto* p = parser("B");
|
auto* p = parser("B");
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:1: unknown constructed type 'B'");
|
EXPECT_EQ(p->error(), "1:1: unknown constructed type 'B'");
|
||||||
}
|
}
|
||||||
|
@ -76,10 +82,12 @@ TEST_F(ParserImplTest, TypeDecl_Bool) {
|
||||||
|
|
||||||
auto* bool_type = tm()->Get(std::make_unique<ast::type::BoolType>());
|
auto* bool_type = tm()->Get(std::make_unique<ast::type::BoolType>());
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, bool_type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsBool());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
|
EXPECT_EQ(t.value, bool_type);
|
||||||
|
ASSERT_TRUE(t.value->IsBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_F32) {
|
TEST_F(ParserImplTest, TypeDecl_F32) {
|
||||||
|
@ -87,10 +95,12 @@ TEST_F(ParserImplTest, TypeDecl_F32) {
|
||||||
|
|
||||||
auto* float_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
auto* float_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, float_type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsF32());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
|
EXPECT_EQ(t.value, float_type);
|
||||||
|
ASSERT_TRUE(t.value->IsF32());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_I32) {
|
TEST_F(ParserImplTest, TypeDecl_I32) {
|
||||||
|
@ -98,10 +108,12 @@ TEST_F(ParserImplTest, TypeDecl_I32) {
|
||||||
|
|
||||||
auto* int_type = tm()->Get(std::make_unique<ast::type::I32Type>());
|
auto* int_type = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, int_type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsI32());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
|
EXPECT_EQ(t.value, int_type);
|
||||||
|
ASSERT_TRUE(t.value->IsI32());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_U32) {
|
TEST_F(ParserImplTest, TypeDecl_U32) {
|
||||||
|
@ -109,10 +121,12 @@ TEST_F(ParserImplTest, TypeDecl_U32) {
|
||||||
|
|
||||||
auto* uint_type = tm()->Get(std::make_unique<ast::type::U32Type>());
|
auto* uint_type = tm()->Get(std::make_unique<ast::type::U32Type>());
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, uint_type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsU32());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
|
EXPECT_EQ(t.value, uint_type);
|
||||||
|
ASSERT_TRUE(t.value->IsU32());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VecData {
|
struct VecData {
|
||||||
|
@ -129,11 +143,13 @@ class VecTest : public ParserImplTestWithParam<VecData> {};
|
||||||
TEST_P(VecTest, Parse) {
|
TEST_P(VecTest, Parse) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
EXPECT_TRUE(t->IsVector());
|
EXPECT_TRUE(t.value->IsVector());
|
||||||
EXPECT_EQ(t->AsVector()->size(), params.count);
|
EXPECT_EQ(t.value->AsVector()->size(), params.count);
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||||
VecTest,
|
VecTest,
|
||||||
|
@ -146,8 +162,10 @@ class VecMissingGreaterThanTest : public ParserImplTestWithParam<VecData> {};
|
||||||
TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:9: expected '>' for vector");
|
ASSERT_EQ(p->error(), "1:9: expected '>' for vector");
|
||||||
}
|
}
|
||||||
|
@ -162,8 +180,10 @@ class VecMissingLessThanTest : public ParserImplTestWithParam<VecData> {};
|
||||||
TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
|
TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:5: expected '<' for vector");
|
ASSERT_EQ(p->error(), "1:5: expected '<' for vector");
|
||||||
}
|
}
|
||||||
|
@ -178,8 +198,10 @@ class VecBadType : public ParserImplTestWithParam<VecData> {};
|
||||||
TEST_P(VecBadType, Handles_Unknown_Type) {
|
TEST_P(VecBadType, Handles_Unknown_Type) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:6: unknown constructed type 'unknown'");
|
ASSERT_EQ(p->error(), "1:6: unknown constructed type 'unknown'");
|
||||||
}
|
}
|
||||||
|
@ -194,8 +216,10 @@ class VecMissingType : public ParserImplTestWithParam<VecData> {};
|
||||||
TEST_P(VecMissingType, Handles_Missing_Type) {
|
TEST_P(VecMissingType, Handles_Missing_Type) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
ASSERT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
||||||
}
|
}
|
||||||
|
@ -207,24 +231,28 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr) {
|
||||||
auto* p = parser("ptr<function, f32>");
|
auto* p = parser("ptr<function, f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsPointer());
|
ASSERT_TRUE(t.value->IsPointer());
|
||||||
|
|
||||||
auto* ptr = t->AsPointer();
|
auto* ptr = t.value->AsPointer();
|
||||||
ASSERT_TRUE(ptr->type()->IsF32());
|
ASSERT_TRUE(ptr->type()->IsF32());
|
||||||
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
|
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
|
||||||
auto* p = parser("ptr<function, vec2<f32>>");
|
auto* p = parser("ptr<function, vec2<f32>>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsPointer());
|
ASSERT_TRUE(t.value->IsPointer());
|
||||||
|
|
||||||
auto* ptr = t->AsPointer();
|
auto* ptr = t.value->AsPointer();
|
||||||
ASSERT_TRUE(ptr->type()->IsVector());
|
ASSERT_TRUE(ptr->type()->IsVector());
|
||||||
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
|
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
|
||||||
|
|
||||||
|
@ -235,76 +263,94 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
|
||||||
auto* p = parser("ptr private, f32>");
|
auto* p = parser("ptr private, f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration");
|
ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) {
|
||||||
auto* p = parser("ptr<function, f32");
|
auto* p = parser("ptr<function, f32");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration");
|
ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) {
|
||||||
auto* p = parser("ptr<function f32>");
|
auto* p = parser("ptr<function f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:14: expected ',' for ptr declaration");
|
ASSERT_EQ(p->error(), "1:14: expected ',' for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) {
|
||||||
auto* p = parser("ptr<, f32>");
|
auto* p = parser("ptr<, f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
|
||||||
auto* p = parser("ptr<>");
|
auto* p = parser("ptr<>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
|
||||||
auto* p = parser("ptr<function,>");
|
auto* p = parser("ptr<function,>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:14: missing type for ptr declaration");
|
ASSERT_EQ(p->error(), "1:14: missing type for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
|
||||||
auto* p = parser("ptr<unknown, f32>");
|
auto* p = parser("ptr<unknown, f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Ptr_BadType) {
|
TEST_F(ParserImplTest, TypeDecl_Ptr_BadType) {
|
||||||
auto* p = parser("ptr<function, unknown>");
|
auto* p = parser("ptr<function, unknown>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:15: unknown constructed type 'unknown'");
|
ASSERT_EQ(p->error(), "1:15: unknown constructed type 'unknown'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array) {
|
TEST_F(ParserImplTest, TypeDecl_Array) {
|
||||||
auto* p = parser("array<f32, 5>");
|
auto* p = parser("array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_FALSE(a->IsRuntimeArray());
|
ASSERT_FALSE(a->IsRuntimeArray());
|
||||||
ASSERT_EQ(a->size(), 5u);
|
ASSERT_EQ(a->size(), 5u);
|
||||||
ASSERT_TRUE(a->type()->IsF32());
|
ASSERT_TRUE(a->type()->IsF32());
|
||||||
|
@ -313,12 +359,14 @@ TEST_F(ParserImplTest, TypeDecl_Array) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
|
||||||
auto* p = parser("[[stride(16)]] array<f32, 5>");
|
auto* p = parser("[[stride(16)]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_FALSE(a->IsRuntimeArray());
|
ASSERT_FALSE(a->IsRuntimeArray());
|
||||||
ASSERT_EQ(a->size(), 5u);
|
ASSERT_EQ(a->size(), 5u);
|
||||||
ASSERT_TRUE(a->type()->IsF32());
|
ASSERT_TRUE(a->type()->IsF32());
|
||||||
|
@ -328,12 +376,14 @@ TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
|
||||||
auto* p = parser("[[stride(16)]] array<f32>");
|
auto* p = parser("[[stride(16)]] array<f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_TRUE(a->IsRuntimeArray());
|
ASSERT_TRUE(a->IsRuntimeArray());
|
||||||
ASSERT_TRUE(a->type()->IsF32());
|
ASSERT_TRUE(a->type()->IsF32());
|
||||||
ASSERT_TRUE(a->has_array_stride());
|
ASSERT_TRUE(a->has_array_stride());
|
||||||
|
@ -342,12 +392,14 @@ TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
|
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
|
||||||
auto* p = parser("[[stride(16), stride(32)]] array<f32>");
|
auto* p = parser("[[stride(16), stride(32)]] array<f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_TRUE(a->IsRuntimeArray());
|
ASSERT_TRUE(a->IsRuntimeArray());
|
||||||
ASSERT_TRUE(a->type()->IsF32());
|
ASSERT_TRUE(a->type()->IsF32());
|
||||||
|
|
||||||
|
@ -361,12 +413,14 @@ TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
|
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
|
||||||
auto* p = parser("[[stride(16)]] [[stride(32)]] array<f32>");
|
auto* p = parser("[[stride(16)]] [[stride(32)]] array<f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_TRUE(a->IsRuntimeArray());
|
ASSERT_TRUE(a->IsRuntimeArray());
|
||||||
ASSERT_TRUE(a->type()->IsF32());
|
ASSERT_TRUE(a->type()->IsF32());
|
||||||
|
|
||||||
|
@ -380,48 +434,60 @@ TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
|
||||||
auto* p = parser("[[stride(16)]] f32");
|
auto* p = parser("[[stride(16)]] f32");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: unexpected decorations");
|
EXPECT_EQ(p->error(), "1:3: unexpected decorations");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingClosingAttr) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingClosingAttr) {
|
||||||
auto* p = parser("[[stride(16) array<f32, 5>");
|
auto* p = parser("[[stride(16) array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:14: expected ']]' for decoration list");
|
EXPECT_EQ(p->error(), "1:14: expected ']]' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_UnknownDecoration) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_UnknownDecoration) {
|
||||||
auto* p = parser("[[unknown 16]] array<f32, 5>");
|
auto* p = parser("[[unknown 16]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:3: expected decoration");
|
EXPECT_EQ(p->error(), "1:3: expected decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingLeftParen) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingLeftParen) {
|
||||||
auto* p = parser("[[stride 4)]] array<f32, 5>");
|
auto* p = parser("[[stride 4)]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '(' for stride decoration");
|
EXPECT_EQ(p->error(), "1:10: expected '(' for stride decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingRightParen) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingRightParen) {
|
||||||
auto* p = parser("[[stride(4]] array<f32, 5>");
|
auto* p = parser("[[stride(4]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected ')' for stride decoration");
|
EXPECT_EQ(p->error(), "1:11: expected ')' for stride decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingValue) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingValue) {
|
||||||
auto* p = parser("[[stride()]] array<f32, 5>");
|
auto* p = parser("[[stride()]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:10: expected signed integer literal for stride decoration");
|
"1:10: expected signed integer literal for stride decoration");
|
||||||
|
@ -429,8 +495,10 @@ TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingValue) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue) {
|
||||||
auto* p = parser("[[stride(invalid)]] array<f32, 5>");
|
auto* p = parser("[[stride(invalid)]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:10: expected signed integer literal for stride decoration");
|
"1:10: expected signed integer literal for stride decoration");
|
||||||
|
@ -438,76 +506,94 @@ TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue_Negative) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue_Negative) {
|
||||||
auto* p = parser("[[stride(-1)]] array<f32, 5>");
|
auto* p = parser("[[stride(-1)]] array<f32, 5>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: stride decoration must be greater than 0");
|
EXPECT_EQ(p->error(), "1:10: stride decoration must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
|
TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
|
||||||
auto* p = parser("array<u32>");
|
auto* p = parser("array<u32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(t->IsArray());
|
ASSERT_TRUE(t.value->IsArray());
|
||||||
|
|
||||||
auto* a = t->AsArray();
|
auto* a = t.value->AsArray();
|
||||||
ASSERT_TRUE(a->IsRuntimeArray());
|
ASSERT_TRUE(a->IsRuntimeArray());
|
||||||
ASSERT_TRUE(a->type()->IsU32());
|
ASSERT_TRUE(a->type()->IsU32());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_BadType) {
|
TEST_F(ParserImplTest, TypeDecl_Array_BadType) {
|
||||||
auto* p = parser("array<unknown, 3>");
|
auto* p = parser("array<unknown, 3>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:7: unknown constructed type 'unknown'");
|
ASSERT_EQ(p->error(), "1:7: unknown constructed type 'unknown'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_ZeroSize) {
|
TEST_F(ParserImplTest, TypeDecl_Array_ZeroSize) {
|
||||||
auto* p = parser("array<f32, 0>");
|
auto* p = parser("array<f32, 0>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
|
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_NegativeSize) {
|
TEST_F(ParserImplTest, TypeDecl_Array_NegativeSize) {
|
||||||
auto* p = parser("array<f32, -1>");
|
auto* p = parser("array<f32, -1>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
|
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
|
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
|
||||||
auto* p = parser("array<f32, invalid>");
|
auto* p = parser("array<f32, invalid>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:12: expected signed integer literal for array size");
|
ASSERT_EQ(p->error(), "1:12: expected signed integer literal for array size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
|
TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
|
||||||
auto* p = parser("array f32>");
|
auto* p = parser("array f32>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration");
|
ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
|
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
|
||||||
auto* p = parser("array<f32");
|
auto* p = parser("array<f32");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:10: expected '>' for array declaration");
|
ASSERT_EQ(p->error(), "1:10: expected '>' for array declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) {
|
TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) {
|
||||||
auto* p = parser("array<f32 3>");
|
auto* p = parser("array<f32 3>");
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:11: expected '>' for array declaration");
|
ASSERT_EQ(p->error(), "1:11: expected '>' for array declaration");
|
||||||
}
|
}
|
||||||
|
@ -527,11 +613,13 @@ class MatrixTest : public ParserImplTestWithParam<MatrixData> {};
|
||||||
TEST_P(MatrixTest, Parse) {
|
TEST_P(MatrixTest, Parse) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
|
EXPECT_FALSE(t.errored);
|
||||||
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
EXPECT_TRUE(t->IsMatrix());
|
EXPECT_TRUE(t.value->IsMatrix());
|
||||||
auto* mat = t->AsMatrix();
|
auto* mat = t.value->AsMatrix();
|
||||||
EXPECT_EQ(mat->rows(), params.rows);
|
EXPECT_EQ(mat->rows(), params.rows);
|
||||||
EXPECT_EQ(mat->columns(), params.columns);
|
EXPECT_EQ(mat->columns(), params.columns);
|
||||||
}
|
}
|
||||||
|
@ -553,10 +641,12 @@ class MatrixMissingGreaterThanTest
|
||||||
TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:11: missing > for matrix");
|
ASSERT_EQ(p->error(), "1:11: expected '>' for matrix");
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||||
MatrixMissingGreaterThanTest,
|
MatrixMissingGreaterThanTest,
|
||||||
|
@ -575,10 +665,12 @@ class MatrixMissingLessThanTest : public ParserImplTestWithParam<MatrixData> {};
|
||||||
TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
|
TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:8: missing < for matrix");
|
ASSERT_EQ(p->error(), "1:8: expected '<' for matrix");
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||||
MatrixMissingLessThanTest,
|
MatrixMissingLessThanTest,
|
||||||
|
@ -597,8 +689,10 @@ class MatrixBadType : public ParserImplTestWithParam<MatrixData> {};
|
||||||
TEST_P(MatrixBadType, Handles_Unknown_Type) {
|
TEST_P(MatrixBadType, Handles_Unknown_Type) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:8: unknown constructed type 'unknown'");
|
ASSERT_EQ(p->error(), "1:8: unknown constructed type 'unknown'");
|
||||||
}
|
}
|
||||||
|
@ -619,8 +713,10 @@ class MatrixMissingType : public ParserImplTestWithParam<MatrixData> {};
|
||||||
TEST_P(MatrixMissingType, Handles_Missing_Type) {
|
TEST_P(MatrixMissingType, Handles_Missing_Type) {
|
||||||
auto params = GetParam();
|
auto params = GetParam();
|
||||||
auto* p = parser(params.input);
|
auto* p = parser(params.input);
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_EQ(t, nullptr);
|
EXPECT_TRUE(t.errored);
|
||||||
|
EXPECT_FALSE(t.matched);
|
||||||
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:8: unable to determine subtype for matrix");
|
ASSERT_EQ(p->error(), "1:8: unable to determine subtype for matrix");
|
||||||
}
|
}
|
||||||
|
@ -642,11 +738,13 @@ TEST_F(ParserImplTest, TypeDecl_Sampler) {
|
||||||
auto* type = tm()->Get(std::make_unique<ast::type::SamplerType>(
|
auto* type = tm()->Get(std::make_unique<ast::type::SamplerType>(
|
||||||
ast::type::SamplerKind::kSampler));
|
ast::type::SamplerKind::kSampler));
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsSampler());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_FALSE(t->AsSampler()->IsComparison());
|
EXPECT_EQ(t.value, type);
|
||||||
|
ASSERT_TRUE(t.value->IsSampler());
|
||||||
|
ASSERT_FALSE(t.value->AsSampler()->IsComparison());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Texture_Old) {
|
TEST_F(ParserImplTest, TypeDecl_Texture_Old) {
|
||||||
|
@ -656,12 +754,14 @@ TEST_F(ParserImplTest, TypeDecl_Texture_Old) {
|
||||||
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
|
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
|
||||||
ast::type::TextureDimension::kCube, &f32));
|
ast::type::TextureDimension::kCube, &f32));
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr) << p->error();
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
ASSERT_NE(t.value, nullptr) << p->error();
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
EXPECT_EQ(t.value, type);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, TypeDecl_Texture) {
|
TEST_F(ParserImplTest, TypeDecl_Texture) {
|
||||||
|
@ -671,12 +771,14 @@ TEST_F(ParserImplTest, TypeDecl_Texture) {
|
||||||
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
|
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
|
||||||
ast::type::TextureDimension::kCube, &f32));
|
ast::type::TextureDimension::kCube, &f32));
|
||||||
|
|
||||||
auto* t = p->type_decl();
|
auto t = p->type_decl();
|
||||||
ASSERT_NE(t, nullptr);
|
EXPECT_TRUE(t.matched);
|
||||||
EXPECT_EQ(t, type);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_TRUE(t->IsTexture());
|
ASSERT_NE(t.value, nullptr);
|
||||||
ASSERT_TRUE(t->AsTexture()->IsSampled());
|
EXPECT_EQ(t.value, type);
|
||||||
ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
|
ASSERT_TRUE(t.value->IsTexture());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->IsSampled());
|
||||||
|
ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -29,11 +29,13 @@ namespace {
|
||||||
TEST_F(ParserImplTest, UnaryExpression_Postix) {
|
TEST_F(ParserImplTest, UnaryExpression_Postix) {
|
||||||
auto* p = parser("a[2]");
|
auto* p = parser("a[2]");
|
||||||
auto e = p->unary_expression();
|
auto e = p->unary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsArrayAccessor());
|
ASSERT_TRUE(e.value->IsArrayAccessor());
|
||||||
auto* ary = e->AsArrayAccessor();
|
auto* ary = e.value->AsArrayAccessor();
|
||||||
ASSERT_TRUE(ary->array()->IsIdentifier());
|
ASSERT_TRUE(ary->array()->IsIdentifier());
|
||||||
auto* ident = ary->array()->AsIdentifier();
|
auto* ident = ary->array()->AsIdentifier();
|
||||||
EXPECT_EQ(ident->name(), "a");
|
EXPECT_EQ(ident->name(), "a");
|
||||||
|
@ -48,11 +50,13 @@ TEST_F(ParserImplTest, UnaryExpression_Postix) {
|
||||||
TEST_F(ParserImplTest, UnaryExpression_Minus) {
|
TEST_F(ParserImplTest, UnaryExpression_Minus) {
|
||||||
auto* p = parser("- 1");
|
auto* p = parser("- 1");
|
||||||
auto e = p->unary_expression();
|
auto e = p->unary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsUnaryOp());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsUnaryOp());
|
||||||
|
|
||||||
auto* u = e->AsUnaryOp();
|
auto* u = e.value->AsUnaryOp();
|
||||||
ASSERT_EQ(u->op(), ast::UnaryOp::kNegation);
|
ASSERT_EQ(u->op(), ast::UnaryOp::kNegation);
|
||||||
|
|
||||||
ASSERT_TRUE(u->expr()->IsConstructor());
|
ASSERT_TRUE(u->expr()->IsConstructor());
|
||||||
|
@ -66,19 +70,23 @@ TEST_F(ParserImplTest, UnaryExpression_Minus) {
|
||||||
TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
|
TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
|
||||||
auto* p = parser("-if(a) {}");
|
auto* p = parser("-if(a) {}");
|
||||||
auto e = p->unary_expression();
|
auto e = p->unary_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of - expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse right side of - expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, UnaryExpression_Bang) {
|
TEST_F(ParserImplTest, UnaryExpression_Bang) {
|
||||||
auto* p = parser("!1");
|
auto* p = parser("!1");
|
||||||
auto e = p->unary_expression();
|
auto e = p->unary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsUnaryOp());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsUnaryOp());
|
||||||
|
|
||||||
auto* u = e->AsUnaryOp();
|
auto* u = e.value->AsUnaryOp();
|
||||||
ASSERT_EQ(u->op(), ast::UnaryOp::kNot);
|
ASSERT_EQ(u->op(), ast::UnaryOp::kNot);
|
||||||
|
|
||||||
ASSERT_TRUE(u->expr()->IsConstructor());
|
ASSERT_TRUE(u->expr()->IsConstructor());
|
||||||
|
@ -92,8 +100,10 @@ TEST_F(ParserImplTest, UnaryExpression_Bang) {
|
||||||
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
|
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
|
||||||
auto* p = parser("!if (a) {}");
|
auto* p = parser("!if (a) {}");
|
||||||
auto e = p->unary_expression();
|
auto e = p->unary_expression();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,23 +25,27 @@ namespace {
|
||||||
TEST_F(ParserImplTest, VariableDecl_Parses) {
|
TEST_F(ParserImplTest, VariableDecl_Parses) {
|
||||||
auto* p = parser("var my_var : f32");
|
auto* p = parser("var my_var : f32");
|
||||||
auto var = p->variable_decl();
|
auto var = p->variable_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_NE(var, nullptr);
|
EXPECT_TRUE(var.matched);
|
||||||
ASSERT_EQ(var->name(), "my_var");
|
EXPECT_FALSE(var.errored);
|
||||||
ASSERT_NE(var->type(), nullptr);
|
ASSERT_NE(var.value, nullptr);
|
||||||
ASSERT_TRUE(var->type()->IsF32());
|
EXPECT_EQ(var.value->name(), "my_var");
|
||||||
|
EXPECT_NE(var.value->type(), nullptr);
|
||||||
|
EXPECT_TRUE(var.value->type()->IsF32());
|
||||||
|
|
||||||
ASSERT_EQ(var->source().range.begin.line, 1u);
|
EXPECT_EQ(var.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(var->source().range.begin.column, 5u);
|
EXPECT_EQ(var.value->source().range.begin.column, 5u);
|
||||||
ASSERT_EQ(var->source().range.end.line, 1u);
|
EXPECT_EQ(var.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(var->source().range.end.column, 11u);
|
EXPECT_EQ(var.value->source().range.end.column, 11u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecl_MissingVar) {
|
TEST_F(ParserImplTest, VariableDecl_MissingVar) {
|
||||||
auto* p = parser("my_var : f32");
|
auto* p = parser("my_var : f32");
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
ASSERT_EQ(v, nullptr);
|
EXPECT_EQ(v.value, nullptr);
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(v.matched);
|
||||||
|
EXPECT_FALSE(v.errored);
|
||||||
|
EXPECT_FALSE(p->has_error());
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
ASSERT_TRUE(t.IsIdentifier());
|
ASSERT_TRUE(t.IsIdentifier());
|
||||||
|
@ -50,31 +54,37 @@ TEST_F(ParserImplTest, VariableDecl_MissingVar) {
|
||||||
TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
|
TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
|
||||||
auto* p = parser("var my_var f32");
|
auto* p = parser("var my_var f32");
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(v.matched);
|
||||||
ASSERT_EQ(v, nullptr);
|
EXPECT_TRUE(v.errored);
|
||||||
ASSERT_EQ(p->error(), "1:12: expected ':' for variable declaration");
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(v.value, nullptr);
|
||||||
|
EXPECT_EQ(p->error(), "1:12: expected ':' for variable declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
||||||
auto* p = parser("var<private> my_var : f32");
|
auto* p = parser("var<private> my_var : f32");
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_TRUE(v.matched);
|
||||||
ASSERT_NE(v, nullptr);
|
EXPECT_FALSE(v.errored);
|
||||||
EXPECT_EQ(v->name(), "my_var");
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_TRUE(v->type()->IsF32());
|
ASSERT_NE(v.value, nullptr);
|
||||||
EXPECT_EQ(v->storage_class(), ast::StorageClass::kPrivate);
|
EXPECT_EQ(v.value->name(), "my_var");
|
||||||
|
EXPECT_TRUE(v.value->type()->IsF32());
|
||||||
|
EXPECT_EQ(v.value->storage_class(), ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
EXPECT_EQ(v->source().range.begin.line, 1u);
|
EXPECT_EQ(v.value->source().range.begin.line, 1u);
|
||||||
EXPECT_EQ(v->source().range.begin.column, 14u);
|
EXPECT_EQ(v.value->source().range.begin.column, 14u);
|
||||||
EXPECT_EQ(v->source().range.end.line, 1u);
|
EXPECT_EQ(v.value->source().range.end.line, 1u);
|
||||||
EXPECT_EQ(v->source().range.end.column, 20u);
|
EXPECT_EQ(v.value->source().range.end.column, 20u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecl_InvalidStorageClass) {
|
TEST_F(ParserImplTest, VariableDecl_InvalidStorageClass) {
|
||||||
auto* p = parser("var<unknown> my_var : f32");
|
auto* p = parser("var<unknown> my_var : f32");
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(v.matched);
|
||||||
ASSERT_EQ(v, nullptr);
|
EXPECT_TRUE(v.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(v.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,12 @@ TEST_F(ParserImplTest, VariableDecorationList_Parses) {
|
||||||
auto* p = parser(R"([[location(4), builtin(position)]])");
|
auto* p = parser(R"([[location(4), builtin(position)]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(decos.size(), 2u);
|
ASSERT_FALSE(decos.errored);
|
||||||
|
ASSERT_TRUE(decos.matched);
|
||||||
|
ASSERT_EQ(decos.value.size(), 2u);
|
||||||
|
|
||||||
auto deco_0 = ast::As<ast::VariableDecoration>(std::move(decos[0]));
|
auto deco_0 = ast::As<ast::VariableDecoration>(std::move(decos.value[0]));
|
||||||
auto deco_1 = ast::As<ast::VariableDecoration>(std::move(decos[1]));
|
auto deco_1 = ast::As<ast::VariableDecoration>(std::move(decos.value[1]));
|
||||||
ASSERT_NE(deco_0, nullptr);
|
ASSERT_NE(deco_0, nullptr);
|
||||||
ASSERT_NE(deco_1, nullptr);
|
ASSERT_NE(deco_1, nullptr);
|
||||||
|
|
||||||
|
@ -43,44 +45,62 @@ TEST_F(ParserImplTest, VariableDecorationList_Parses) {
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_Empty) {
|
TEST_F(ParserImplTest, VariableDecorationList_Empty) {
|
||||||
auto* p = parser(R"([[]])");
|
auto* p = parser(R"([[]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:3: empty decoration list");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:3: empty decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_Invalid) {
|
TEST_F(ParserImplTest, VariableDecorationList_Invalid) {
|
||||||
auto* p = parser(R"([[invalid]])");
|
auto* p = parser(R"([[invalid]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(decos.empty());
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:3: expected decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_ExtraComma) {
|
TEST_F(ParserImplTest, VariableDecorationList_ExtraComma) {
|
||||||
auto* p = parser(R"([[builtin(position), ]])");
|
auto* p = parser(R"([[builtin(position), ]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:22: expected decoration");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:22: expected decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_MissingComma) {
|
TEST_F(ParserImplTest, VariableDecorationList_MissingComma) {
|
||||||
auto* p = parser(R"([[binding(4) location(5)]])");
|
auto* p = parser(R"([[binding(4) location(5)]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:14: expected ',' for decoration list");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:14: expected ',' for decoration list");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_BadDecoration) {
|
TEST_F(ParserImplTest, VariableDecorationList_BadDecoration) {
|
||||||
auto* p = parser(R"([[location(bad)]])");
|
auto* p = parser(R"([[location(bad)]])");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(),
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(),
|
||||||
"1:12: expected signed integer literal for location decoration");
|
"1:12: expected signed integer literal for location decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecorationList_InvalidBuiltin) {
|
TEST_F(ParserImplTest, VariableDecorationList_InvalidBuiltin) {
|
||||||
auto* p = parser("[[builtin(invalid)]]");
|
auto* p = parser("[[builtin(invalid)]]");
|
||||||
auto decos = p->decoration_list();
|
auto decos = p->decoration_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:11: invalid value for builtin decoration");
|
EXPECT_TRUE(decos.errored);
|
||||||
|
EXPECT_FALSE(decos.matched);
|
||||||
|
EXPECT_TRUE(decos.value.empty());
|
||||||
|
EXPECT_EQ(p->error(), "1:11: invalid value for builtin decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,8 +28,10 @@ namespace {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Location) {
|
TEST_F(ParserImplTest, VariableDecoration_Location) {
|
||||||
auto* p = parser("location(4)");
|
auto* p = parser("location(4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
|
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(var_deco, nullptr);
|
ASSERT_NE(var_deco, nullptr);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(var_deco->IsLocation());
|
ASSERT_TRUE(var_deco->IsLocation());
|
||||||
|
@ -41,24 +43,30 @@ TEST_F(ParserImplTest, VariableDecoration_Location) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingLeftParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Location_MissingLeftParen) {
|
||||||
auto* p = parser("location 4)");
|
auto* p = parser("location 4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '(' for location decoration");
|
EXPECT_EQ(p->error(), "1:10: expected '(' for location decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingRightParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Location_MissingRightParen) {
|
||||||
auto* p = parser("location(4");
|
auto* p = parser("location(4");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected ')' for location decoration");
|
EXPECT_EQ(p->error(), "1:11: expected ')' for location decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingValue) {
|
TEST_F(ParserImplTest, VariableDecoration_Location_MissingValue) {
|
||||||
auto* p = parser("location()");
|
auto* p = parser("location()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:10: expected signed integer literal for location decoration");
|
"1:10: expected signed integer literal for location decoration");
|
||||||
}
|
}
|
||||||
|
@ -66,8 +74,10 @@ TEST_F(ParserImplTest, VariableDecoration_Location_MissingValue) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingInvalid) {
|
TEST_F(ParserImplTest, VariableDecoration_Location_MissingInvalid) {
|
||||||
auto* p = parser("location(nan)");
|
auto* p = parser("location(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:10: expected signed integer literal for location decoration");
|
"1:10: expected signed integer literal for location decoration");
|
||||||
}
|
}
|
||||||
|
@ -88,8 +98,10 @@ TEST_P(BuiltinTest, VariableDecoration_Builtin) {
|
||||||
auto* p = parser(std::string("builtin(") + params.input + ")");
|
auto* p = parser(std::string("builtin(") + params.input + ")");
|
||||||
|
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
|
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(var_deco, nullptr);
|
ASSERT_NE(var_deco, nullptr);
|
||||||
ASSERT_TRUE(var_deco->IsBuiltin());
|
ASSERT_TRUE(var_deco->IsBuiltin());
|
||||||
|
@ -115,48 +127,60 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingLeftParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingLeftParen) {
|
||||||
auto* p = parser("builtin position)");
|
auto* p = parser("builtin position)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected '(' for builtin decoration");
|
EXPECT_EQ(p->error(), "1:9: expected '(' for builtin decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingRightParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingRightParen) {
|
||||||
auto* p = parser("builtin(position");
|
auto* p = parser("builtin(position");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:17: expected ')' for builtin decoration");
|
EXPECT_EQ(p->error(), "1:17: expected ')' for builtin decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
|
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
|
||||||
auto* p = parser("builtin()");
|
auto* p = parser("builtin()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
|
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_InvalidValue) {
|
TEST_F(ParserImplTest, VariableDecoration_Builtin_InvalidValue) {
|
||||||
auto* p = parser("builtin(other_thingy)");
|
auto* p = parser("builtin(other_thingy)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
|
EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
|
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
|
||||||
auto* p = parser("builtin(3)");
|
auto* p = parser("builtin(3)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
|
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Binding) {
|
TEST_F(ParserImplTest, VariableDecoration_Binding) {
|
||||||
auto* p = parser("binding(4)");
|
auto* p = parser("binding(4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
|
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
|
||||||
ASSERT_NE(var_deco, nullptr);
|
ASSERT_NE(var_deco, nullptr);
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_TRUE(var_deco->IsBinding());
|
ASSERT_TRUE(var_deco->IsBinding());
|
||||||
|
@ -168,24 +192,30 @@ TEST_F(ParserImplTest, VariableDecoration_Binding) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingLeftParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingLeftParen) {
|
||||||
auto* p = parser("binding 4)");
|
auto* p = parser("binding 4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected '(' for binding decoration");
|
EXPECT_EQ(p->error(), "1:9: expected '(' for binding decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingRightParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingRightParen) {
|
||||||
auto* p = parser("binding(4");
|
auto* p = parser("binding(4");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected ')' for binding decoration");
|
EXPECT_EQ(p->error(), "1:10: expected ')' for binding decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingValue) {
|
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingValue) {
|
||||||
auto* p = parser("binding()");
|
auto* p = parser("binding()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:9: expected signed integer literal for binding decoration");
|
"1:9: expected signed integer literal for binding decoration");
|
||||||
}
|
}
|
||||||
|
@ -193,8 +223,10 @@ TEST_F(ParserImplTest, VariableDecoration_Binding_MissingValue) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingInvalid) {
|
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingInvalid) {
|
||||||
auto* p = parser("binding(nan)");
|
auto* p = parser("binding(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:9: expected signed integer literal for binding decoration");
|
"1:9: expected signed integer literal for binding decoration");
|
||||||
}
|
}
|
||||||
|
@ -202,8 +234,10 @@ TEST_F(ParserImplTest, VariableDecoration_Binding_MissingInvalid) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_set) {
|
TEST_F(ParserImplTest, VariableDecoration_set) {
|
||||||
auto* p = parser("set(4)");
|
auto* p = parser("set(4)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_NE(deco, nullptr);
|
EXPECT_TRUE(deco.matched);
|
||||||
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
|
EXPECT_FALSE(deco.errored);
|
||||||
|
ASSERT_NE(deco.value, nullptr);
|
||||||
|
auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_NE(var_deco.get(), nullptr);
|
ASSERT_NE(var_deco.get(), nullptr);
|
||||||
ASSERT_TRUE(var_deco->IsSet());
|
ASSERT_TRUE(var_deco->IsSet());
|
||||||
|
@ -215,24 +249,30 @@ TEST_F(ParserImplTest, VariableDecoration_set) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingLeftParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Set_MissingLeftParen) {
|
||||||
auto* p = parser("set 2)");
|
auto* p = parser("set 2)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:5: expected '(' for set decoration");
|
EXPECT_EQ(p->error(), "1:5: expected '(' for set decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingRightParen) {
|
TEST_F(ParserImplTest, VariableDecoration_Set_MissingRightParen) {
|
||||||
auto* p = parser("set(2");
|
auto* p = parser("set(2");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: expected ')' for set decoration");
|
EXPECT_EQ(p->error(), "1:6: expected ')' for set decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingValue) {
|
TEST_F(ParserImplTest, VariableDecoration_Set_MissingValue) {
|
||||||
auto* p = parser("set()");
|
auto* p = parser("set()");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:5: expected signed integer literal for set decoration");
|
"1:5: expected signed integer literal for set decoration");
|
||||||
}
|
}
|
||||||
|
@ -240,8 +280,10 @@ TEST_F(ParserImplTest, VariableDecoration_Set_MissingValue) {
|
||||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingInvalid) {
|
TEST_F(ParserImplTest, VariableDecoration_Set_MissingInvalid) {
|
||||||
auto* p = parser("set(nan)");
|
auto* p = parser("set(nan)");
|
||||||
auto deco = p->decoration();
|
auto deco = p->decoration();
|
||||||
ASSERT_EQ(deco, nullptr);
|
EXPECT_FALSE(deco.matched);
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(deco.errored);
|
||||||
|
EXPECT_EQ(deco.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(),
|
EXPECT_EQ(p->error(),
|
||||||
"1:5: expected signed integer literal for set decoration");
|
"1:5: expected signed integer literal for set decoration");
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,96 +26,114 @@ namespace {
|
||||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
|
TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
|
||||||
auto* p = parser("var a : i32;");
|
auto* p = parser("var a : i32;");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e->variable(), nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_EQ(e->variable()->name(), "a");
|
ASSERT_TRUE(e.value->IsVariableDecl());
|
||||||
|
ASSERT_NE(e.value->variable(), nullptr);
|
||||||
|
EXPECT_EQ(e.value->variable()->name(), "a");
|
||||||
|
|
||||||
ASSERT_EQ(e->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.begin.column, 5u);
|
ASSERT_EQ(e.value->source().range.begin.column, 5u);
|
||||||
ASSERT_EQ(e->source().range.end.line, 1u);
|
ASSERT_EQ(e.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.end.column, 6u);
|
ASSERT_EQ(e.value->source().range.end.column, 6u);
|
||||||
|
|
||||||
EXPECT_EQ(e->variable()->constructor(), nullptr);
|
EXPECT_EQ(e.value->variable()->constructor(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
|
TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
|
||||||
auto* p = parser("var a : i32 = 1;");
|
auto* p = parser("var a : i32 = 1;");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e->variable(), nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_EQ(e->variable()->name(), "a");
|
ASSERT_TRUE(e.value->IsVariableDecl());
|
||||||
|
ASSERT_NE(e.value->variable(), nullptr);
|
||||||
|
EXPECT_EQ(e.value->variable()->name(), "a");
|
||||||
|
|
||||||
ASSERT_EQ(e->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.begin.column, 5u);
|
ASSERT_EQ(e.value->source().range.begin.column, 5u);
|
||||||
ASSERT_EQ(e->source().range.end.line, 1u);
|
ASSERT_EQ(e.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.end.column, 6u);
|
ASSERT_EQ(e.value->source().range.end.column, 6u);
|
||||||
|
|
||||||
ASSERT_NE(e->variable()->constructor(), nullptr);
|
ASSERT_NE(e.value->variable()->constructor(), nullptr);
|
||||||
EXPECT_TRUE(e->variable()->constructor()->IsConstructor());
|
EXPECT_TRUE(e.value->variable()->constructor()->IsConstructor());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {
|
TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {
|
||||||
auto* p = parser("var a : invalid;");
|
auto* p = parser("var a : invalid;");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_ConstructorInvalid) {
|
TEST_F(ParserImplTest, VariableStmt_VariableDecl_ConstructorInvalid) {
|
||||||
auto* p = parser("var a : i32 = if(a) {}");
|
auto* p = parser("var a : i32 = if(a) {}");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:15: missing constructor for variable declaration");
|
EXPECT_EQ(p->error(), "1:15: missing constructor for variable declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const) {
|
TEST_F(ParserImplTest, VariableStmt_Const) {
|
||||||
auto* p = parser("const a : i32 = 1");
|
auto* p = parser("const a : i32 = 1");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_NE(e, nullptr);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e.value->IsVariableDecl());
|
||||||
|
|
||||||
ASSERT_EQ(e->source().range.begin.line, 1u);
|
ASSERT_EQ(e.value->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.begin.column, 7u);
|
ASSERT_EQ(e.value->source().range.begin.column, 7u);
|
||||||
ASSERT_EQ(e->source().range.end.line, 1u);
|
ASSERT_EQ(e.value->source().range.end.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.end.column, 8u);
|
ASSERT_EQ(e.value->source().range.end.column, 8u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const_InvalidVarIdent) {
|
TEST_F(ParserImplTest, VariableStmt_Const_InvalidVarIdent) {
|
||||||
auto* p = parser("const a : invalid = 1");
|
auto* p = parser("const a : invalid = 1");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:11: unknown constructed type 'invalid'");
|
EXPECT_EQ(p->error(), "1:11: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const_MissingEqual) {
|
TEST_F(ParserImplTest, VariableStmt_Const_MissingEqual) {
|
||||||
auto* p = parser("const a : i32 1");
|
auto* p = parser("const a : i32 1");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:15: expected '=' for constant declaration");
|
EXPECT_EQ(p->error(), "1:15: expected '=' for constant declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const_MissingConstructor) {
|
TEST_F(ParserImplTest, VariableStmt_Const_MissingConstructor) {
|
||||||
auto* p = parser("const a : i32 =");
|
auto* p = parser("const a : i32 =");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: missing constructor for const declaration");
|
EXPECT_EQ(p->error(), "1:16: missing constructor for const declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const_InvalidConstructor) {
|
TEST_F(ParserImplTest, VariableStmt_Const_InvalidConstructor) {
|
||||||
auto* p = parser("const a : i32 = if (a) {}");
|
auto* p = parser("const a : i32 = if (a) {}");
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_FALSE(e.matched);
|
||||||
ASSERT_EQ(e, nullptr);
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_EQ(e.value, nullptr);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:17: missing constructor for const declaration");
|
EXPECT_EQ(p->error(), "1:17: missing constructor for const declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,10 @@ TEST_P(VariableStorageTest, Parses) {
|
||||||
auto* p = parser(std::string("<") + params.input + ">");
|
auto* p = parser(std::string("<") + params.input + ">");
|
||||||
|
|
||||||
auto sc = p->variable_storage_decoration();
|
auto sc = p->variable_storage_decoration();
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(sc, params.result);
|
EXPECT_FALSE(sc.errored);
|
||||||
|
EXPECT_TRUE(sc.matched);
|
||||||
|
EXPECT_EQ(sc.value, params.result);
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
EXPECT_TRUE(t.IsEof());
|
EXPECT_TRUE(t.IsEof());
|
||||||
|
@ -64,24 +66,27 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TEST_F(ParserImplTest, VariableStorageDecoration_NoMatch) {
|
TEST_F(ParserImplTest, VariableStorageDecoration_NoMatch) {
|
||||||
auto* p = parser("<not-a-storage-class>");
|
auto* p = parser("<not-a-storage-class>");
|
||||||
auto sc = p->variable_storage_decoration();
|
auto sc = p->variable_storage_decoration();
|
||||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(sc.errored);
|
||||||
ASSERT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
EXPECT_FALSE(sc.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStorageDecoration_Empty) {
|
TEST_F(ParserImplTest, VariableStorageDecoration_Empty) {
|
||||||
auto* p = parser("<>");
|
auto* p = parser("<>");
|
||||||
auto sc = p->variable_storage_decoration();
|
auto sc = p->variable_storage_decoration();
|
||||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(sc.errored);
|
||||||
ASSERT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
EXPECT_FALSE(sc.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStorageDecoration_MissingLessThan) {
|
TEST_F(ParserImplTest, VariableStorageDecoration_MissingLessThan) {
|
||||||
auto* p = parser("in>");
|
auto* p = parser("in>");
|
||||||
auto sc = p->variable_storage_decoration();
|
auto sc = p->variable_storage_decoration();
|
||||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
EXPECT_FALSE(p->has_error());
|
||||||
ASSERT_FALSE(p->has_error());
|
EXPECT_FALSE(sc.errored);
|
||||||
|
EXPECT_FALSE(sc.matched);
|
||||||
|
|
||||||
auto t = p->next();
|
auto t = p->next();
|
||||||
ASSERT_TRUE(t.IsIn());
|
ASSERT_TRUE(t.IsIn());
|
||||||
|
@ -90,9 +95,10 @@ TEST_F(ParserImplTest, VariableStorageDecoration_MissingLessThan) {
|
||||||
TEST_F(ParserImplTest, VariableStorageDecoration_MissingGreaterThan) {
|
TEST_F(ParserImplTest, VariableStorageDecoration_MissingGreaterThan) {
|
||||||
auto* p = parser("<in");
|
auto* p = parser("<in");
|
||||||
auto sc = p->variable_storage_decoration();
|
auto sc = p->variable_storage_decoration();
|
||||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
EXPECT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(p->has_error());
|
EXPECT_TRUE(sc.errored);
|
||||||
ASSERT_EQ(p->error(), "1:4: expected '>' for variable decoration");
|
EXPECT_FALSE(sc.matched);
|
||||||
|
EXPECT_EQ(p->error(), "1:4: expected '>' for variable decoration");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue