Files
carbon-lang/toolchain/parse/precedence_test.cpp
T
Jon Ross-PerkinsandChandler Carruth ec182fb00d Rename lexer dir to lex (#3179)
Continuing with #3070. Just a dir and file rename (only prefix change is
lexer_file_test). Everything in the lex dir should be marked as a move.

Note, I think this closes #3070. There may still be further cleanup
later, but the organizational changes suggested there are being
completed.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-09-01 02:39:04 +00:00

162 lines
6.4 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/parse/precedence.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "toolchain/lex/token_kind.h"
namespace Carbon::Testing {
namespace {
using Parse::Associativity;
using Parse::OperatorPriority;
using Parse::PrecedenceGroup;
using ::testing::Eq;
TEST(PrecedenceTest, OperatorsAreRecognized) {
EXPECT_TRUE(PrecedenceGroup::ForLeading(Lex::TokenKind::Minus).has_value());
EXPECT_TRUE(PrecedenceGroup::ForLeading(Lex::TokenKind::Caret).has_value());
EXPECT_FALSE(PrecedenceGroup::ForLeading(Lex::TokenKind::Slash).has_value());
EXPECT_FALSE(
PrecedenceGroup::ForLeading(Lex::TokenKind::Identifier).has_value());
EXPECT_FALSE(PrecedenceGroup::ForLeading(Lex::TokenKind::Tilde).has_value());
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Minus, false).has_value());
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Caret, false).has_value());
EXPECT_FALSE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Tilde, false).has_value());
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Slash, true).has_value());
EXPECT_FALSE(PrecedenceGroup::ForTrailing(Lex::TokenKind::Identifier, false)
.has_value());
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Minus, true)->is_binary);
EXPECT_FALSE(PrecedenceGroup::ForTrailing(Lex::TokenKind::MinusMinus, false)
.has_value());
}
TEST(PrecedenceTest, InfixVsPostfix) {
// A trailing `-` is always binary, even when written with whitespace that
// suggests it's postfix.
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Minus, /*infix*/ false)
->is_binary);
// A trailing `*` is interpreted based on context.
EXPECT_TRUE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->is_binary);
EXPECT_FALSE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->is_binary);
// Infix `*` can appear in `+` contexts; postfix `*` cannot.
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level),
Eq(OperatorPriority::Ambiguous));
}
TEST(PrecedenceTest, Associativity) {
EXPECT_THAT(
PrecedenceGroup::ForLeading(Lex::TokenKind::Minus)->GetAssociativity(),
Eq(Associativity::None));
EXPECT_THAT(
PrecedenceGroup::ForLeading(Lex::TokenKind::Star)->GetAssociativity(),
Eq(Associativity::RightToLeft));
EXPECT_THAT(PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)
->level.GetAssociativity(),
Eq(Associativity::LeftToRight));
EXPECT_THAT(PrecedenceGroup::ForTrailing(Lex::TokenKind::Equal, true)
->level.GetAssociativity(),
Eq(Associativity::None));
}
TEST(PrecedenceTest, DirectRelations) {
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level),
Eq(OperatorPriority::RightFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Amp, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Less, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Less, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Amp, true)->level),
Eq(OperatorPriority::RightFirst));
}
TEST(PrecedenceTest, IndirectRelations) {
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Or, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Or, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level),
Eq(OperatorPriority::RightFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
*PrecedenceGroup::ForLeading(Lex::TokenKind::Caret),
PrecedenceGroup::ForTrailing(Lex::TokenKind::Equal, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Equal, true)->level,
*PrecedenceGroup::ForLeading(Lex::TokenKind::Caret)),
Eq(OperatorPriority::RightFirst));
}
TEST(PrecedenceTest, IncomparableOperators) {
EXPECT_THAT(PrecedenceGroup::GetPriority(
*PrecedenceGroup::ForLeading(Lex::TokenKind::Caret),
*PrecedenceGroup::ForLeading(Lex::TokenKind::Not)),
Eq(OperatorPriority::Ambiguous));
EXPECT_THAT(PrecedenceGroup::GetPriority(
*PrecedenceGroup::ForLeading(Lex::TokenKind::Caret),
*PrecedenceGroup::ForLeading(Lex::TokenKind::Minus)),
Eq(OperatorPriority::Ambiguous));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
*PrecedenceGroup::ForLeading(Lex::TokenKind::Not),
PrecedenceGroup::ForTrailing(Lex::TokenKind::Amp, true)->level),
Eq(OperatorPriority::Ambiguous));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Equal, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::PipeEqual, true)->level),
Eq(OperatorPriority::Ambiguous));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Amp, true)->level),
Eq(OperatorPriority::Ambiguous));
}
} // namespace
} // namespace Carbon::Testing