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