Skip to main content

moxy_token/lit/
mod.rs

1use crate::lex::{Cursor, LexError, Scan};
2use crate::{Span, Spanner, ToTokens, TokenStream, TokenTree};
3
4/// Floating-point literal parsing and representation.
5pub mod float;
6/// Integer literal parsing, radix, and suffix representation.
7pub mod int;
8
9mod r#bool;
10mod byte;
11mod byte_str;
12mod c_str;
13mod char;
14mod str;
15mod verbatim;
16
17pub use r#bool::*;
18pub use byte::*;
19pub use byte_str::*;
20pub use c_str::*;
21pub use char::*;
22pub use float::*;
23pub use int::*;
24pub use str::*;
25pub use verbatim::*;
26
27/// A parsed Rust  literal token.
28#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(into = "String"))]
30pub enum Lit {
31    Int(LitInt),
32    Float(LitFloat),
33    Str(LitStr),
34    ByteStr(LitByteStr),
35    CStr(LitCStr),
36    Char(LitChar),
37    Byte(LitByte),
38    Bool(LitBool),
39    Verbatim(LitVerbatim),
40}
41
42impl Lit {
43    #[inline]
44    pub fn string(value: &str) -> Self {
45        Self::Str(LitStr::new(value, Span::default()))
46    }
47
48    #[inline]
49    pub fn char(value: char) -> Self {
50        Self::Char(LitChar::new(value, Span::default()))
51    }
52
53    /// Classify and decode an arbitrary literal repr into the matching variant. Used by
54    /// the proc-macro bridges, which only have the source text. Falls back to
55    /// [`LitVerbatim`] for anything that doesn't lex as a known literal.
56    #[inline]
57    pub fn from_repr(repr: &str, span: Span) -> Self {
58        use std::str::FromStr;
59
60        match TokenStream::from_str(repr).ok().and_then(|ts| ts.into_iter().next()) {
61            Some(TokenTree::Literal(mut lit)) if lit.repr() == repr => {
62                lit.set_span(span);
63                lit
64            }
65            _ => Self::Verbatim(LitVerbatim::new(repr, span)),
66        }
67    }
68
69    #[inline]
70    pub fn is_int(&self) -> bool {
71        matches!(self, Self::Int(_))
72    }
73
74    #[inline]
75    pub fn is_float(&self) -> bool {
76        matches!(self, Self::Float(_))
77    }
78
79    #[inline]
80    pub fn is_str(&self) -> bool {
81        matches!(self, Self::Str(_))
82    }
83
84    #[inline]
85    pub fn is_c_str(&self) -> bool {
86        matches!(self, Self::CStr(_))
87    }
88
89    #[inline]
90    pub fn is_bool(&self) -> bool {
91        matches!(self, Self::Bool(_))
92    }
93
94    #[inline]
95    pub fn is_char(&self) -> bool {
96        matches!(self, Self::Char(_))
97    }
98
99    #[inline]
100    pub fn is_byte(&self) -> bool {
101        matches!(self, Self::Byte(_))
102    }
103
104    #[inline]
105    pub fn is_byte_str(&self) -> bool {
106        matches!(self, Self::ByteStr(_))
107    }
108
109    #[inline]
110    pub fn is_verbatim(&self) -> bool {
111        matches!(self, Self::Verbatim(_))
112    }
113
114    #[inline]
115    pub fn as_str(&self) -> Option<&LitStr> {
116        if let Self::Str(v) = self { Some(v) } else { None }
117    }
118
119    #[inline]
120    pub fn as_c_str(&self) -> Option<&LitCStr> {
121        if let Self::CStr(v) = self { Some(v) } else { None }
122    }
123
124    #[inline]
125    pub fn as_bool(&self) -> Option<&LitBool> {
126        if let Self::Bool(v) = self { Some(v) } else { None }
127    }
128
129    #[inline]
130    pub fn as_int(&self) -> Option<&LitInt> {
131        if let Self::Int(v) = self { Some(v) } else { None }
132    }
133
134    #[inline]
135    pub fn as_float(&self) -> Option<&LitFloat> {
136        if let Self::Float(v) = self { Some(v) } else { None }
137    }
138
139    #[inline]
140    pub fn as_char(&self) -> Option<&LitChar> {
141        if let Self::Char(v) = self { Some(v) } else { None }
142    }
143
144    #[inline]
145    pub fn as_byte(&self) -> Option<&LitByte> {
146        if let Self::Byte(v) = self { Some(v) } else { None }
147    }
148
149    #[inline]
150    pub fn as_byte_str(&self) -> Option<&LitByteStr> {
151        if let Self::ByteStr(v) = self { Some(v) } else { None }
152    }
153
154    #[inline]
155    pub fn to_token_tree(&self) -> TokenTree {
156        TokenTree::Literal(self.clone())
157    }
158
159    #[inline]
160    pub fn into_token_tree(self) -> TokenTree {
161        TokenTree::Literal(self)
162    }
163
164    #[inline]
165    pub fn repr(&self) -> &str {
166        match self {
167            Self::Int(v) => v.repr(),
168            Self::Float(v) => v.repr(),
169            Self::Str(v) => v.repr(),
170            Self::ByteStr(v) => v.repr(),
171            Self::CStr(v) => v.repr(),
172            Self::Char(v) => v.repr(),
173            Self::Byte(v) => v.repr(),
174            Self::Bool(v) => v.repr(),
175            Self::Verbatim(v) => v.repr(),
176        }
177    }
178
179    #[inline]
180    pub fn span(&self) -> Span {
181        match self {
182            Self::Int(v) => v.span(),
183            Self::Float(v) => v.span(),
184            Self::Str(v) => v.span(),
185            Self::ByteStr(v) => v.span(),
186            Self::CStr(v) => v.span(),
187            Self::Char(v) => v.span(),
188            Self::Byte(v) => v.span(),
189            Self::Bool(v) => v.span(),
190            Self::Verbatim(v) => v.span(),
191        }
192    }
193
194    #[inline]
195    pub fn set_span(&mut self, span: Span) {
196        match self {
197            Self::Int(v) => v.set_span(span),
198            Self::Float(v) => v.set_span(span),
199            Self::Str(v) => v.set_span(span),
200            Self::ByteStr(v) => v.set_span(span),
201            Self::CStr(v) => v.set_span(span),
202            Self::Char(v) => v.set_span(span),
203            Self::Byte(v) => v.set_span(span),
204            Self::Bool(v) => v.set_span(span),
205            Self::Verbatim(v) => v.set_span(span),
206        }
207    }
208}
209
210impl Spanner for Lit {
211    fn span(&self) -> Span {
212        self.span()
213    }
214}
215
216impl std::fmt::Display for Lit {
217    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218        f.write_str(self.repr())
219    }
220}
221
222#[cfg(feature = "serde")]
223impl From<Lit> for String {
224    fn from(value: Lit) -> Self {
225        value.repr().to_string()
226    }
227}
228
229impl Scan for Lit {
230    fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
231        if let Ok((end, v)) = LitBool::scan(cursor) {
232            return Ok((end, Self::Bool(v)));
233        }
234
235        if let Ok((end, v)) = LitByte::scan(cursor) {
236            return Ok((end, Self::Byte(v)));
237        }
238
239        if let Ok((end, v)) = LitByteStr::scan(cursor) {
240            return Ok((end, Self::ByteStr(v)));
241        }
242
243        if let Ok((end, v)) = LitCStr::scan(cursor) {
244            return Ok((end, Self::CStr(v)));
245        }
246
247        if let Ok((end, v)) = LitStr::scan(cursor) {
248            return Ok((end, Self::Str(v)));
249        }
250
251        if let Ok((end, v)) = LitChar::scan(cursor) {
252            return Ok((end, Self::Char(v)));
253        }
254
255        if let Ok((end, v)) = LitFloat::scan(cursor) {
256            return Ok((end, Self::Float(v)));
257        }
258
259        if let Ok((end, v)) = LitInt::scan(cursor) {
260            return Ok((end, Self::Int(v)));
261        }
262
263        cursor.error().into()
264    }
265}
266
267impl ToTokens for Lit {
268    fn to_tokens(&self, tokens: &mut TokenStream) {
269        tokens.extend_one(TokenTree::Literal(self.clone()));
270    }
271}