macro_rules_rt/
matcher.rs

1use crate::{
2    match_all::MatchAllBuilder,
3    token_entry::{
4        cts_len, CursorToken, CursorTokenTree, FindAllStringBuilder, LongToken, LongTokenTree,
5        ParseStreamEx, Source, TokenEntry, TokenStringBuilder,
6    },
7    utils::{parse_macro_stmt, to_delimiter},
8    MatchAll, Rule,
9};
10use proc_macro2::{Delimiter, Group, Span, TokenStream};
11use quote::{ToTokens, TokenStreamExt};
12use std::{collections::HashMap, ops::Range, rc::Rc, str::FromStr};
13use structmeta::{Parse, ToTokens};
14use syn::{
15    buffer::Cursor,
16    ext::IdentExt,
17    parse::{Parse, ParseStream, Parser},
18    parse_str,
19    spanned::Spanned,
20    token, Block, Error, Expr, Ident, Item, Lifetime, Lit, MacroDelimiter, Meta, Pat, Path, Result,
21    Token, Type, Visibility,
22};
23
24pub use self::macro_flag_spec::MacroFlagSpec;
25
26#[derive(Debug)]
27pub struct FindAllParts(Vec<FindAllPart>);
28
29impl FindAllParts {
30    pub fn apply_tokens(&self, index: &mut usize, input: TokenStream, rule: &Rule) -> TokenStream {
31        let mut tokens = TokenStream::new();
32        self.apply_tokens_to(index, input, rule, &mut tokens);
33        tokens
34    }
35    pub fn apply_tokens_to(
36        &self,
37        index: &mut usize,
38        input: TokenStream,
39        rule: &Rule,
40        tokens: &mut TokenStream,
41    ) {
42        (|input: ParseStream| {
43            self.apply_tokens_parser(index, input, rule, tokens);
44            Ok(())
45        })
46        .parse2(input)
47        .unwrap();
48    }
49    fn apply_tokens_parser(
50        &self,
51        index: &mut usize,
52        input: ParseStream,
53        rule: &Rule,
54        tokens: &mut TokenStream,
55    ) {
56        while *index < self.0.len() {
57            match &self.0[*index] {
58                FindAllPart::NoMatch(p) => p.apply_tokens_to(input, tokens),
59                FindAllPart::Match(p) => p.apply_tokens_to(input, rule, tokens),
60                FindAllPart::GroupOpen => {
61                    *index += 1;
62                    let Ok(g) = input.parse::<Group>() else {
63                        unreachable!()
64                    };
65                    let mut g_new =
66                        Group::new(g.delimiter(), self.apply_tokens(index, g.stream(), rule));
67                    g_new.set_span(g.span());
68                    tokens.append(g_new);
69                    assert!(matches!(self.0[*index], FindAllPart::GroupClose));
70                }
71                FindAllPart::GroupClose => return,
72            }
73            *index += 1;
74        }
75    }
76    pub fn apply_string(&self, rule: &Rule, b: &mut FindAllStringBuilder) {
77        for p in &self.0 {
78            match p {
79                FindAllPart::NoMatch(p) => b.push_no_match(p.tts_and_tes_len),
80                FindAllPart::Match(p) => p.apply_string_for_find_all(rule, b),
81                FindAllPart::GroupOpen | FindAllPart::GroupClose => b.push_no_match(1),
82            }
83        }
84        b.commit_no_match(0);
85    }
86}
87
88#[derive(Debug)]
89enum FindAllPart {
90    NoMatch(FindAllPartNoMatch),
91    Match(FindAllPartMatch),
92    GroupOpen,
93    GroupClose,
94}
95
96#[derive(Debug)]
97struct FindAllPartNoMatch {
98    tts_and_tes_len: usize,
99}
100impl FindAllPartNoMatch {
101    fn apply_tokens_to(&self, input: ParseStream, tokens: &mut TokenStream) {
102        for _ in 0..self.tts_and_tes_len {
103            let t: CursorToken = input.parse().unwrap();
104            t.to_tokens(tokens);
105        }
106    }
107}
108
109#[derive(Debug)]
110pub struct FindAllPartMatch {
111    m: RawMatch,
112    cts_len: usize,
113    pub(crate) tes_len: usize,
114}
115impl FindAllPartMatch {
116    fn apply_tokens_to(&self, input: ParseStream, rule: &Rule, tokens: &mut TokenStream) {
117        for _ in 0..self.cts_len {
118            let _: CursorTokenTree = input.parse().unwrap();
119        }
120        let mut b = MatchTokensBuilder {
121            tokens,
122            rule,
123            tes_len: self.tes_len,
124        };
125        rule.to.apply_tokens_to(&self.m, &mut b);
126    }
127    fn apply_string_for_find_all(&self, rule: &Rule, b: &mut FindAllStringBuilder) {
128        b.commit_no_match(self.tes_len);
129        self.apply_string(rule, b.b)
130    }
131    pub(crate) fn apply_string(&self, rule: &Rule, b: &mut TokenStringBuilder) {
132        rule.to.apply_string(&self.m, rule, self.tes_len, b);
133    }
134}
135
136/// Search pattern.
137///
138/// `Matcher` corresponds to `MacroMatch*` (excluding outermost brace) in [`Macros By Example`](https://doc.rust-lang.org/reference/macros-by-example.html).
139#[derive(Debug, Clone)]
140pub struct Matcher(pub(crate) Rc<PatternItems>);
141
142impl Parse for Matcher {
143    fn parse(input: ParseStream) -> Result<Self> {
144        Ok(Self(Rc::new(input.parse::<MacroMatches>()?.to_pattern()?)))
145    }
146}
147impl FromStr for Matcher {
148    type Err = Error;
149    fn from_str(s: &str) -> Result<Self> {
150        parse_str(s)
151    }
152}
153
154impl Matcher {
155    pub fn is_empty(&self) -> bool {
156        self.0.items.is_empty()
157    }
158    pub(crate) fn try_match(&self, input: &mut ParseStreamEx) -> Result<RawMatch> {
159        self.0.try_match(input)
160    }
161
162    pub(crate) fn find_all(&self, input: TokenStream, tes_offset: usize) -> FindAllParts {
163        let mut parts = Vec::new();
164        self.find_all_parts(input, tes_offset, &mut parts);
165        FindAllParts(parts)
166    }
167
168    fn find_all_parts(
169        &self,
170        input: TokenStream,
171        tes_offset: usize,
172        parts: &mut Vec<FindAllPart>,
173    ) -> bool {
174        ParseStreamEx::parse_from_tokens(input, tes_offset, |input: &mut ParseStreamEx| {
175            Ok(self.find_all_parts_parser(input, parts))
176        })
177        .unwrap()
178    }
179    fn find_all_parts_parser(
180        &self,
181        input: &mut ParseStreamEx,
182        parts: &mut Vec<FindAllPart>,
183    ) -> bool {
184        let mut tts_and_tes_len = 0;
185        let mut is_match = false;
186        while !input.is_empty() {
187            let mut fork = input.fork();
188            if let Ok(m) = self.try_match(&mut fork) {
189                if !m.is_empty {
190                    parts.push(FindAllPart::NoMatch(FindAllPartNoMatch { tts_and_tes_len }));
191                    parts.push(FindAllPart::Match(match_part(
192                        m,
193                        input.cursor(),
194                        fork.cursor(),
195                    )));
196                    input.advance_to(&fork);
197                    tts_and_tes_len = 0;
198                    is_match = true;
199                    continue;
200                }
201            }
202            if input.peek(token::Paren) || input.peek(token::Brace) || input.peek(token::Bracket) {
203                input
204                    .parse_group(|_, input| {
205                        parts.push(FindAllPart::NoMatch(FindAllPartNoMatch { tts_and_tes_len }));
206                        parts.push(FindAllPart::GroupOpen);
207                        is_match |= self.find_all_parts_parser(input, parts);
208                        parts.push(FindAllPart::GroupClose);
209                        tts_and_tes_len = 0;
210                        Ok(())
211                    })
212                    .unwrap();
213                continue;
214            }
215            if let Ok(t) = input.parse::<LongToken>() {
216                tts_and_tes_len += t.len();
217            } else {
218                // End after non-delimiter Group
219                break;
220            }
221        }
222        parts.push(FindAllPart::NoMatch(FindAllPartNoMatch { tts_and_tes_len }));
223        is_match
224    }
225
226    pub(crate) fn match_all<'a>(
227        &'a self,
228        source: Source<'a>,
229        input: TokenStream,
230        rule: &'a Rule,
231    ) -> MatchAll<'a> {
232        let mut b = MatchAllBuilder::new(source);
233        let ps = self.find_all(input, 0);
234        for p in ps.0 {
235            match p {
236                FindAllPart::NoMatch(n) => b.push_no_match(n.tts_and_tes_len),
237                FindAllPart::Match(m) => b.push_match(m),
238                FindAllPart::GroupOpen | FindAllPart::GroupClose => b.push_no_match(1),
239            }
240        }
241        b.finish(rule)
242    }
243}
244fn match_part(m: RawMatch, start: Cursor, end: Cursor) -> FindAllPartMatch {
245    FindAllPartMatch {
246        m,
247        cts_len: cts_len(start, end),
248        tes_len: TokenEntry::len_from_cursor(start, end),
249    }
250}
251
252#[derive(Debug)]
253pub struct PatternItems {
254    items: Vec<PatternItem>,
255    pub vars: HashMap<String, MacroVarRef>,
256    var_count: usize,
257    rep_count: usize,
258}
259
260impl PatternItems {
261    fn new(items: Vec<PatternItem>) -> Result<Self> {
262        let mut vars = HashMap::new();
263        let mut var_index = 0;
264        let mut rep_index = 0;
265        for item in &items {
266            match item {
267                PatternItem::Token(_) => {}
268                PatternItem::Group(g) => g.get_vars(&mut var_index, &mut rep_index, &mut vars)?,
269                PatternItem::Var(v) => v.get_vars(&mut var_index, &mut vars)?,
270                PatternItem::Rep(r) => r.get_vars(&mut rep_index, &mut vars)?,
271            }
272        }
273        Ok(Self {
274            items,
275            vars,
276            var_count: var_index,
277            rep_count: rep_index,
278        })
279    }
280    pub fn find_rep(&self, name: &str) -> Option<&RepPattern> {
281        if let Some(PatternItem::Rep(r)) = self.find_item(name) {
282            Some(r)
283        } else {
284            None
285        }
286    }
287    fn find_item(&self, name: &str) -> Option<&PatternItem> {
288        for item in &self.items {
289            match item {
290                PatternItem::Token(_) => {}
291                PatternItem::Group(g) => {
292                    if let Some(item) = g.content.find_item(name) {
293                        return Some(item);
294                    }
295                }
296                PatternItem::Var(v) => {
297                    if v.name.as_deref() == Some(name) {
298                        return Some(item);
299                    }
300                }
301                PatternItem::Rep(r) => {
302                    if r.content.vars.contains_key(name) {
303                        return Some(item);
304                    }
305                }
306            }
307        }
308        None
309    }
310    fn try_match(&self, input: &mut ParseStreamEx) -> Result<RawMatch> {
311        let mut m = RawMatch::new();
312        self.try_match_to(input, &mut m)?;
313        Ok(m)
314    }
315    fn try_match_to(&self, input: &mut ParseStreamEx, m: &mut RawMatch) -> Result<()> {
316        for item in &self.items {
317            item.try_match(input, m)?;
318        }
319        Ok(())
320    }
321}
322
323#[derive(Debug)]
324enum PatternItem {
325    Token(TokenPattern),
326    Group(GroupPattern),
327    Var(VarPattern),
328    Rep(RepPattern),
329}
330impl PatternItem {
331    fn try_match(&self, input: &mut ParseStreamEx, m: &mut RawMatch) -> Result<()> {
332        match self {
333            PatternItem::Token(t) => t.try_match_to(input, m),
334            PatternItem::Group(g) => g.try_match_to(input, m),
335            PatternItem::Var(v) => {
336                let tes_start = input.tes_offset;
337                let tokens = input.parse_with(|input| v.try_match(input))?;
338                let tes_end = input.tes_offset;
339                m.vars.push(MatchVar {
340                    tokens,
341                    tes_range: tes_start..tes_end,
342                });
343                m.is_empty = false;
344                Ok(())
345            }
346            PatternItem::Rep(r) => {
347                let m1 = r.try_match_to(input, m)?;
348                m.is_empty &= m1.0.is_empty();
349                m.reps.push(m1);
350                Ok(())
351            }
352        }
353    }
354}
355
356#[derive(Debug)]
357struct TokenPattern {
358    s: String,
359}
360
361impl TokenPattern {
362    fn new(tt: LongToken) -> Self {
363        let s = tt.to_string();
364        Self { s }
365    }
366    fn eq_token(&self, tt: &LongToken) -> bool {
367        self.s == tt.to_string()
368    }
369    fn try_match_to(&self, input: &mut ParseStreamEx, m: &mut RawMatch) -> Result<()> {
370        let span = input.span();
371        if self.eq_token(&input.parse()?) {
372            m.is_empty = false;
373            Ok(())
374        } else {
375            bail!(span, "mismatch");
376        }
377    }
378}
379
380#[derive(Debug)]
381struct GroupPattern {
382    delimiter: Delimiter,
383    content: PatternItems,
384}
385impl GroupPattern {
386    fn get_vars(
387        &self,
388        var_index: &mut usize,
389        rep_index: &mut usize,
390        vars: &mut HashMap<String, MacroVarRef>,
391    ) -> Result<()> {
392        for b in &self.content.vars {
393            let depth = b.1.depth;
394            let var_index_or_rep_index =
395                if depth == 0 { *var_index } else { *rep_index } + b.1.var_index_or_rep_index;
396            insert_var(
397                vars,
398                b.0,
399                MacroVarRef {
400                    depth: b.1.depth,
401                    var_index_or_rep_index,
402                    span: b.1.span,
403                },
404            )?;
405        }
406        *var_index += self.content.var_count;
407        *rep_index += self.content.rep_count;
408        Ok(())
409    }
410
411    fn try_match_to(&self, input: &mut ParseStreamEx, m: &mut RawMatch) -> Result<()> {
412        match self.delimiter {
413            Delimiter::Parenthesis => input.expect(token::Paren)?,
414            Delimiter::Brace => input.expect(token::Brace)?,
415            Delimiter::Bracket => input.expect(token::Bracket)?,
416            Delimiter::None => input.expect(token::Group)?,
417        }
418        input.parse_group(|_g, input| {
419            self.content.try_match_to(input, m)?;
420            m.is_empty = false;
421            Ok(())
422        })
423    }
424}
425
426#[derive(Debug)]
427struct VarPattern {
428    name: Option<String>,
429    name_span: Span,
430    flag: MacroFlagSpec,
431}
432impl VarPattern {
433    fn get_vars(
434        &self,
435        var_index: &mut usize,
436        vars: &mut HashMap<String, MacroVarRef>,
437    ) -> Result<()> {
438        if let Some(name) = &self.name {
439            insert_var(
440                vars,
441                name,
442                MacroVarRef {
443                    depth: 0,
444                    var_index_or_rep_index: *var_index,
445                    span: self.name_span,
446                },
447            )?;
448            *var_index += 1;
449        }
450        Ok(())
451    }
452
453    fn try_match(&self, input: ParseStream) -> Result<TokenStream> {
454        Ok(match self.flag {
455            MacroFlagSpec::Block(_) => input.parse::<Block>()?.to_token_stream(),
456            MacroFlagSpec::Expr(_) => input.parse::<Expr>()?.to_token_stream(),
457            MacroFlagSpec::Ident(_) => Ident::parse_any(input)?.to_token_stream(),
458            MacroFlagSpec::Item(_) => input.parse::<Item>()?.to_token_stream(),
459            MacroFlagSpec::Lifetime(_) => input.parse::<Lifetime>()?.to_token_stream(),
460            MacroFlagSpec::Literal(_) => input.parse::<Lit>()?.to_token_stream(),
461            MacroFlagSpec::Meta(_) => input.parse::<Meta>()?.to_token_stream(),
462            MacroFlagSpec::Pat(_) => Pat::parse_multi_with_leading_vert(input)?.to_token_stream(),
463            MacroFlagSpec::PatParam(_) => Pat::parse_single(input)?.to_token_stream(),
464            MacroFlagSpec::Path(_) => input.parse::<Path>()?.to_token_stream(),
465            MacroFlagSpec::Stmt(_) => parse_macro_stmt(input)?.to_token_stream(),
466            MacroFlagSpec::Tt(_) => input.parse::<LongTokenTree>()?.to_token_stream(),
467            MacroFlagSpec::Ty(_) => input.parse::<Type>()?.to_token_stream(),
468            MacroFlagSpec::Vis(_) => input.parse::<Visibility>()?.to_token_stream(),
469        })
470    }
471}
472
473#[derive(Debug)]
474pub struct RepPattern {
475    pub content: PatternItems,
476    sep: Option<TokenPattern>,
477    pub op: MacroRepOp,
478}
479impl RepPattern {
480    fn get_vars(
481        &self,
482        rep_index: &mut usize,
483        vars: &mut HashMap<String, MacroVarRef>,
484    ) -> Result<()> {
485        for b in &self.content.vars {
486            insert_var(
487                vars,
488                b.0,
489                MacroVarRef {
490                    depth: 1 + b.1.depth,
491                    var_index_or_rep_index: *rep_index,
492                    span: b.1.span,
493                },
494            )?;
495        }
496        *rep_index += 1;
497        Ok(())
498    }
499
500    fn try_match_to(&self, input: &mut ParseStreamEx, m: &mut RawMatch) -> Result<MatchRep> {
501        let mut ms = Vec::new();
502        let mut is_next = false;
503        while !input.is_empty() {
504            let mut fork = input.fork();
505            if is_next {
506                if let Some(sep) = &self.sep {
507                    sep.try_match_to(&mut fork, m)?;
508                }
509            }
510            if let Ok(m) = self.content.try_match(&mut fork) {
511                if !m.is_empty || self.sep.is_some() {
512                    ms.push(m);
513                    input.advance_to(&fork);
514                    if self.op.is_zero_or_one() {
515                        break;
516                    }
517                    is_next = true;
518                    continue;
519                }
520            }
521            if self.op.is_one_or_more() && !is_next {
522                bail!(input.span(), "expected at least one repetition")
523            }
524            break;
525        }
526        Ok(MatchRep(ms))
527    }
528}
529
530#[derive(Debug)]
531pub struct MacroVarRef {
532    pub depth: usize,
533
534    // if depth == 0, this is the index of `Match::vars`
535    // if depth > 0, this is the index of `Match::reps`
536    pub var_index_or_rep_index: usize,
537    span: Span,
538}
539fn insert_var(vars: &mut HashMap<String, MacroVarRef>, name: &str, var: MacroVarRef) -> Result<()> {
540    if vars.contains_key(name) {
541        bail!(var.span, "duplicate metavariable `{name}`")
542    }
543    vars.insert(name.to_owned(), var);
544    Ok(())
545}
546
547struct MacroMatches(Vec<MacroMatch>);
548
549impl Parse for MacroMatches {
550    fn parse(input: ParseStream) -> Result<Self> {
551        let mut ms = Vec::new();
552        while !input.is_empty() {
553            ms.push(input.parse()?);
554        }
555        Ok(Self(ms))
556    }
557}
558impl ToTokens for MacroMatches {
559    fn to_tokens(&self, tokens: &mut TokenStream) {
560        for m in &self.0 {
561            m.to_tokens(tokens);
562        }
563    }
564}
565
566impl MacroMatches {
567    fn to_pattern(&self) -> Result<PatternItems> {
568        PatternItems::new(
569            self.0
570                .iter()
571                .map(|m| m.to_pattern())
572                .collect::<Result<Vec<PatternItem>>>()?,
573        )
574    }
575}
576
577#[derive(ToTokens)]
578enum MacroMatch {
579    Token(LongToken),
580    Matcher(MacroMatcher),
581    Var(MacroVar),
582    Rep(MacroRep),
583}
584impl MacroMatch {
585    fn to_pattern(&self) -> Result<PatternItem> {
586        Ok(match self {
587            Self::Token(token) => PatternItem::Token(TokenPattern::new(token.clone())),
588            Self::Matcher(m) => m.to_pattern()?,
589            Self::Var(f) => PatternItem::Var(f.to_pattern()?),
590            Self::Rep(r) => PatternItem::Rep(r.to_pattern()?),
591        })
592    }
593}
594impl Parse for MacroMatch {
595    fn parse(input: ParseStream) -> Result<Self> {
596        if input.peek(token::Bracket) || input.peek(token::Brace) || input.peek(token::Paren) {
597            Ok(Self::Matcher(input.parse()?))
598        } else {
599            if input.peek(Token![$]) {
600                if input.peek2(Ident) {
601                    return Ok(Self::Var(input.parse()?));
602                } else if input.peek2(token::Paren) {
603                    return Ok(Self::Rep(input.parse()?));
604                }
605            }
606            Ok(Self::Token(input.parse()?))
607        }
608    }
609}
610
611#[derive(Parse, ToTokens)]
612struct MacroMatcher {
613    #[to_tokens("(")]
614    delimiter: MacroDelimiter,
615    content: MacroMatches,
616}
617impl MacroMatcher {
618    fn to_pattern(&self) -> Result<PatternItem> {
619        let delimiter = to_delimiter(&self.delimiter);
620        let content = self.content.to_pattern()?;
621        Ok(PatternItem::Group(GroupPattern { delimiter, content }))
622    }
623}
624
625#[derive(Parse, ToTokens)]
626struct MacroVar {
627    dollar_token: Token![$],
628    name: MacroVarName,
629    colon_token: Token![:],
630    flag: MacroFlagSpec,
631}
632impl MacroVar {
633    fn to_pattern(&self) -> Result<VarPattern> {
634        Ok(VarPattern {
635            name: self.name.to_option_string(),
636            name_span: self.name.span(),
637            flag: self.flag,
638        })
639    }
640}
641
642#[derive(Clone, Debug, Parse, ToTokens)]
643enum MacroVarName {
644    Underscore(#[parse(peek)] token::Underscore),
645    Ident(#[parse(peek, any)] Ident),
646}
647impl MacroVarName {
648    fn to_option_string(&self) -> Option<String> {
649        match self {
650            Self::Underscore(_) => None,
651            Self::Ident(i) => Some(i.to_string()),
652        }
653    }
654}
655
656mod macro_flag_spec {
657    use structmeta::{Parse, ToTokens};
658    use syn::custom_keyword;
659
660    custom_keyword!(block);
661    custom_keyword!(expr);
662    custom_keyword!(ident);
663    custom_keyword!(item);
664    custom_keyword!(lifetime);
665    custom_keyword!(literal);
666    custom_keyword!(meta);
667    custom_keyword!(pat);
668    custom_keyword!(pat_param);
669    custom_keyword!(path);
670    custom_keyword!(stmt);
671    custom_keyword!(tt);
672    custom_keyword!(ty);
673    custom_keyword!(vis);
674
675    #[derive(Copy, Clone, Debug, Parse, ToTokens)]
676    pub enum MacroFlagSpec {
677        Block(#[parse(peek)] block),
678        Expr(#[parse(peek)] expr),
679        Ident(#[parse(peek)] ident),
680        Item(#[parse(peek)] item),
681        Lifetime(#[parse(peek)] lifetime),
682        Literal(#[parse(peek)] literal),
683        Meta(#[parse(peek)] meta),
684        Pat(#[parse(peek)] pat),
685        PatParam(#[parse(peek)] pat_param),
686        Path(#[parse(peek)] path),
687        Stmt(#[parse(peek)] stmt),
688        Tt(#[parse(peek)] tt),
689        Ty(#[parse(peek)] ty),
690        Vis(#[parse(peek)] vis),
691    }
692}
693
694#[derive(Debug)]
695pub struct RawMatch {
696    pub vars: Vec<MatchVar>,
697    pub reps: Vec<MatchRep>,
698    is_empty: bool,
699}
700impl RawMatch {
701    fn new() -> Self {
702        Self {
703            vars: Vec::new(),
704            reps: Vec::new(),
705            is_empty: true,
706        }
707    }
708}
709
710#[derive(Debug)]
711pub struct MatchVar {
712    tokens: TokenStream,
713    tes_range: Range<usize>,
714}
715
716impl MatchVar {
717    pub fn apply_tokens_to(&self, b: &mut MatchTokensBuilder) {
718        if let Some(find_all) = self.try_find_all(b.rule, b.tes_len) {
719            find_all.apply_tokens_to(&mut 0, self.tokens.clone(), b.rule, b.tokens);
720        } else {
721            self.tokens.to_tokens(b.tokens);
722        }
723    }
724    pub fn apply_string(&self, b: &mut MatchStringBuilder) {
725        if let Some(find_all) = self.try_find_all(b.rule, b.tes_len) {
726            find_all.apply_string(
727                b.rule,
728                &mut FindAllStringBuilder::new(b.b, self.tes_range.start),
729            );
730        } else {
731            b.b.push_tes(self.tes_range.clone());
732        }
733    }
734    fn try_find_all(&self, rule: &Rule, tes_len: usize) -> Option<FindAllParts> {
735        let tes_range = self.tes_range.clone();
736        if tes_range.end - tes_range.start < tes_len && rule.nest {
737            Some(rule.from.find_all(self.tokens.clone(), tes_range.start))
738        } else {
739            None
740        }
741    }
742}
743
744#[derive(Debug)]
745pub struct MatchRep(pub Vec<RawMatch>);
746
747#[derive(Parse, ToTokens)]
748struct MacroRep {
749    dollar_token: Token![$],
750    #[to_tokens("(")]
751    paren_token: token::Paren,
752    content: MacroMatches,
753    #[to_tokens(")")]
754    sep: MacroRepSep,
755    op: MacroRepOp,
756}
757impl MacroRep {
758    fn to_pattern(&self) -> Result<RepPattern> {
759        let content = self.content.to_pattern()?;
760        Ok(RepPattern {
761            content,
762            sep: self.sep.0.as_ref().map(|tt| TokenPattern::new(tt.clone())),
763            op: self.op,
764        })
765    }
766}
767#[derive(ToTokens, Debug, Clone)]
768pub struct MacroRepSep(pub Option<LongToken>);
769
770impl Parse for MacroRepSep {
771    fn parse(input: ParseStream) -> Result<Self> {
772        Ok(Self(if input.fork().parse::<MacroRepOp>().is_ok() {
773            None
774        } else {
775            Some(input.parse()?)
776        }))
777    }
778}
779
780#[derive(Clone, Copy, Debug, Parse, ToTokens, PartialEq)]
781pub enum MacroRepOp {
782    ZeroOrMore(#[parse(peek)] Token![*]),
783    OneOrMore(#[parse(peek)] Token![+]),
784    ZeroOrOne(#[parse(peek)] Token![?]),
785}
786
787impl MacroRepOp {
788    pub fn is_one_or_more(self) -> bool {
789        matches!(self, Self::OneOrMore(_))
790    }
791    pub fn is_zero_or_one(self) -> bool {
792        matches!(self, Self::ZeroOrOne(_))
793    }
794}
795
796pub struct MatchStringBuilder<'a, 'b> {
797    pub b: &'a mut TokenStringBuilder<'b>,
798    pub rule: &'a Rule,
799    pub tes_len: usize,
800    pub is_ready_string: bool,
801}
802
803pub struct MatchTokensBuilder<'a> {
804    pub tokens: &'a mut TokenStream,
805    pub rule: &'a Rule,
806    pub tes_len: usize,
807}