1use core::ascii;
2use core::fmt;
3
4use crate::ast::prelude::*;
5use crate::ast::{Kind, Span, Spanned};
6use crate::compile;
7use crate::macros::{MacroContext, SyntheticId, ToTokens, TokenStream};
8use crate::parse::{Expectation, IntoExpectation, Parse, Parser, Peek};
9use crate::SourceId;
10
11#[derive(TryClone, Clone, Copy, PartialEq, Eq, Hash)]
13#[try_clone(copy)]
14#[non_exhaustive]
15pub struct Token {
16 pub span: Span,
18 pub kind: Kind,
20}
21
22impl Token {
23 pub(crate) fn token_fmt(&self, cx: &MacroContext, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 match &self.kind {
26 Kind::Eof | Kind::Error => {
27 return Err(fmt::Error);
29 }
30 Kind::Ident(s) => {
31 let literal = cx.literal_source(*s, self.span).ok_or(fmt::Error)?;
32 write!(f, "{literal}")?;
33 }
34 Kind::Label(s) => {
35 let literal = cx.literal_source(*s, self.span).ok_or(fmt::Error)?;
36 write!(f, "'{literal}")?;
37 }
38 Kind::Byte(s) => match s {
39 CopySource::Text(source_id) => {
40 let s = cx
41 .idx
42 .q
43 .sources
44 .source(*source_id, self.span)
45 .ok_or(fmt::Error)?;
46 write!(f, "{s}")?;
47 }
48 CopySource::Inline(b) => {
49 write!(f, "{b:?}")?;
50 }
51 },
52 Kind::ByteStr(s) => match s {
53 StrSource::Text(text) => {
54 let span = if text.wrapped {
55 self.span.narrow(1u32)
56 } else {
57 self.span
58 };
59
60 let s = cx
61 .idx
62 .q
63 .sources
64 .source(text.source_id, span)
65 .ok_or(fmt::Error)?;
66
67 write!(f, "b\"{s}\"")?;
68 }
69 StrSource::Synthetic(id) => {
70 let b = cx.idx.q.storage.get_byte_string(*id).ok_or(fmt::Error)?;
71 write!(f, "{}", FormatBytes(b))?;
72 }
73 },
74 Kind::Str(s) => match s {
75 StrSource::Text(text) => {
76 let span = if text.wrapped {
77 self.span.narrow(1u32)
78 } else {
79 self.span
80 };
81
82 let s = cx
83 .idx
84 .q
85 .sources
86 .source(text.source_id, span)
87 .ok_or(fmt::Error)?;
88 write!(f, "\"{s}\"")?;
89 }
90 StrSource::Synthetic(id) => {
91 let s = cx.idx.q.storage.get_string(*id).ok_or(fmt::Error)?;
92 write!(f, "{s:?}")?;
93 }
94 },
95 Kind::Char(s) => match s {
96 CopySource::Text(source_id) => {
97 let s = cx
98 .idx
99 .q
100 .sources
101 .source(*source_id, self.span)
102 .ok_or(fmt::Error)?;
103 write!(f, "{s}")?;
104 }
105 CopySource::Inline(c) => {
106 write!(f, "{c:?}")?;
107 }
108 },
109 Kind::Number(s) => match s {
110 NumberSource::Text(text) => {
111 let s = cx
112 .idx
113 .q
114 .sources
115 .source(text.source_id, self.span)
116 .ok_or(fmt::Error)?;
117 write!(f, "{s}")?;
118 }
119 NumberSource::Synthetic(id) => {
120 let n = cx.idx.q.storage.get_number(*id).ok_or(fmt::Error)?;
121 write!(f, "{n}")?;
122 }
123 },
124 other => {
125 let s = other.as_literal_str().ok_or(fmt::Error)?;
126 write!(f, "{s}")?;
127 }
128 }
129
130 return Ok(());
131
132 struct FormatBytes<'a>(&'a [u8]);
133
134 impl fmt::Display for FormatBytes<'_> {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(f, "b\"")?;
137
138 for b in bytes_escape_default(self.0) {
139 write!(f, "{}", b as char)?;
140 }
141
142 write!(f, "\"")?;
143 Ok(())
144 }
145 }
146
147 fn bytes_escape_default(bytes: &[u8]) -> impl Iterator<Item = u8> + '_ {
148 bytes.iter().copied().flat_map(ascii::escape_default)
149 }
150 }
151}
152
153impl fmt::Debug for Token {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 write!(f, "{:?}@{:?}", self.kind, self.span)
156 }
157}
158
159impl Parse for Token {
160 fn parse(p: &mut Parser<'_>) -> compile::Result<Self> {
161 p.next()
162 }
163}
164
165impl Peek for Token {
166 fn peek(p: &mut super::prelude::Peeker<'_>) -> bool {
167 !p.is_eof()
168 }
169}
170
171impl ToTokens for Token {
172 fn to_tokens(
173 &self,
174 _: &mut MacroContext<'_, '_, '_>,
175 stream: &mut TokenStream,
176 ) -> alloc::Result<()> {
177 stream.push(*self)
178 }
179}
180
181impl Spanned for Token {
182 fn span(&self) -> Span {
183 self.span
184 }
185}
186
187impl IntoExpectation for Token {
188 fn into_expectation(self) -> Expectation {
189 self.kind.into_expectation()
190 }
191}
192
193#[derive(Debug, Clone, Copy, TryClone)]
195#[non_exhaustive]
196#[try_clone(copy)]
197pub enum NumberValue {
198 Float(f64),
200 Integer(i128),
202}
203
204#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
208#[try_clone(copy)]
209#[non_exhaustive]
210pub enum NumberSize {
211 S8,
213 S16,
215 S32,
217 S64,
219}
220
221impl NumberSize {
222 pub(crate) fn signed_in(&self, value: i64) -> bool {
223 self.signed_min() <= value && value <= self.signed_max()
224 }
225
226 pub(crate) fn unsigned_in(&self, value: u64) -> bool {
227 self.unsigned_min() <= value && value <= self.unsigned_max()
228 }
229
230 pub(crate) fn signed_min(&self) -> i64 {
231 match self {
232 Self::S8 => i8::MIN as i64,
233 Self::S16 => i16::MIN as i64,
234 Self::S32 => i32::MIN as i64,
235 Self::S64 => i64::MIN,
236 }
237 }
238
239 pub(crate) fn signed_max(&self) -> i64 {
240 match self {
241 Self::S8 => i8::MAX as i64,
242 Self::S16 => i16::MAX as i64,
243 Self::S32 => i32::MAX as i64,
244 Self::S64 => i64::MAX,
245 }
246 }
247
248 pub(crate) fn unsigned_min(&self) -> u64 {
249 match self {
250 Self::S8 => u8::MIN as u64,
251 Self::S16 => u16::MIN as u64,
252 Self::S32 => u32::MIN as u64,
253 Self::S64 => u64::MIN,
254 }
255 }
256
257 pub(crate) fn unsigned_max(&self) -> u64 {
258 match self {
259 Self::S8 => u8::MAX as u64,
260 Self::S16 => u16::MAX as u64,
261 Self::S32 => u32::MAX as u64,
262 Self::S64 => u64::MAX,
263 }
264 }
265}
266
267#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
269#[try_clone(copy)]
270#[non_exhaustive]
271pub enum NumberSuffix {
272 Unsigned(Span, NumberSize),
274 Signed(Span, NumberSize),
276 Float(Span),
278}
279
280#[derive(Debug, Clone, Copy, TryClone)]
282#[non_exhaustive]
283#[try_clone(copy)]
284pub struct Number {
285 pub value: NumberValue,
287 pub suffix: Option<NumberSuffix>,
289}
290
291impl Number {
292 pub(crate) fn as_u32(&self) -> Option<u32> {
294 match self.value {
295 NumberValue::Integer(n) => u32::try_from(n).ok(),
296 _ => None,
297 }
298 }
299
300 pub(crate) fn as_usize(&self) -> Option<usize> {
302 match self.value {
303 NumberValue::Integer(n) => usize::try_from(n).ok(),
304 _ => None,
305 }
306 }
307
308 pub(crate) fn as_tuple_index(&self) -> Option<usize> {
310 match self.value {
311 NumberValue::Integer(n) => usize::try_from(n).ok(),
312 _ => None,
313 }
314 }
315}
316
317macro_rules! from_unsigned {
318 ($($ty:ty),*) => {
319 $(
320 impl From<$ty> for Number {
321 #[inline]
322 fn from(value: $ty) -> Self {
323 Self {
324 value: NumberValue::Integer(value as i128),
325 suffix: None,
326 }
327 }
328 }
329 )*
330 };
331}
332
333macro_rules! from_signed {
334 ($($ty:ty),*) => {
335 $(
336 impl From<$ty> for Number {
337 #[inline]
338 fn from(value: $ty) -> Self {
339 Self {
340 value: NumberValue::Integer(value as i128),
341 suffix: None,
342 }
343 }
344 }
345 )*
346 };
347}
348
349from_unsigned!(usize, u8, u16, u32, u64);
350from_signed!(isize, i8, i16, i32, i64);
351
352impl From<f32> for Number {
353 #[inline]
354 fn from(value: f32) -> Self {
355 Self {
356 value: NumberValue::Float(value as f64),
357 suffix: None,
358 }
359 }
360}
361
362impl From<f64> for Number {
363 #[inline]
364 fn from(value: f64) -> Self {
365 Self {
366 value: NumberValue::Float(value),
367 suffix: None,
368 }
369 }
370}
371
372impl fmt::Display for Number {
373 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374 match &self.value {
375 NumberValue::Float(n) => n.fmt(f),
376 NumberValue::Integer(n) => n.fmt(f),
377 }
378 }
379}
380
381#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
383#[try_clone(copy)]
384#[non_exhaustive]
385pub enum NumberBase {
386 Decimal,
388 Hex,
390 Octal,
392 Binary,
394}
395
396impl fmt::Display for NumberBase {
397 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
398 match *self {
399 Self::Decimal => write!(fmt, "decimal"),
400 Self::Hex => write!(fmt, "hex"),
401 Self::Octal => write!(fmt, "octal"),
402 Self::Binary => write!(fmt, "binary"),
403 }
404 }
405}
406
407#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
412#[try_clone(copy)]
413#[non_exhaustive]
414pub enum BuiltIn {
415 Template,
417 Format,
419 BuiltIn,
421 Literal,
423 Doc,
425}
426
427impl BuiltIn {
428 pub(crate) fn as_str(self) -> &'static str {
430 match self {
431 Self::Template => "template",
432 Self::Format => "formatspec",
433 Self::BuiltIn => "builtin",
434 Self::Literal => "literal",
435 Self::Doc => "doc",
436 }
437 }
438}
439
440impl fmt::Display for BuiltIn {
441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
442 f.write_str(self.as_str())
443 }
444}
445
446#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
448#[try_clone(copy)]
449#[non_exhaustive]
450pub enum LitSource {
451 Text(SourceId),
453 Synthetic(SyntheticId),
455 BuiltIn(BuiltIn),
457}
458
459#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
463#[try_clone(copy)]
464#[non_exhaustive]
465pub enum StrSource {
466 Text(StrText),
468 Synthetic(SyntheticId),
470}
471
472#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
474#[try_clone(copy)]
475#[non_exhaustive]
476pub struct StrText {
477 pub source_id: SourceId,
479 pub escaped: bool,
481 pub wrapped: bool,
483}
484
485#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
487#[try_clone(copy)]
488#[non_exhaustive]
489pub enum NumberSource {
490 Text(NumberText),
493 Synthetic(SyntheticId),
495}
496
497#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
499#[try_clone(copy)]
500#[non_exhaustive]
501#[try_clone(bound = {T: TryClone})]
502pub enum CopySource<T>
503where
504 T: Copy,
505{
506 Text(SourceId),
509 Inline(T),
511}
512
513#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
515#[try_clone(copy)]
516#[non_exhaustive]
517pub struct NumberText {
518 pub source_id: SourceId,
520 pub is_fractional: bool,
524 pub base: NumberBase,
526 pub number: Span,
528 pub suffix: Span,
530}
531
532#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
534#[try_clone(copy)]
535#[non_exhaustive]
536pub enum Delimiter {
537 Parenthesis,
539 Brace,
541 Bracket,
543 Empty,
545}
546
547impl Delimiter {
548 pub(crate) fn open(self) -> &'static str {
550 match self {
551 Self::Parenthesis => "(",
552 Self::Brace => "{",
553 Self::Bracket => "[",
554 Self::Empty => "",
555 }
556 }
557
558 pub(crate) fn close(self) -> &'static str {
560 match self {
561 Self::Parenthesis => ")",
562 Self::Brace => "}",
563 Self::Bracket => "]",
564 Self::Empty => "",
565 }
566 }
567}