1use crate::{
5 Parser, Punct, PunctAny, PunctJoint, Result, Spacing, ToTokens, TokenIter, TokenStream,
6};
7
8#[derive(Default, Copy, Clone, PartialEq, Eq)]
13pub struct Operator<
14 const C1: char,
15 const C2: char = '\0',
16 const C3: char = '\0',
17 const C4: char = '\0',
18>;
19
20impl<const C1: char, const C2: char, const C3: char, const C4: char> Operator<C1, C2, C3, C4> {
21 #[must_use]
23 pub const fn new() -> Self {
24 const {
25 assert!(C1.is_ascii_punctuation());
26 assert!(C2 == '\0' || C2.is_ascii_punctuation());
27 assert!(C3 == '\0' || C3.is_ascii_punctuation());
28 assert!(C4 == '\0' || C4.is_ascii_punctuation());
29 }
30 Self
31 }
32}
33
34impl<const C1: char, const C2: char, const C3: char, const C4: char> Parser
35 for Operator<C1, C2, C3, C4>
36{
37 #[mutants::skip]
43 fn parser(tokens: &mut TokenIter) -> Result<Self> {
44 if C2 == '\0' {
45 PunctAny::<C1>::parser(tokens)?;
46 Ok(Self)
47 } else {
48 PunctJoint::<C1>::parser(tokens)?;
49 if C3 == '\0' {
50 PunctAny::<C2>::parser(tokens)?;
51 Ok(Self)
52 } else {
53 PunctJoint::<C2>::parser(tokens)?;
54 if C4 == '\0' {
55 PunctAny::<C3>::parser(tokens)?;
56 Ok(Self)
57 } else {
58 PunctJoint::<C3>::parser(tokens)?;
59 PunctAny::<C4>::parser(tokens)?;
60 Ok(Self)
61 }
62 }
63 }
64 }
65}
66
67impl<const C1: char, const C2: char, const C3: char, const C4: char> ToTokens
68 for Operator<C1, C2, C3, C4>
69{
70 fn to_tokens(&self, tokens: &mut TokenStream) {
71 const fn spacing(c: char) -> Spacing {
73 if c == '\0' {
74 Spacing::Alone
75 } else {
76 Spacing::Joint
77 }
78 }
79
80 Punct::new(C1, spacing(C2)).to_tokens(tokens);
81 if C2 != '\0' {
82 Punct::new(C2, spacing(C3)).to_tokens(tokens);
83 if C3 != '\0' {
84 Punct::new(C3, spacing(C4)).to_tokens(tokens);
85 if C4 != '\0' {
86 Punct::new(C4, Spacing::Alone).to_tokens(tokens);
87 }
88 }
89 }
90 }
91}
92
93#[mutants::skip]
94impl<const C1: char, const C2: char, const C3: char, const C4: char> std::fmt::Debug
95 for Operator<C1, C2, C3, C4>
96{
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 if C4 != '\0' {
99 write!(f, "Operator<'{C1}{C2}{C3}{C4}'>")
100 } else if C3 != '\0' {
101 write!(f, "Operator<'{C1}{C2}{C3}'>")
102 } else if C2 != '\0' {
103 write!(f, "Operator<'{C1}{C2}'>")
104 } else {
105 write!(f, "Operator<'{C1}'>")
106 }
107 }
108}
109
110pub mod names {
122 use crate::{operator, PunctJoint};
123
124 pub type LifetimeTick = PunctJoint<'\''>;
126
127 operator! {
128 pub Plus = "+";
129 pub Minus = "-";
130 pub Star = "*";
131 pub Slash = "/";
132 pub Percent = "%";
133 pub Caret = "^";
134 pub Bang = "!";
135 pub And = "&";
136 pub Or = "|";
137 pub AndAnd = "&&";
138 pub OrOr = "||";
139 pub Shl = "<<";
140 pub Shr = ">>";
141 pub PlusEq = "+=";
142 pub MinusEq = "-=";
143 pub StarEq = "*=";
144 pub SlashEq = "/=";
145 pub PercentEq = "%=";
146 pub CaretEq = "^=";
147 pub AndEq = "&=";
148 pub OrEq = "|=";
149 pub ShlEq = "<<=";
150 pub ShrEq = ">>=";
151 pub Assign = "=";
152 pub Equal = "==";
153 pub NotEqual = "!=";
154 pub Gt = ">";
155 pub Lt = "<";
156 pub Ge = ">=";
157 pub Le = "<=";
158 pub At = "@";
159 pub Dot = ".";
160 pub DotDot = "..";
161 pub Ellipsis = "...";
162 pub DotDotEq = "..=";
163 pub Comma = ",";
164 pub Semicolon = ";";
165 pub Colon = ":";
166 pub PathSep = "::";
167 pub RArrow = "->";
168 pub FatArrow = "=>";
169 pub LArrow = "<-";
170 pub Pound = "#";
171 pub Dollar = "$";
172 pub Question = "?";
173 pub Tilde = "~";
174 pub Backslash = "\\";
175 }
176}