core_extensions_proc_macros/
macro_utils_shared.rs

1use crate::{
2    used_proc_macro::{
3        token_stream::IntoIter,
4        Delimiter, Group, Ident, Punct, Literal, TokenStream, TokenTree, Spacing, Span,
5    },
6    parsing_shared::{parenthesize_ts, out_ident},
7    mmatches, try_,
8};
9
10use core::{
11    iter::{Peekable, once},
12    ops::Range,
13};
14
15use alloc::{
16    string::{String, ToString},
17    format,
18};
19
20
21
22pub(crate) mod cmp_ts;
23pub(crate) mod list_generation;
24
25
26
27pub(crate) fn macro_span() -> Span {
28    #[cfg(not(feature = "rust_1_45"))]
29    let span = Span::call_site();
30
31    #[cfg(feature = "rust_1_45")]
32    let span = Span::mixed_site();
33
34    span
35}
36
37
38macro_rules! match_token {
39    ($msg:expr, $matched:expr => $($branches:tt)* ) => {
40        match $matched {
41            $($branches)*
42            Some(tt) => {
43                // let mut msg = format!("{}, found: {:?}", $msg, tt);
44
45                return Err(crate::Error::one_tt(tt.span(), &$msg));
46            }
47            None =>{
48                return Err(crate::Error::end($msg))
49            }
50        }
51    };
52} pub(crate) use match_token;
53
54
55#[allow(dead_code)]
56pub(crate) fn parse_integer<I>(mut input: I) -> crate::Result<usize>
57where
58    I: Iterator<Item = TokenTree>
59{
60    match_token!{"expected a decimal integer", input.next() => 
61        Some(TokenTree::Literal(lit)) => {
62            lit.to_string().parse::<usize>()
63                .map_err(|_| crate::Error::one_tt(lit.span(), "expected a decimal integer") )
64        }
65    }
66}
67
68pub(crate) fn parse_count_param<I>(input: I) -> crate::Result<(usize, Span)> 
69where
70    I: IntoIterator<Item = TokenTree>,
71{
72    const MSG: &str = "\
73        expected either `count(....)` or an integer literal\
74    ";
75
76    let sident;
77
78    let mut input = input.into_iter();
79
80    match_token!{MSG, input.next() =>
81        Some(TokenTree::Ident(ident)) if {
82            sident = ident.to_string();
83            sident == "count"
84        } => {
85            match_token!{"expected parentheses", input.next() =>
86                Some(TokenTree::Group(group)) => {
87                    Ok((group.stream().into_iter().count() as usize, group.span()))
88                }
89            }
90        }
91        Some(TokenTree::Group(group)) if mmatches!(group.delimiter(), Delimiter::None) => {
92            let mut iter = group.stream().into_iter();
93            let res = parse_count_param(&mut iter);
94
95            if let Some(tt) = iter.next() {
96                return Err(Error::one_tt(tt.span(), "Expected no more tokens after integer"));
97            }
98
99            res
100        }
101        Some(TokenTree::Literal(lit)) => {
102            const IL_MSG: &str = "could not parse integer literal";
103
104            let int = try_!(lit.to_string().parse::<usize>(),
105                map_err = |_| crate::Error::one_tt(lit.span(), IL_MSG) 
106            );
107
108            Ok((int, lit.span()))
109        }
110    }
111}
112
113
114
115pub(crate) struct CountAnd<U> {
116    pub(crate) count: usize,
117    #[allow(dead_code)]
118    pub(crate) count_span: Span,
119    pub(crate) other: U,
120}
121
122pub(crate) fn parse_count_and<I, F, U>(iter: I, func: F) -> crate::Result<CountAnd<U>>
123where
124    I: IntoIterator<Item = TokenTree>,
125    F: FnOnce(&mut I::IntoIter) -> crate::Result<U>,
126{
127    let mut iter = iter.into_iter();
128
129    let (count, count_span) = try_!(parse_count_param(&mut iter));
130
131    try_!(parse_check_punct(&mut iter, ','));
132
133    let other = try_!(func(&mut iter));
134
135    try_!(expect_no_tokens(iter));
136
137    Ok(CountAnd{count, count_span, other})
138}
139
140
141////////////////////////////////////////////////////////////////////////////////
142
143pub(crate) struct RangeB {
144    pub(crate) start: usize,
145    pub(crate) end: Option<usize>,
146    pub(crate) spans: Spans,
147}
148
149pub(crate) fn parse_start_bound(input: &mut Peekable<IntoIter>) -> crate::Result<(usize, Span)> {
150    match input.peek() {
151        Some(TokenTree::Punct(p)) if p.as_char() == '.' => Ok((0, p.span())),
152        _=> parse_count_param(&mut *input)
153    }
154}
155
156pub(crate) fn parse_range_param(input: &mut Peekable<IntoIter>) -> crate::Result<RangeB> {
157    let (start, start_span) = try_!(parse_start_bound(&mut *input));
158    let (end, end_span);
159
160    let range_ty = try_!(parse_range_operator(&mut *input));
161    
162    match range_ty {
163        RangeType::Inclusive|RangeType::Exclusive=> {
164            let (end_, end_span_) = try_!(parse_count_param(input));
165            end = if let RangeType::Inclusive = range_ty {
166                Some(end_.saturating_add(1))
167            } else {
168                Some(end_)
169            };
170            end_span = end_span_;
171        }
172        RangeType::RangeStart => {
173            end = None;
174            end_span = start_span;
175        }
176    }
177
178    let spans = Spans {start: start_span, end: end_span};
179    Ok(RangeB{start, end, spans})
180}
181
182pub(crate) fn parse_bounded_range_param(
183    input: &mut Peekable<IntoIter>,
184) -> crate::Result<Range<usize>> {
185    let RangeB{start, end, spans} = try_!(parse_range_param(input));
186    const ERR_MSG: &str =  "Expected a finite range";
187    let end = match end {
188        Some(x) => x,
189        None => return Err(crate::Error::with_spans(spans, ERR_MSG)),
190    };
191    Ok(start .. end)
192}
193
194pub(crate) fn parse_unbounded_range_param(
195    input: &mut Peekable<IntoIter>,
196) -> crate::Result<Range<usize>> {
197    let RangeB{start, end, ..} = try_!(parse_range_param(input));
198    let end = end.unwrap_or(!0);
199    Ok(start .. end)
200}
201
202// Implicitly unbounded
203pub(crate) fn parse_int_or_range_param(
204    input: &mut Peekable<IntoIter>,
205) -> crate::Result<RangeB> {
206    let (start, start_span) = try_!(parse_start_bound(&mut *input));
207    let mut end_span = start_span;
208
209    let end = match try_!(parse_range_operator_opt(&mut *input)) {
210        Some(RangeType::RangeStart) => None,
211        Some(range_ty) => {
212            let (end_, end_span_) = try_!(parse_count_param(input));
213            end_span = end_span_;
214            if let RangeType::Inclusive = range_ty {
215                Some(end_.saturating_add(1))
216            } else {
217                Some(end_)
218            }
219        },
220        None => Some(start.saturating_add(1)),
221    };
222
223    let spans = Spans{start: start_span, end: end_span};
224    Ok(RangeB{start, end, spans})
225}
226
227
228
229pub(crate)  enum RangeType {
230    Inclusive,
231    Exclusive,
232    RangeStart,
233}
234
235fn parse_range_operator_inner(input: &mut Peekable<IntoIter>) -> crate::Result<RangeType> { 
236    match_token!{"expected a range", input.next() =>
237        Some(TokenTree::Punct(_)) => {}
238    }
239
240    match input.peek() {
241        Some(TokenTree::Punct(punct)) if punct.as_char() == '=' => {
242            input.next();
243            Ok(RangeType::Inclusive)
244        },
245        Some(_) => Ok(RangeType::Exclusive),
246        None=> Ok(RangeType::RangeStart),
247    }
248}
249
250fn parse_range_operator(input: &mut Peekable<IntoIter>) -> crate::Result<RangeType> {
251    match_token!{"expected a range", input.next() => 
252        Some(TokenTree::Punct(punct)) if
253            punct.as_char() == '.' && mmatches!(punct.spacing(), Spacing::Joint) 
254        => {
255            parse_range_operator_inner(input)
256        }
257    }
258}
259
260fn parse_range_operator_opt(input: &mut Peekable<IntoIter>) -> crate::Result<Option<RangeType>> {
261    match input.next() {
262        Some(TokenTree::Punct(punct)) if
263            punct.as_char() == '.' && mmatches!(punct.spacing(), Spacing::Joint) 
264        => {
265            parse_range_operator_inner(input).map(Some)
266        }
267        Some(tt) => Err(crate::Error::one_tt(tt.span(), "expected a range")),
268        None => Ok(None)
269    }
270}
271
272
273////////////////////////////////////////////////////////////////////////////////
274
275pub(crate) fn parse_parentheses<I>(mut input: I) -> crate::Result<Group>
276where
277    I: Iterator<Item = TokenTree>
278{
279    match_token!{"expected parentheses", input.next() => 
280        Some(TokenTree::Group(group)) if mmatches!(group.delimiter(), Delimiter::Parenthesis) => {
281            Ok(group)
282        }
283    }
284}
285
286#[allow(dead_code)]
287pub(crate) fn assert_parentheses(tt: TokenTree) -> crate::Result<Group> {
288    match tt {
289        TokenTree::Group(group) if mmatches!(group.delimiter(), Delimiter::Parenthesis) => 
290            Ok(group),
291        tt => Err(crate::Error::one_tt(tt.span(), "expected parentheses"))
292    }
293}
294
295pub(crate) fn parse_group<I>(mut input: I) -> crate::Result<Group>
296where
297    I: Iterator<Item = TokenTree>
298{
299    match_token!{"expected `(`, `{`, or `[`", input.next() => 
300        Some(TokenTree::Group(group)) if !mmatches!(group.delimiter(), Delimiter::None) => {
301            Ok(group)
302        }
303    }
304}
305
306////////////////////////////////////////////////////////////////////////////////
307
308pub(crate) fn parse_ident<I>(mut input: I) -> crate::Result<Ident>
309where
310    I: Iterator<Item = TokenTree>
311{
312    match_token!{"expected identifier", input.next() => 
313        Some(TokenTree::Group(group)) if mmatches!(group.delimiter(), Delimiter::None) => {
314            parse_ident(group.stream().into_iter())
315        }
316        Some(TokenTree::Ident(ident)) => {
317            Ok(ident)
318        }
319    }
320}
321
322////////////////////////////////////////////////////////////////////////////////
323
324pub(crate) fn parse_keyword<I>(mut input: I, keyword: &str) -> crate::Result<Ident>
325where
326    I: Iterator<Item = TokenTree>
327{
328    match_token!{&format!("expected {:?}", keyword), input.next() => 
329        Some(TokenTree::Ident(ident)) if ident.to_string() == keyword => {
330            Ok(ident)
331        }
332    }
333}
334
335////////////////////////////////////////////////////////////////////////////////
336
337pub(crate) fn parse_check_punct<I>(mut input: I, punct: char) -> crate::Result<Punct>
338where
339    I: Iterator<Item = TokenTree>
340{
341    match_token!{&format!("expected {:?}", punct), input.next() => 
342        Some(TokenTree::Punct(p)) if p.as_char() == punct => {
343            Ok(p)
344        }
345    }
346}
347
348////////////////////////////////////////////////////////////////////////////////
349
350
351
352////////////////////////////////////////////////////////////////////////////////
353
354
355pub(crate) struct PathAndSpan {
356    pub(crate) path: TokenStream,
357    pub(crate) start_span: Span,
358    pub(crate) end_span: Span,
359    pub(crate) terminator: Option<TokenTree>,
360}
361
362pub(crate) fn parse_path_and_span<I>(
363    iter: I
364) -> crate::Result<PathAndSpan> 
365where
366    I: IntoIterator<Item = TokenTree>
367{
368    let mut this = PathAndSpan{
369        path: TokenStream::new(),
370        start_span: Span::call_site(),
371        end_span: Span::call_site(),
372        terminator: None,
373    };
374
375    let mut start = true;
376
377    for tt in iter {
378        if start {
379            this.start_span = tt.span();
380            start = false;
381        } else {
382            this.end_span = tt.span();
383        };
384
385        macro_rules! return_ {
386            ($tt:expr) => ({
387                this.terminator = Some($tt);
388                return Ok(this);
389            });
390        }
391
392        match tt {
393            TokenTree::Group(group) => {
394                if mmatches!(group.delimiter(), Delimiter::None) {
395                    this.path.extend(group.stream());
396                } else {
397                    return_!(TokenTree::Group(group))
398                }
399            }
400            TokenTree::Punct(punct) => {
401                if punct.as_char() == ':' {
402                    this.path.extend(once(TokenTree::Punct(punct)));
403                } else {
404                    return_!(TokenTree::Punct(punct))
405                }
406            },
407            tt @ TokenTree::Literal(_) => return_!(tt),
408            x @ TokenTree::Ident(_) => {
409                this.path.extend(once(x));
410            }
411        }
412    }
413
414    Ok(this)
415}
416
417
418////////////////////////////////////////////////////////////////////////////////
419
420
421pub(crate) fn expect_no_tokens<I>(iter: I) -> Result<(), crate::Error>
422where
423    I: IntoIterator<Item = TokenTree>
424{
425    if let Some(tt) = iter.into_iter().next() {
426        let msg = "expected no more tokens, starting from this one";
427        Err(crate::Error::one_tt(tt.span(), msg))
428    } else {
429        Ok(())
430    }
431}
432
433
434////////////////////////////////////////////////////////////////////////////////
435
436pub(crate) fn usize_tt(n: usize, span: Span) -> TokenTree {
437    let mut lit = Literal::usize_unsuffixed(n);
438    lit.set_span(span);
439    TokenTree::Literal(lit)
440}
441
442////////////////////////////////////////////////////////////////////////////////
443
444pub(crate) fn out_parenthesized_tt(tt: TokenTree, out: &mut TokenStream) {
445    let span = tt.span();
446    out.extend(once(parenthesize_ts(tt.into(), span)));
447}
448
449pub(crate) fn braced_ts(ts: TokenStream, span: Span) -> TokenTree {
450    let mut group = Group::new(Delimiter::Brace, ts);
451    group.set_span(span);
452    TokenTree::Group(group)
453}
454
455pub(crate) fn out_braced_tt(tt: TokenTree, out: &mut TokenStream) {
456    let span = tt.span();
457    out.extend(once(braced_ts(tt.into(), span)));
458}
459
460////////////////////////////////////////////////////////////////////////////////
461
462#[derive(Copy, Clone)]
463pub(crate) struct Spans {
464    pub(crate) start: Span,
465    pub(crate) end: Span,
466}
467
468impl Spans {
469    #[inline(always)]
470    pub(crate) fn new(start: Span, end: Span) -> Self {
471        Self{start, end}
472    }
473}
474
475////////////////////////////////////////////////////////////////////////////////
476
477pub(crate) struct RepeatTimes<I> {
478    cloned: I,
479    iter: I,
480    times: usize,
481}
482
483impl<I> RepeatTimes<I>
484where
485    I: Iterator + Clone
486{
487    pub fn new(times: usize, iter: I) -> Self {
488        let cloned = iter.clone();
489        Self{cloned, iter, times}
490    }
491}
492
493impl<I> Iterator for RepeatTimes<I> 
494where
495    I: Iterator + Clone
496{
497    type Item = I::Item;
498
499    fn next(&mut self) -> Option<I::Item> {
500        loop {
501            match self.iter.next() {
502                x @ Some(_) => return x,
503                None if self.times <= 1 => return None,
504                None => {
505                    self.iter = self.cloned.clone();
506                    self.times -= 1;
507                }
508            }
509        }
510    }
511}
512
513////////////////////////////////////////////////////////////////////////////////
514
515
516pub(crate) struct Error {
517    spans: Spans,
518    message: String,
519}
520
521impl Error {
522    #[allow(dead_code)]
523    pub(crate) fn new(start_span: Span, end_span: Span, message: &str) -> Self {
524        Self {
525            spans: Spans::new(start_span, end_span),
526            message: message.into(),
527        }
528    }
529
530    pub(crate) fn with_spans(spans: Spans, message: &str) -> Self {
531        Self {
532            spans,
533            message: message.into(),
534        }
535    }
536
537    pub(crate) fn one_tt(span: Span, message: &str) -> Self {
538        Self {
539            spans: Spans::new(span, span),
540            message: message.into(),
541        }
542    }
543
544    pub(crate) fn end(message_: &str) -> Self {
545        let mut message = "tokens ended before parsing finished, ".to_string();
546        message.push_str(message_);
547
548        Self {
549            spans: Spans::new(Span::call_site(), Span::call_site()),
550            message,
551        }
552    }
553
554    pub(crate) fn start_span(&self) -> Span {
555        self.spans.start
556    }
557    #[allow(dead_code)]
558    pub(crate) fn end_span(&self) -> Span {
559        self.spans.end
560    }
561
562    pub(crate) fn into_compile_error(self) -> TokenStream {
563        self.to_compile_error()
564    }
565    pub(crate) fn to_compile_error(&self) -> TokenStream {
566        let Error { ref message, spans: Spans{start: start_span, end: end_span} } = *self;
567
568        let mut out = TokenStream::new();
569
570        out_ident("compile_error", start_span, &mut out);
571
572        let mut bang = Punct::new('!', Spacing::Alone);
573        bang.set_span(start_span);
574        out.extend(once(TokenTree::Punct(bang)));
575
576        let mut msg = Literal::string(message);
577        msg.set_span(end_span);
578        let msg = TokenStream::from(TokenTree::from(msg));
579
580        let mut group = Group::new(Delimiter::Brace, msg);
581        group.set_span(end_span);
582        out.extend(once(TokenTree::Group(group)));
583
584        out
585    }
586}
587
588impl From<Error> for TokenStream {
589    fn from(err: Error) -> TokenStream {
590        err.into_compile_error()
591    }
592}
593
594
595