Skip to main content

moxy_token/lit/
mod.rs

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