use crate::{
Parser, Punct, PunctAny, PunctJoint, Result, Spacing, ToTokens, TokenIter, TokenStream,
};
#[derive(Default, Copy, Clone, PartialEq, Eq)]
pub struct Operator<
const C1: char,
const C2: char = '\0',
const C3: char = '\0',
const C4: char = '\0',
>;
impl<const C1: char, const C2: char, const C3: char, const C4: char> Operator<C1, C2, C3, C4> {
#[must_use]
pub const fn new() -> Self {
const {
assert!(C1.is_ascii_punctuation());
assert!(C2 == '\0' || C2.is_ascii_punctuation());
assert!(C3 == '\0' || C3.is_ascii_punctuation());
assert!(C4 == '\0' || C4.is_ascii_punctuation());
}
Self
}
}
impl<const C1: char, const C2: char, const C3: char, const C4: char> Parser
for Operator<C1, C2, C3, C4>
{
#[mutants::skip]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
if C2 == '\0' {
PunctAny::<C1>::parser(tokens)?;
Ok(Self)
} else {
PunctJoint::<C1>::parser(tokens)?;
if C3 == '\0' {
PunctAny::<C2>::parser(tokens)?;
Ok(Self)
} else {
PunctJoint::<C2>::parser(tokens)?;
if C4 == '\0' {
PunctAny::<C3>::parser(tokens)?;
Ok(Self)
} else {
PunctJoint::<C3>::parser(tokens)?;
PunctAny::<C4>::parser(tokens)?;
Ok(Self)
}
}
}
}
}
impl<const C1: char, const C2: char, const C3: char, const C4: char> ToTokens
for Operator<C1, C2, C3, C4>
{
fn to_tokens(&self, tokens: &mut TokenStream) {
const fn spacing(c: char) -> Spacing {
if c == '\0' {
Spacing::Alone
} else {
Spacing::Joint
}
}
Punct::new(C1, spacing(C2)).to_tokens(tokens);
if C2 != '\0' {
Punct::new(C2, spacing(C3)).to_tokens(tokens);
if C3 != '\0' {
Punct::new(C3, spacing(C4)).to_tokens(tokens);
if C4 != '\0' {
Punct::new(C4, Spacing::Alone).to_tokens(tokens);
}
}
}
}
}
#[mutants::skip]
impl<const C1: char, const C2: char, const C3: char, const C4: char> std::fmt::Debug
for Operator<C1, C2, C3, C4>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if C4 != '\0' {
write!(f, "Operator<'{C1}{C2}{C3}{C4}'>")
} else if C3 != '\0' {
write!(f, "Operator<'{C1}{C2}{C3}'>")
} else if C2 != '\0' {
write!(f, "Operator<'{C1}{C2}'>")
} else {
write!(f, "Operator<'{C1}'>")
}
}
}
pub mod names {
use crate::{operator, PunctJoint};
pub type LifetimeTick = PunctJoint<'\''>;
operator! {
pub Plus = "+";
pub Minus = "-";
pub Star = "*";
pub Slash = "/";
pub Percent = "%";
pub Caret = "^";
pub Bang = "!";
pub And = "&";
pub Or = "|";
pub AndAnd = "&&";
pub OrOr = "||";
pub Shl = "<<";
pub Shr = ">>";
pub PlusEq = "+=";
pub MinusEq = "-=";
pub StarEq = "*=";
pub SlashEq = "/=";
pub PercentEq = "%=";
pub CaretEq = "^=";
pub AndEq = "&=";
pub OrEq = "|=";
pub ShlEq = "<<=";
pub ShrEq = ">>=";
pub Assign = "=";
pub Equal = "==";
pub NotEqual = "!=";
pub Gt = ">";
pub Lt = "<";
pub Ge = ">=";
pub Le = "<=";
pub At = "@";
pub Dot = ".";
pub DotDot = "..";
pub Ellipsis = "...";
pub DotDotEq = "..=";
pub Comma = ",";
pub Semicolon = ";";
pub Colon = ":";
pub PathSep = "::";
pub RArrow = "->";
pub FatArrow = "=>";
pub LArrow = "<-";
pub Pound = "#";
pub Dollar = "$";
pub Question = "?";
pub Tilde = "~";
pub Backslash = "\\";
}
}