mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-16 12:21:35 +00:00
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_continuing_stmt_test.cc",
|
||||||
"reader/wgsl/parser_impl_core_lhs_expression_test.cc",
|
"reader/wgsl/parser_impl_core_lhs_expression_test.cc",
|
||||||
"reader/wgsl/parser_impl_depth_texture_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_enable_directive_test.cc",
|
||||||
"reader/wgsl/parser_impl_equality_expression_test.cc",
|
"reader/wgsl/parser_impl_equality_expression_test.cc",
|
||||||
"reader/wgsl/parser_impl_error_msg_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_and_expression_test.cc",
|
||||||
"reader/wgsl/parser_impl_logical_or_expression_test.cc",
|
"reader/wgsl/parser_impl_logical_or_expression_test.cc",
|
||||||
"reader/wgsl/parser_impl_loop_stmt_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_multiplicative_expression_test.cc",
|
||||||
"reader/wgsl/parser_impl_param_list_test.cc",
|
"reader/wgsl/parser_impl_param_list_test.cc",
|
||||||
"reader/wgsl/parser_impl_paren_expression_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_continuing_stmt_test.cc
|
||||||
reader/wgsl/parser_impl_core_lhs_expression_test.cc
|
reader/wgsl/parser_impl_core_lhs_expression_test.cc
|
||||||
reader/wgsl/parser_impl_depth_texture_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_enable_directive_test.cc
|
||||||
reader/wgsl/parser_impl_external_texture_test.cc
|
reader/wgsl/parser_impl_external_texture_test.cc
|
||||||
reader/wgsl/parser_impl_equality_expression_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_and_expression_test.cc
|
||||||
reader/wgsl/parser_impl_logical_or_expression_test.cc
|
reader/wgsl/parser_impl_logical_or_expression_test.cc
|
||||||
reader/wgsl/parser_impl_loop_stmt_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_multiplicative_expression_test.cc
|
||||||
reader/wgsl/parser_impl_param_list_test.cc
|
reader/wgsl/parser_impl_param_list_test.cc
|
||||||
reader/wgsl/parser_impl_paren_expression_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::kMod},
|
||||||
TokenData{"!=", Token::Type::kNotEqual},
|
TokenData{"!=", Token::Type::kNotEqual},
|
||||||
TokenData{"-", Token::Type::kMinus},
|
TokenData{"-", Token::Type::kMinus},
|
||||||
TokenData{"--", Token::Type::kMinusMinus},
|
|
||||||
TokenData{".", Token::Type::kPeriod},
|
TokenData{".", Token::Type::kPeriod},
|
||||||
TokenData{"+", Token::Type::kPlus},
|
TokenData{"+", Token::Type::kPlus},
|
||||||
TokenData{"++", Token::Type::kPlusPlus},
|
TokenData{"++", Token::Type::kPlusPlus},
|
||||||
@ -1088,6 +1087,7 @@ INSTANTIATE_TEST_SUITE_P(LexerTest,
|
|||||||
SplittablePunctuationTest,
|
SplittablePunctuationTest,
|
||||||
testing::Values(TokenData{"&&", Token::Type::kAndAnd},
|
testing::Values(TokenData{"&&", Token::Type::kAndAnd},
|
||||||
TokenData{">=", Token::Type::kGreaterThanEqual},
|
TokenData{">=", Token::Type::kGreaterThanEqual},
|
||||||
|
TokenData{"--", Token::Type::kMinusMinus},
|
||||||
TokenData{">>", Token::Type::kShiftRight}));
|
TokenData{">>", Token::Type::kShiftRight}));
|
||||||
|
|
||||||
using KeywordTest = testing::TestWithParam<TokenData>;
|
using KeywordTest = testing::TestWithParam<TokenData>;
|
||||||
|
@ -1066,7 +1066,7 @@ Maybe<const ast::Alias*> ParserImpl::type_alias_decl() {
|
|||||||
// | VEC3 LESS_THAN type_decl GREATER_THAN
|
// | VEC3 LESS_THAN type_decl GREATER_THAN
|
||||||
// | VEC4 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
|
// | 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
|
// | array_attribute_list* ARRAY LESS_THAN type_decl GREATER_THAN
|
||||||
// | MAT2x2 LESS_THAN type_decl GREATER_THAN
|
// | MAT2x2 LESS_THAN type_decl GREATER_THAN
|
||||||
// | MAT2x3 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};
|
return TypeAndSize{type.value, nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = primary_expression();
|
auto size = element_count_expression();
|
||||||
if (size.errored) {
|
if (size.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
} else if (!size.matched) {
|
}
|
||||||
|
if (!size.matched) {
|
||||||
return add_error(peek(), "expected array size expression");
|
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;
|
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
|
// unary_expression
|
||||||
// : singular_expression
|
// : singular_expression
|
||||||
// | MINUS unary_expression
|
// | MINUS unary_expression
|
||||||
|
@ -646,6 +646,30 @@ class ParserImpl {
|
|||||||
/// @returns the parsed expression or nullptr
|
/// @returns the parsed expression or nullptr
|
||||||
Maybe<const ast::Expression*> bitwise_expression_post_unary_expression(
|
Maybe<const ast::Expression*> bitwise_expression_post_unary_expression(
|
||||||
const ast::Expression* lhs);
|
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
|
/// 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
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
namespace tint::reader::wgsl {
|
namespace tint::reader::wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
TEST_F(ParserImplTest, AdditiveExpression_Orig_Parses_Plus) {
|
||||||
auto p = parser("a + true");
|
auto p = parser("a + true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
|||||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
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 p = parser("a - true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -62,7 +62,7 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
|||||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
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 p = parser("if (a) {} + true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
@ -71,7 +71,7 @@ TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
|||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, AdditiveExpression_Orig_InvalidRHS) {
|
||||||
auto p = parser("true + if (a) {}");
|
auto p = parser("true + if (a) {}");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
EXPECT_FALSE(e.matched);
|
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");
|
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 p = parser("a true");
|
||||||
auto e = p->additive_expression();
|
auto e = p->additive_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -91,5 +91,189 @@ TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
|||||||
ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
|
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
|
||||||
} // namespace tint::reader::wgsl
|
} // 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) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayInvalidSize) {
|
||||||
EXPECT("var i : array<u32, !>;",
|
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, !>;
|
var i : array<u32, !>;
|
||||||
^
|
^
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
153
src/tint/reader/wgsl/parser_impl_math_expression_test.cc
Normal file
153
src/tint/reader/wgsl/parser_impl_math_expression_test.cc
Normal file
@ -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 tint::reader::wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_Parses_Multiply) {
|
||||||
auto p = parser("a * true");
|
auto p = parser("a * true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
|||||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
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 p = parser("a / true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -62,7 +62,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
|||||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
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 p = parser("a % true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -82,7 +82,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
|||||||
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
|
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 p = parser("if (a) {} * true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
@ -91,7 +91,7 @@ TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
|||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
TEST_F(ParserImplTest, MultiplicativeExpression_Orig_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_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");
|
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 p = parser("a true");
|
||||||
auto e = p->multiplicative_expression();
|
auto e = p->multiplicative_expression();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
@ -111,5 +111,170 @@ TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
|||||||
ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
|
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
|
||||||
} // namespace tint::reader::wgsl
|
} // namespace tint::reader::wgsl
|
||||||
|
@ -469,6 +469,33 @@ TEST_F(ParserImplTest, TypeDecl_Array_ConstantSize) {
|
|||||||
EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->symbol), "size");
|
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) {
|
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();
|
||||||
@ -524,7 +551,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
|
|||||||
EXPECT_FALSE(t.matched);
|
EXPECT_FALSE(t.matched);
|
||||||
ASSERT_EQ(t.value, nullptr);
|
ASSERT_EQ(t.value, nullptr);
|
||||||
ASSERT_TRUE(p->has_error());
|
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) {
|
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
|
/// @returns true if the token can be split during parse into component tokens
|
||||||
bool IsSplittable() const {
|
bool IsSplittable() const {
|
||||||
return Is(Token::Type::kShiftRight) || Is(Token::Type::kGreaterThanEqual) ||
|
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
|
/// @returns the source information for this token
|
||||||
|
Loading…
x
Reference in New Issue
Block a user