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#[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 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 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}