1use crate::lex::{Cursor, LexError, Scan};
2use crate::{Span, Spanner, ToTokens, TokenStream, TokenTree};
3
4pub mod float;
6pub 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#[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 #[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}