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