use ecma_lex_cat::token::TokenKind;
use ecma_syntax_cat::operator::{BinaryOperator, LogicalOperator};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BinaryInfo {
pub op: BinaryKind,
pub precedence: u8,
pub right_assoc: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryKind {
Binary(BinaryOperator),
Logical(LogicalOperator),
}
pub const MIN_PRECEDENCE: u8 = 1;
#[must_use]
#[allow(clippy::too_many_lines)] pub fn binary_info(kind: &TokenKind) -> Option<BinaryInfo> {
match kind {
TokenKind::QQ => Some(BinaryInfo {
op: BinaryKind::Logical(LogicalOperator::NullishCoalescing),
precedence: 3,
right_assoc: false,
}),
TokenKind::PipePipe => Some(BinaryInfo {
op: BinaryKind::Logical(LogicalOperator::Or),
precedence: 4,
right_assoc: false,
}),
TokenKind::AmpAmp => Some(BinaryInfo {
op: BinaryKind::Logical(LogicalOperator::And),
precedence: 5,
right_assoc: false,
}),
TokenKind::Pipe => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::BitwiseOr),
precedence: 6,
right_assoc: false,
}),
TokenKind::Caret => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::BitwiseXor),
precedence: 7,
right_assoc: false,
}),
TokenKind::Amp => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::BitwiseAnd),
precedence: 8,
right_assoc: false,
}),
TokenKind::EqEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Equal),
precedence: 9,
right_assoc: false,
}),
TokenKind::BangEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::NotEqual),
precedence: 9,
right_assoc: false,
}),
TokenKind::EqEqEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::StrictEqual),
precedence: 9,
right_assoc: false,
}),
TokenKind::BangEqEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::StrictNotEqual),
precedence: 9,
right_assoc: false,
}),
TokenKind::Lt => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::LessThan),
precedence: 10,
right_assoc: false,
}),
TokenKind::LtEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::LessThanOrEqual),
precedence: 10,
right_assoc: false,
}),
TokenKind::Gt => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::GreaterThan),
precedence: 10,
right_assoc: false,
}),
TokenKind::GtEq => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::GreaterThanOrEqual),
precedence: 10,
right_assoc: false,
}),
TokenKind::KwInstanceof => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::InstanceOf),
precedence: 10,
right_assoc: false,
}),
TokenKind::KwIn => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::In),
precedence: 10,
right_assoc: false,
}),
TokenKind::LtLt => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::LeftShift),
precedence: 11,
right_assoc: false,
}),
TokenKind::GtGt => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::RightShift),
precedence: 11,
right_assoc: false,
}),
TokenKind::GtGtGt => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::UnsignedRightShift),
precedence: 11,
right_assoc: false,
}),
TokenKind::Plus => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Add),
precedence: 12,
right_assoc: false,
}),
TokenKind::Minus => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Subtract),
precedence: 12,
right_assoc: false,
}),
TokenKind::Star => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Multiply),
precedence: 13,
right_assoc: false,
}),
TokenKind::Slash => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Divide),
precedence: 13,
right_assoc: false,
}),
TokenKind::Percent => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Remainder),
precedence: 13,
right_assoc: false,
}),
TokenKind::StarStar => Some(BinaryInfo {
op: BinaryKind::Binary(BinaryOperator::Exponentiation),
precedence: 14,
right_assoc: true,
}),
_other => None,
}
}
#[must_use]
pub fn assignment_operator(
kind: &TokenKind,
) -> Option<ecma_syntax_cat::operator::AssignmentOperator> {
use ecma_syntax_cat::operator::AssignmentOperator as A;
match kind {
TokenKind::Eq => Some(A::Assign),
TokenKind::PlusEq => Some(A::AddAssign),
TokenKind::MinusEq => Some(A::SubtractAssign),
TokenKind::StarEq => Some(A::MultiplyAssign),
TokenKind::SlashEq => Some(A::DivideAssign),
TokenKind::PercentEq => Some(A::RemainderAssign),
TokenKind::StarStarEq => Some(A::ExponentiationAssign),
TokenKind::LtLtEq => Some(A::LeftShiftAssign),
TokenKind::GtGtEq => Some(A::RightShiftAssign),
TokenKind::GtGtGtEq => Some(A::UnsignedRightShiftAssign),
TokenKind::AmpEq => Some(A::BitwiseAndAssign),
TokenKind::PipeEq => Some(A::BitwiseOrAssign),
TokenKind::CaretEq => Some(A::BitwiseXorAssign),
TokenKind::AmpAmpEq => Some(A::LogicalAndAssign),
TokenKind::PipePipeEq => Some(A::LogicalOrAssign),
TokenKind::QQEq => Some(A::NullishCoalescingAssign),
_other => None,
}
}