Add `element_count_expression` to WGSL parser
This CL adds the `element_count_expression` and the requisite math expression parsing to support along with tests. Bug: tint:1633 Change-Id: I54ab37339754217f417f69dcd6140adbc14cbf83 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/99560 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
5d7de871b4
commit
2788becd09
|
@ -1364,6 +1364,7 @@ if (tint_build_unittests) {
|
|||
"reader/wgsl/parser_impl_continuing_stmt_test.cc",
|
||||
"reader/wgsl/parser_impl_core_lhs_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_depth_texture_test.cc",
|
||||
"reader/wgsl/parser_impl_element_count_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_enable_directive_test.cc",
|
||||
"reader/wgsl/parser_impl_equality_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_error_msg_test.cc",
|
||||
|
@ -1385,6 +1386,7 @@ if (tint_build_unittests) {
|
|||
"reader/wgsl/parser_impl_logical_and_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_logical_or_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_loop_stmt_test.cc",
|
||||
"reader/wgsl/parser_impl_math_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_multiplicative_expression_test.cc",
|
||||
"reader/wgsl/parser_impl_param_list_test.cc",
|
||||
"reader/wgsl/parser_impl_paren_expression_test.cc",
|
||||
|
|
|
@ -959,6 +959,7 @@ if(TINT_BUILD_TESTS)
|
|||
reader/wgsl/parser_impl_continuing_stmt_test.cc
|
||||
reader/wgsl/parser_impl_core_lhs_expression_test.cc
|
||||
reader/wgsl/parser_impl_depth_texture_test.cc
|
||||
reader/wgsl/parser_impl_element_count_expression_test.cc
|
||||
reader/wgsl/parser_impl_enable_directive_test.cc
|
||||
reader/wgsl/parser_impl_external_texture_test.cc
|
||||
reader/wgsl/parser_impl_equality_expression_test.cc
|
||||
|
@ -980,6 +981,7 @@ if(TINT_BUILD_TESTS)
|
|||
reader/wgsl/parser_impl_logical_and_expression_test.cc
|
||||
reader/wgsl/parser_impl_logical_or_expression_test.cc
|
||||
reader/wgsl/parser_impl_loop_stmt_test.cc
|
||||
reader/wgsl/parser_impl_math_expression_test.cc
|
||||
reader/wgsl/parser_impl_multiplicative_expression_test.cc
|
||||
reader/wgsl/parser_impl_param_list_test.cc
|
||||
reader/wgsl/parser_impl_paren_expression_test.cc
|
||||
|
|
|
@ -1028,7 +1028,6 @@ INSTANTIATE_TEST_SUITE_P(LexerTest,
|
|||
TokenData{"%", Token::Type::kMod},
|
||||
TokenData{"!=", Token::Type::kNotEqual},
|
||||
TokenData{"-", Token::Type::kMinus},
|
||||
TokenData{"--", Token::Type::kMinusMinus},
|
||||
TokenData{".", Token::Type::kPeriod},
|
||||
TokenData{"+", Token::Type::kPlus},
|
||||
TokenData{"++", Token::Type::kPlusPlus},
|
||||
|
@ -1088,6 +1087,7 @@ INSTANTIATE_TEST_SUITE_P(LexerTest,
|
|||
SplittablePunctuationTest,
|
||||
testing::Values(TokenData{"&&", Token::Type::kAndAnd},
|
||||
TokenData{">=", Token::Type::kGreaterThanEqual},
|
||||
TokenData{"--", Token::Type::kMinusMinus},
|
||||
TokenData{">>", Token::Type::kShiftRight}));
|
||||
|
||||
using KeywordTest = testing::TestWithParam<TokenData>;
|
||||
|
|
|
@ -1066,7 +1066,7 @@ Maybe<const ast::Alias*> ParserImpl::type_alias_decl() {
|
|||
// | VEC3 LESS_THAN type_decl GREATER_THAN
|
||||
// | VEC4 LESS_THAN type_decl GREATER_THAN
|
||||
// | PTR LESS_THAN storage_class, type_decl (COMMA access_mode)? GREATER_THAN
|
||||
// | array_attribute_list* ARRAY LESS_THAN type_decl COMMA INT_LITERAL GREATER_THAN
|
||||
// | array_attribute_list* ARRAY LESS_THAN type_decl COMMA element_count_expression GREATER_THAN
|
||||
// | array_attribute_list* ARRAY LESS_THAN type_decl GREATER_THAN
|
||||
// | MAT2x2 LESS_THAN type_decl GREATER_THAN
|
||||
// | MAT2x3 LESS_THAN type_decl GREATER_THAN
|
||||
|
@ -1244,10 +1244,11 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_array(const Token& t) {
|
|||
return TypeAndSize{type.value, nullptr};
|
||||
}
|
||||
|
||||
auto size = primary_expression();
|
||||
auto size = element_count_expression();
|
||||
if (size.errored) {
|
||||
return Failure::kErrored;
|
||||
} else if (!size.matched) {
|
||||
}
|
||||
if (!size.matched) {
|
||||
return add_error(peek(), "expected array size expression");
|
||||
}
|
||||
|
||||
|
@ -2657,6 +2658,162 @@ Maybe<const ast::Expression*> ParserImpl::bitwise_expression_post_unary_expressi
|
|||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
// multiplicative_operator
|
||||
// : FORWARD_SLASH
|
||||
// | MODULO
|
||||
// | STAR
|
||||
Maybe<ast::BinaryOp> ParserImpl::multiplicative_operator() {
|
||||
if (match(Token::Type::kForwardSlash)) {
|
||||
return ast::BinaryOp::kDivide;
|
||||
}
|
||||
if (match(Token::Type::kMod)) {
|
||||
return ast::BinaryOp::kModulo;
|
||||
}
|
||||
if (match(Token::Type::kStar)) {
|
||||
return ast::BinaryOp::kMultiply;
|
||||
}
|
||||
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
||||
// multiplicative_expression.post.unary_expression
|
||||
// : (multiplicative_operator unary_expression)*
|
||||
Expect<const ast::Expression*> ParserImpl::expect_multiplicative_expression_post_unary_expression(
|
||||
const ast::Expression* lhs) {
|
||||
while (continue_parsing()) {
|
||||
auto& t = peek();
|
||||
|
||||
auto op = multiplicative_operator();
|
||||
if (op.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!op.matched) {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
auto rhs = unary_expression();
|
||||
if (rhs.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!rhs.matched) {
|
||||
return add_error(peek(), std::string("unable to parse right side of ") +
|
||||
std::string(t.to_name()) + " expression");
|
||||
}
|
||||
|
||||
lhs = create<ast::BinaryExpression>(t.source(), op.value, lhs, rhs.value);
|
||||
}
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
// additive_operator
|
||||
// : MINUS
|
||||
// | PLUS
|
||||
//
|
||||
// Note, this also splits a `--` token. This is currently safe as the only way to get into
|
||||
// here is through additive expression and rules for where `--` are allowed are very restrictive.
|
||||
Maybe<ast::BinaryOp> ParserImpl::additive_operator() {
|
||||
if (match(Token::Type::kPlus)) {
|
||||
return ast::BinaryOp::kAdd;
|
||||
}
|
||||
|
||||
auto& t = peek();
|
||||
if (t.Is(Token::Type::kMinusMinus)) {
|
||||
next();
|
||||
split_token(Token::Type::kMinus, Token::Type::kMinus);
|
||||
} else if (t.Is(Token::Type::kMinus)) {
|
||||
next();
|
||||
} else {
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
||||
return ast::BinaryOp::kSubtract;
|
||||
}
|
||||
|
||||
// additive_expression.pos.unary_expression
|
||||
// : (additive_operator unary_expression expect_multiplicative_expression.post.unary_expression)*
|
||||
//
|
||||
// This is `( additive_operator unary_expression ( multiplicative_operator unary_expression )* )*`
|
||||
// split apart.
|
||||
Expect<const ast::Expression*> ParserImpl::expect_additive_expression_post_unary_expression(
|
||||
const ast::Expression* lhs) {
|
||||
while (continue_parsing()) {
|
||||
auto& t = peek();
|
||||
|
||||
auto op = additive_operator();
|
||||
if (op.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!op.matched) {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
auto unary = unary_expression();
|
||||
if (unary.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!unary.matched) {
|
||||
return add_error(peek(), std::string("unable to parse right side of ") +
|
||||
std::string(t.to_name()) + " expression");
|
||||
}
|
||||
|
||||
// The multiplicative binds tigher, so pass the unary into that and build that expression
|
||||
// before creating the additve expression.
|
||||
auto rhs = expect_multiplicative_expression_post_unary_expression(unary.value);
|
||||
if (rhs.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
lhs = create<ast::BinaryExpression>(t.source(), op.value, lhs, rhs.value);
|
||||
}
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
// math_expression.post.unary_expression
|
||||
// : multiplicative_expression.post.unary_expression additive_expression.post.unary_expression
|
||||
//
|
||||
// This is `( multiplicative_operator unary_expression )* ( additive_operator unary_expression (
|
||||
// multiplicative_operator unary_expression )* )*` split apart.
|
||||
Expect<const ast::Expression*> ParserImpl::expect_math_expression_post_unary_expression(
|
||||
const ast::Expression* lhs) {
|
||||
auto rhs = expect_multiplicative_expression_post_unary_expression(lhs);
|
||||
if (rhs.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
return expect_additive_expression_post_unary_expression(rhs.value);
|
||||
}
|
||||
|
||||
// element_count_expression
|
||||
// : unary_expression math_expression.post.unary_expression
|
||||
// | unary_expression bitwise_expression.post.unary_expression
|
||||
//
|
||||
// Note, this moves the `( multiplicative_operator unary_expression )* ( additive_operator
|
||||
// unary_expression ( multiplicative_operator unary_expression )* )*` expression for the first
|
||||
// branch out into helper methods.
|
||||
Maybe<const ast::Expression*> ParserImpl::element_count_expression() {
|
||||
auto lhs = unary_expression();
|
||||
if (lhs.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!lhs.matched) {
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
||||
auto bitwise = bitwise_expression_post_unary_expression(lhs.value);
|
||||
if (bitwise.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (bitwise.matched) {
|
||||
return bitwise.value;
|
||||
}
|
||||
|
||||
auto math = expect_math_expression_post_unary_expression(lhs.value);
|
||||
if (math.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return math.value;
|
||||
}
|
||||
|
||||
// unary_expression
|
||||
// : singular_expression
|
||||
// | MINUS unary_expression
|
||||
|
|
|
@ -646,6 +646,30 @@ class ParserImpl {
|
|||
/// @returns the parsed expression or nullptr
|
||||
Maybe<const ast::Expression*> bitwise_expression_post_unary_expression(
|
||||
const ast::Expression* lhs);
|
||||
/// Parse the `multiplicative_operator` grammar element
|
||||
/// @returns the parsed operator if successful
|
||||
Maybe<ast::BinaryOp> multiplicative_operator();
|
||||
/// Parses multiplicative elements
|
||||
/// @param lhs the left side of the expression
|
||||
/// @returns the parsed expression or `lhs` if no match
|
||||
Expect<const ast::Expression*> expect_multiplicative_expression_post_unary_expression(
|
||||
const ast::Expression* lhs);
|
||||
/// Parses additive elements
|
||||
/// @param lhs the left side of the expression
|
||||
/// @returns the parsed expression or `lhs` if no match
|
||||
Expect<const ast::Expression*> expect_additive_expression_post_unary_expression(
|
||||
const ast::Expression* lhs);
|
||||
/// Parses math elements
|
||||
/// @param lhs the left side of the expression
|
||||
/// @returns the parsed expression or `lhs` if no match
|
||||
Expect<const ast::Expression*> expect_math_expression_post_unary_expression(
|
||||
const ast::Expression* lhs);
|
||||
/// Parses an `element_count_expression` grammar element
|
||||
/// @returns the parsed expression or nullptr
|
||||
Maybe<const ast::Expression*> element_count_expression();
|
||||
/// Parse the `additive_operator` grammar element
|
||||
/// @returns the parsed operator if successful
|
||||
Maybe<ast::BinaryOp> additive_operator();
|
||||
/// Parses the recursive part of the `and_expression`, erroring on parse
|
||||
/// failure.
|
||||
/// @param lhs the left side of the expression
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Orig_Parses_Plus) {
|
||||
auto p = parser("a + true");
|
||||
auto e = p->additive_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
|||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Orig_Parses_Minus) {
|
||||
auto p = parser("a - true");
|
||||
auto e = p->additive_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -62,7 +62,7 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
|||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Orig_InvalidLHS) {
|
||||
auto p = parser("if (a) {} + true");
|
||||
auto e = p->additive_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
|
@ -71,7 +71,7 @@ TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
|||
EXPECT_EQ(e.value, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Orig_InvalidRHS) {
|
||||
auto p = parser("true + if (a) {}");
|
||||
auto e = p->additive_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
|
@ -81,7 +81,7 @@ TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
|||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of + expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Orig_NoOr_ReturnsLHS) {
|
||||
auto p = parser("a true");
|
||||
auto e = p->additive_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -91,5 +91,189 @@ TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
|||
ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
||||
auto p = parser("a + b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_EQ(e->source.range.begin.line, 1u);
|
||||
EXPECT_EQ(e->source.range.begin.column, 3u);
|
||||
EXPECT_EQ(e->source.range.end.line, 1u);
|
||||
EXPECT_EQ(e->source.range.end.column, 4u);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
||||
auto p = parser("a - b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_MinusMinus) {
|
||||
auto p = parser("a--b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::UnaryOpExpression>());
|
||||
auto* unary = rel->rhs->As<ast::UnaryOpExpression>();
|
||||
EXPECT_EQ(ast::UnaryOp::kNegation, unary->op);
|
||||
|
||||
ASSERT_TRUE(unary->expr->Is<ast::IdentifierExpression>());
|
||||
ident = unary->expr->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_MultipleOps) {
|
||||
auto p = parser("a - b + c - d");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
// lhs: ((a - b) + c
|
||||
// op: -
|
||||
// rhs: d
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a - b
|
||||
// op: +
|
||||
// rhs: c
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a
|
||||
// op: -
|
||||
// rhs: b
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_MultipleOps_MixedMultiplication) {
|
||||
auto p = parser("a - b * c - d");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
// lhs: a - (b * c)
|
||||
// op: -
|
||||
// rhs: d
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a
|
||||
// op: -
|
||||
// rhs: b * c
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::BinaryExpression>());
|
||||
// lhs: b
|
||||
// op: *
|
||||
// rhs: c
|
||||
rel = rel->rhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
||||
auto p = parser("a + if (a) {}");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:5: unable to parse right side of + expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_NoMatch_ReturnsLHS) {
|
||||
auto p = parser("a true");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_additive_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
EXPECT_EQ(lhs.value, e.value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::reader::wgsl
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, ElementCountExpression_Math) {
|
||||
auto p = parser("a * b");
|
||||
auto e = p->element_count_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElementCountExpression_Bitwise) {
|
||||
auto p = parser("a | true");
|
||||
auto e = p->element_count_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
|
||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElementCountExpression_NoMatch) {
|
||||
auto p = parser("if (a) { }");
|
||||
auto e = p->element_count_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElementCountExpression_InvalidRHS) {
|
||||
auto p = parser("a * if");
|
||||
auto e = p->element_count_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ("1:5: unable to parse right side of * expression", p->error());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::reader::wgsl
|
|
@ -937,9 +937,9 @@ var i : array<u32, >;
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayInvalidSize) {
|
||||
EXPECT("var i : array<u32, !>;",
|
||||
R"(test.wgsl:1:20 error: expected array size expression
|
||||
R"(test.wgsl:1:21 error: unable to parse right side of ! expression
|
||||
var i : array<u32, !>;
|
||||
^
|
||||
^
|
||||
)");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_Parses_Multiplicative) {
|
||||
auto p = parser("a * b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_Parses_Mixed_MultiplicativeStart) {
|
||||
auto p = parser("a * b + c");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
// lhs: a * b
|
||||
// op: +
|
||||
// rhs: c
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a
|
||||
// op: *
|
||||
// rhs: b
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_Parses_Additive) {
|
||||
auto p = parser("a + b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_Parses_Mixed_AdditiveStart) {
|
||||
auto p = parser("a + b * c");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
// lhs: a
|
||||
// op: +
|
||||
// rhs: b * c
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::BinaryExpression>());
|
||||
// lhs: b
|
||||
// op: *
|
||||
// rhs: c
|
||||
rel = rel->rhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_NoMatch_ReturnLHS) {
|
||||
auto p = parser("a if");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
EXPECT_EQ(lhs.value, e.value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MathExpression_InvalidRHS) {
|
||||
auto p = parser("a * if");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_math_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ("1:5: unable to parse right side of * expression", p->error());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::reader::wgsl
|
|
@ -17,7 +17,7 @@
|
|||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_Parses_Multiply) {
|
||||
auto p = parser("a * true");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
|||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_Parses_Divide) {
|
||||
auto p = parser("a / true");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -62,7 +62,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
|||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_Parses_Modulo) {
|
||||
auto p = parser("a % true");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -82,7 +82,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
|||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_InvalidLHS) {
|
||||
auto p = parser("if (a) {} * true");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
|
@ -91,7 +91,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
|||
EXPECT_EQ(e.value, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_InvalidRHS) {
|
||||
auto p = parser("true * if (a) {}");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_FALSE(e.matched);
|
||||
|
@ -101,7 +101,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
|||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of * expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_NoOr_ReturnsLHS) {
|
||||
auto p = parser("a true");
|
||||
auto e = p->multiplicative_expression();
|
||||
EXPECT_TRUE(e.matched);
|
||||
|
@ -111,5 +111,170 @@ TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
|||
ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
||||
auto p = parser("a * b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply_UnaryIndirect) {
|
||||
auto p = parser("a **b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::UnaryOpExpression>());
|
||||
auto* unary = rel->rhs->As<ast::UnaryOpExpression>();
|
||||
EXPECT_EQ(ast::UnaryOp::kIndirection, unary->op);
|
||||
|
||||
ASSERT_TRUE(unary->expr->Is<ast::IdentifierExpression>());
|
||||
ident = unary->expr->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
||||
auto p = parser("a / b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kDivide, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
||||
auto p = parser("a % b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kModulo, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Grouping) {
|
||||
auto p = parser("a * b / c % d * e");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->Is<ast::BinaryExpression>());
|
||||
// lhs: ((a * b) / c) % d
|
||||
// op: *
|
||||
// rhs: e
|
||||
auto* rel = e->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("e"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: (a * b) / c
|
||||
// op: %
|
||||
// rhs: d
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kModulo, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a * b
|
||||
// op: /
|
||||
// rhs: c
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kDivide, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
|
||||
// lhs: a
|
||||
// op: *
|
||||
// rhs: b
|
||||
rel = rel->lhs->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
|
||||
|
||||
ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
|
||||
|
||||
ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
|
||||
ident = rel->rhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
||||
auto p = parser("a * if (a) {}");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:5: unable to parse right side of * expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_NoMatch_ReturnsLHS) {
|
||||
auto p = parser("a + b");
|
||||
auto lhs = p->unary_expression();
|
||||
auto e = p->expect_multiplicative_expression_post_unary_expression(lhs.value);
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
EXPECT_EQ(lhs.value, e.value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::reader::wgsl
|
||||
|
|
|
@ -469,6 +469,33 @@ TEST_F(ParserImplTest, TypeDecl_Array_ConstantSize) {
|
|||
EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->symbol), "size");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_ExpressionSize) {
|
||||
auto p = parser("array<f32, size + 2>");
|
||||
auto t = p->type_decl();
|
||||
EXPECT_TRUE(t.matched);
|
||||
EXPECT_FALSE(t.errored);
|
||||
ASSERT_NE(t.value, nullptr) << p->error();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(t.value->Is<ast::Array>());
|
||||
|
||||
auto* a = t.value->As<ast::Array>();
|
||||
ASSERT_FALSE(a->IsRuntimeArray());
|
||||
ASSERT_TRUE(a->type->Is<ast::F32>());
|
||||
EXPECT_EQ(a->attributes.Length(), 0u);
|
||||
|
||||
ASSERT_TRUE(a->count->Is<ast::BinaryExpression>());
|
||||
auto* count_expr = a->count->As<ast::BinaryExpression>();
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, count_expr->op);
|
||||
|
||||
ASSERT_TRUE(count_expr->lhs->Is<ast::IdentifierExpression>());
|
||||
auto* ident = count_expr->lhs->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(p->builder().Symbols().NameFor(ident->symbol), "size");
|
||||
|
||||
ASSERT_TRUE(count_expr->rhs->Is<ast::IntLiteralExpression>());
|
||||
auto* val = count_expr->rhs->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(2, static_cast<int32_t>(val->value));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
|
||||
auto p = parser("array<u32>");
|
||||
auto t = p->type_decl();
|
||||
|
@ -524,7 +551,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
|
|||
EXPECT_FALSE(t.matched);
|
||||
ASSERT_EQ(t.value, nullptr);
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:12: expected array size expression");
|
||||
ASSERT_EQ(p->error(), "1:13: unable to parse right side of ! expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingSize) {
|
||||
|
|
|
@ -380,7 +380,7 @@ class Token {
|
|||
/// @returns true if the token can be split during parse into component tokens
|
||||
bool IsSplittable() const {
|
||||
return Is(Token::Type::kShiftRight) || Is(Token::Type::kGreaterThanEqual) ||
|
||||
Is(Token::Type::kAndAnd);
|
||||
Is(Token::Type::kAndAnd) || Is(Token::Type::kMinusMinus);
|
||||
}
|
||||
|
||||
/// @returns the source information for this token
|
||||
|
|
Loading…
Reference in New Issue