use std::convert::TryFrom;
use crate::{TSXKeyword, TSXToken};
#[rustfmt::skip]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub enum BinaryOperator {
Add, Subtract, Multiply, Divide, Modulo, Exponent,
BitwiseShiftLeft, BitwiseShiftRight, BitwiseShiftRightUnsigned,
BitwiseAnd, BitwiseXOr, BitwiseOr,
StrictEqual, StrictNotEqual, Equal, NotEqual,
GreaterThan, LessThan, LessThanEqual, GreaterThanEqual,
LogicalAnd, LogicalOr,
NullCoalescing,
Divides,
Pipe,
Compose
}
#[rustfmt::skip]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub enum BinaryAssignmentOperator {
LogicalNullishAssignment,
AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, ModuloAssign, ExponentAssign,
LogicalAndAssign, LogicalOrAssign,
BitwiseShiftLeftAssign, BitwiseShiftRightAssign, BitwiseShiftRightUnsigned,
BitwiseAndAssign, BitwiseXOrAssign, BitwiseOrAssign,
}
#[rustfmt::skip]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub enum UnaryOperator {
Plus, Negation,
BitwiseNot, LogicalNot,
Await, TypeOf, Void, Delete, Yield, DelegatedYield,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub enum IncrementOrDecrement {
Increment,
Decrement,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub enum UnaryPrefixAssignmentOperator {
Invert,
IncrementOrDecrement(IncrementOrDecrement),
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "self-rust-tokenize", derive(self_rust_tokenize::SelfRustTokenize))]
#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
pub struct UnaryPostfixAssignmentOperator(pub IncrementOrDecrement);
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum AssociativityDirection {
NA,
LeftToRight,
RightToLeft,
}
impl AssociativityDirection {
pub(crate) fn should_return(self, parent_precedence: u8, upcoming_precedence: u8) -> bool {
match self {
AssociativityDirection::RightToLeft => parent_precedence > upcoming_precedence,
AssociativityDirection::NA | AssociativityDirection::LeftToRight => {
parent_precedence >= upcoming_precedence
}
}
}
}
pub trait Operator: for<'a> TryFrom<&'a TSXToken> {
fn to_str(&self) -> &'static str;
fn precedence(&self) -> u8;
fn associativity_direction(&self) -> AssociativityDirection;
fn is_associative(&self) -> bool;
fn precedence_and_associativity_direction(&self) -> (u8, AssociativityDirection) {
(self.precedence(), self.associativity_direction())
}
}
impl Operator for BinaryOperator {
fn to_str(&self) -> &'static str {
match self {
BinaryOperator::Add => "+",
BinaryOperator::Subtract => "-",
BinaryOperator::Multiply => "*",
BinaryOperator::Divide => "/",
BinaryOperator::Exponent => "**",
BinaryOperator::LessThan => "<",
BinaryOperator::GreaterThan => ">",
BinaryOperator::LessThanEqual => "<=",
BinaryOperator::GreaterThanEqual => ">",
BinaryOperator::Equal => "==",
BinaryOperator::StrictEqual => "===",
BinaryOperator::NotEqual => "!=",
BinaryOperator::StrictNotEqual => "!==",
BinaryOperator::Modulo => "%",
BinaryOperator::NullCoalescing => "??",
BinaryOperator::LogicalAnd => "&&",
BinaryOperator::LogicalOr => "||",
BinaryOperator::BitwiseShiftLeft => "<<",
BinaryOperator::BitwiseShiftRight => ">>",
BinaryOperator::BitwiseShiftRightUnsigned => ">>>",
BinaryOperator::BitwiseAnd => "&",
BinaryOperator::BitwiseOr => "|",
BinaryOperator::BitwiseXOr => "^",
BinaryOperator::Divides => "/%", BinaryOperator::Compose => "<@>", BinaryOperator::Pipe => "|>",
}
}
fn precedence(&self) -> u8 {
match self {
BinaryOperator::Exponent => 14,
BinaryOperator::Multiply => 13,
BinaryOperator::Divide => 13,
BinaryOperator::Modulo => 13,
BinaryOperator::Add => 12,
BinaryOperator::Subtract => 12,
BinaryOperator::BitwiseShiftLeft => 11,
BinaryOperator::BitwiseShiftRight => 11,
BinaryOperator::BitwiseShiftRightUnsigned => 11,
BinaryOperator::LessThan => 10,
BinaryOperator::LessThanEqual => 10,
BinaryOperator::GreaterThan => 10,
BinaryOperator::GreaterThanEqual => 10,
BinaryOperator::Equal
| BinaryOperator::NotEqual
| BinaryOperator::StrictEqual
| BinaryOperator::StrictNotEqual => 9,
BinaryOperator::BitwiseAnd => 8,
BinaryOperator::BitwiseXOr => 7,
BinaryOperator::BitwiseOr => 6,
BinaryOperator::LogicalAnd => 5,
BinaryOperator::NullCoalescing => 4,
BinaryOperator::LogicalOr => 4,
BinaryOperator::Divides => 13,
BinaryOperator::Pipe => 15,
BinaryOperator::Compose => 15,
}
}
fn associativity_direction(&self) -> AssociativityDirection {
if let BinaryOperator::Exponent = self {
AssociativityDirection::RightToLeft
} else {
AssociativityDirection::LeftToRight
}
}
fn is_associative(&self) -> bool {
!matches!(self, Self::Subtract | Self::Exponent | Self::Divide)
}
}
impl Operator for UnaryOperator {
fn to_str(&self) -> &'static str {
match self {
UnaryOperator::Plus => "+",
UnaryOperator::Negation => "-",
UnaryOperator::BitwiseNot => "~",
UnaryOperator::LogicalNot => "!",
UnaryOperator::Delete => "delete ",
UnaryOperator::Yield => "yield ",
UnaryOperator::DelegatedYield => "yield* ",
UnaryOperator::Await => "await ",
UnaryOperator::TypeOf => "typeof ",
UnaryOperator::Void => "void ",
}
}
fn precedence(&self) -> u8 {
match self {
UnaryOperator::TypeOf
| UnaryOperator::Await
| UnaryOperator::Delete
| UnaryOperator::Void
| UnaryOperator::BitwiseNot
| UnaryOperator::LogicalNot
| UnaryOperator::Plus
| UnaryOperator::Negation => 15,
UnaryOperator::Yield | UnaryOperator::DelegatedYield => 2,
}
}
fn associativity_direction(&self) -> AssociativityDirection {
AssociativityDirection::RightToLeft
}
fn is_associative(&self) -> bool {
true
}
}
impl Operator for BinaryAssignmentOperator {
fn to_str(&self) -> &'static str {
match self {
BinaryAssignmentOperator::LogicalNullishAssignment => "??=",
BinaryAssignmentOperator::AddAssign => "+=",
BinaryAssignmentOperator::SubtractAssign => "-=",
BinaryAssignmentOperator::MultiplyAssign => "*=",
BinaryAssignmentOperator::DivideAssign => "/=",
BinaryAssignmentOperator::ModuloAssign => "%=",
BinaryAssignmentOperator::ExponentAssign => "**=",
BinaryAssignmentOperator::BitwiseShiftLeftAssign => "<<=",
BinaryAssignmentOperator::BitwiseShiftRightAssign => ">>=",
BinaryAssignmentOperator::BitwiseShiftRightUnsigned => ">>>=",
BinaryAssignmentOperator::BitwiseAndAssign => "&=",
BinaryAssignmentOperator::BitwiseXOrAssign => "^=",
BinaryAssignmentOperator::BitwiseOrAssign => "|=",
BinaryAssignmentOperator::LogicalAndAssign => "&&=",
BinaryAssignmentOperator::LogicalOrAssign => "||=",
}
}
fn precedence(&self) -> u8 {
ASSIGNMENT_PRECEDENCE
}
fn associativity_direction(&self) -> AssociativityDirection {
AssociativityDirection::RightToLeft
}
fn is_associative(&self) -> bool {
true
}
}
impl Operator for UnaryPrefixAssignmentOperator {
fn precedence(&self) -> u8 {
15
}
fn associativity_direction(&self) -> AssociativityDirection {
AssociativityDirection::RightToLeft
}
fn to_str(&self) -> &'static str {
match self {
UnaryPrefixAssignmentOperator::Invert => ">!", UnaryPrefixAssignmentOperator::IncrementOrDecrement(inc_or_dec) => inc_or_dec.to_str(),
}
}
fn is_associative(&self) -> bool {
true
}
}
impl Operator for UnaryPostfixAssignmentOperator {
fn precedence(&self) -> u8 {
16
}
fn associativity_direction(&self) -> AssociativityDirection {
AssociativityDirection::NA
}
fn to_str(&self) -> &'static str {
self.0.to_str()
}
fn is_associative(&self) -> bool {
true
}
}
impl IncrementOrDecrement {
fn to_str(self) -> &'static str {
match self {
IncrementOrDecrement::Increment => "++",
IncrementOrDecrement::Decrement => "--",
}
}
}
impl From<BinaryAssignmentOperator> for BinaryOperator {
fn from(val: BinaryAssignmentOperator) -> Self {
match val {
BinaryAssignmentOperator::LogicalNullishAssignment => BinaryOperator::NullCoalescing,
BinaryAssignmentOperator::AddAssign => BinaryOperator::Add,
BinaryAssignmentOperator::SubtractAssign => BinaryOperator::Subtract,
BinaryAssignmentOperator::MultiplyAssign => BinaryOperator::Multiply,
BinaryAssignmentOperator::DivideAssign => BinaryOperator::Divide,
BinaryAssignmentOperator::ModuloAssign => BinaryOperator::Modulo,
BinaryAssignmentOperator::ExponentAssign => BinaryOperator::Exponent,
BinaryAssignmentOperator::LogicalAndAssign => BinaryOperator::LogicalAnd,
BinaryAssignmentOperator::LogicalOrAssign => BinaryOperator::LogicalOr,
BinaryAssignmentOperator::BitwiseShiftLeftAssign => BinaryOperator::BitwiseShiftLeft,
BinaryAssignmentOperator::BitwiseShiftRightAssign => BinaryOperator::BitwiseShiftRight,
BinaryAssignmentOperator::BitwiseShiftRightUnsigned => {
BinaryOperator::BitwiseShiftRightUnsigned
}
BinaryAssignmentOperator::BitwiseAndAssign => BinaryOperator::BitwiseAnd,
BinaryAssignmentOperator::BitwiseXOrAssign => BinaryOperator::BitwiseXOr,
BinaryAssignmentOperator::BitwiseOrAssign => BinaryOperator::BitwiseOr,
}
}
}
impl TryFrom<&TSXToken> for BinaryAssignmentOperator {
type Error = ();
fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
match expression {
TSXToken::AddAssign => Ok(BinaryAssignmentOperator::AddAssign),
TSXToken::SubtractAssign => Ok(BinaryAssignmentOperator::SubtractAssign),
TSXToken::MultiplyAssign => Ok(BinaryAssignmentOperator::MultiplyAssign),
TSXToken::DivideAssign => Ok(BinaryAssignmentOperator::DivideAssign),
TSXToken::ExponentAssign => Ok(BinaryAssignmentOperator::ExponentAssign),
TSXToken::LogicalAndAssign => Ok(BinaryAssignmentOperator::LogicalAndAssign),
TSXToken::LogicalOrAssign => Ok(BinaryAssignmentOperator::LogicalOrAssign),
TSXToken::BitwiseAndAssign => Ok(BinaryAssignmentOperator::BitwiseAndAssign),
TSXToken::BitwiseOrAssign => Ok(BinaryAssignmentOperator::BitwiseOrAssign),
TSXToken::BitwiseXorAssign => Ok(BinaryAssignmentOperator::BitwiseXOrAssign),
TSXToken::BitwiseShiftLeftAssign => {
Ok(BinaryAssignmentOperator::BitwiseShiftLeftAssign)
}
TSXToken::BitwiseShiftRightAssign => {
Ok(BinaryAssignmentOperator::BitwiseShiftRightAssign)
}
TSXToken::BitwiseShiftRightUnsignedAssign => {
Ok(BinaryAssignmentOperator::BitwiseShiftRightUnsigned)
}
TSXToken::NullishCoalescingAssign => {
Ok(BinaryAssignmentOperator::LogicalNullishAssignment)
}
_ => Err(()),
}
}
}
impl TryFrom<&TSXToken> for BinaryOperator {
type Error = ();
fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
match expression {
TSXToken::Add => Ok(BinaryOperator::Add),
TSXToken::Subtract => Ok(BinaryOperator::Subtract),
TSXToken::Multiply => Ok(BinaryOperator::Multiply),
TSXToken::Divide => Ok(BinaryOperator::Divide),
TSXToken::Exponent => Ok(BinaryOperator::Exponent),
TSXToken::Modulo => Ok(BinaryOperator::Modulo),
TSXToken::Equal => Ok(BinaryOperator::Equal),
TSXToken::NotEqual => Ok(BinaryOperator::NotEqual),
TSXToken::StrictEqual => Ok(BinaryOperator::StrictEqual),
TSXToken::StrictNotEqual => Ok(BinaryOperator::StrictNotEqual),
TSXToken::LogicalOr => Ok(BinaryOperator::LogicalOr),
TSXToken::LogicalAnd => Ok(BinaryOperator::LogicalAnd),
TSXToken::OpenChevron => Ok(BinaryOperator::LessThan),
TSXToken::LessThanEqual => Ok(BinaryOperator::LessThanEqual),
TSXToken::CloseChevron => Ok(BinaryOperator::GreaterThan),
TSXToken::GreaterThanEqual => Ok(BinaryOperator::GreaterThanEqual),
TSXToken::BitwiseAnd => Ok(BinaryOperator::BitwiseAnd),
TSXToken::BitwiseOr => Ok(BinaryOperator::BitwiseOr),
TSXToken::BitwiseXOr => Ok(BinaryOperator::BitwiseXOr),
TSXToken::BitwiseShiftLeft => Ok(BinaryOperator::BitwiseShiftLeft),
TSXToken::BitwiseShiftRight => Ok(BinaryOperator::BitwiseShiftRight),
TSXToken::BitwiseShiftRightUnsigned => Ok(BinaryOperator::BitwiseShiftRightUnsigned),
TSXToken::NullishCoalescing => Ok(BinaryOperator::NullCoalescing),
#[cfg(feature = "extras")]
TSXToken::DividesOperator => Ok(BinaryOperator::Divides),
#[cfg(feature = "extras")]
TSXToken::ComposeOperator => Ok(BinaryOperator::Compose),
#[cfg(feature = "extras")]
TSXToken::PipeOperator => Ok(BinaryOperator::Pipe),
_ => Err(()),
}
}
}
impl TryFrom<&TSXToken> for UnaryOperator {
type Error = ();
fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
match expression {
TSXToken::Keyword(TSXKeyword::Yield) => Ok(UnaryOperator::Yield),
TSXToken::Keyword(TSXKeyword::TypeOf) => Ok(UnaryOperator::TypeOf),
TSXToken::Keyword(TSXKeyword::Await) => Ok(UnaryOperator::Await),
TSXToken::Keyword(TSXKeyword::Void) => Ok(UnaryOperator::Void),
TSXToken::Keyword(TSXKeyword::Delete) => Ok(UnaryOperator::Delete),
TSXToken::LogicalNot => Ok(UnaryOperator::LogicalNot),
TSXToken::BitwiseNot => Ok(UnaryOperator::BitwiseNot),
TSXToken::Subtract => Ok(UnaryOperator::Negation),
TSXToken::Add => Ok(UnaryOperator::Plus),
_ => Err(()),
}
}
}
impl TryFrom<&TSXToken> for IncrementOrDecrement {
type Error = ();
fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
match token {
TSXToken::Increment => Ok(Self::Increment),
TSXToken::Decrement => Ok(Self::Decrement),
_ => Err(()),
}
}
}
impl TryFrom<&TSXToken> for UnaryPostfixAssignmentOperator {
type Error = ();
fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
IncrementOrDecrement::try_from(token).map(Self)
}
}
impl TryFrom<&TSXToken> for UnaryPrefixAssignmentOperator {
type Error = ();
fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
#[cfg(feature = "extras")]
if *token == TSXToken::InvertAssign {
Ok(Self::Invert)
} else {
IncrementOrDecrement::try_from(token).map(Self::IncrementOrDecrement)
}
#[cfg(not(feature = "extras"))]
IncrementOrDecrement::try_from(token).map(Self::IncrementOrDecrement)
}
}
impl BinaryOperator {
pub fn is_rhs_conditional_evaluation(&self) -> bool {
matches!(self, BinaryOperator::LogicalAnd | BinaryOperator::LogicalOr)
}
}
pub(crate) const COMMA_PRECEDENCE: u8 = 1;
pub(crate) const MEMBER_ACCESS_PRECEDENCE: u8 = 18;
pub(crate) const INDEX_PRECEDENCE: u8 = 18;
pub(crate) const CONDITIONAL_TERNARY_PRECEDENCE: u8 = 2;
pub(crate) const FUNCTION_CALL_PRECEDENCE: u8 = 18;
pub(crate) const CONSTRUCTOR_PRECEDENCE: u8 = 18;
pub(crate) const CONSTRUCTOR_WITHOUT_PARENTHESIS_PRECEDENCE: u8 = 17;
pub(crate) const IN_PRECEDENCE: u8 = 10;
pub(crate) const INSTANCE_OF_PRECEDENCE: u8 = 10;
pub(crate) const PARENTHESIZED_EXPRESSION_AND_LITERAL_PRECEDENCE: u8 = 19;
pub(crate) const ASSIGNMENT_PRECEDENCE: u8 = 2;
pub(crate) const AS_PRECEDENCE: u8 = 2;