proc_macro_rules/
match_set.rs1use proc_macro2::Span;
2use std::collections::HashSet;
3use syn::parse::{Error, ParseBuffer, ParseStream};
4
5pub struct MatchSet<'a, M: Fork> {
6 positions: Vec<Position<'a, M>>,
7 garbage: HashSet<usize>,
8}
9
10pub trait Fork {
11 type Parent;
12
13 fn fork(&self) -> Self;
14 fn new() -> Self;
15 fn hoist(&self, outer: &mut Self::Parent);
16}
17
18pub struct Position<'a, M: Fork> {
19 pub input: ParseBuffer<'a>,
20 pub matches: M,
21 state: FragmentState,
22}
23
24#[derive(Clone, Copy, Eq, PartialEq, Debug)]
25enum FragmentState {
26 Ready,
27 Exhausted,
28}
29
30pub struct MatchHandler<'a, 'b: 'a, M: Fork> {
31 outer_position: &'a mut Position<'b, M>,
32 forked: Vec<Position<'b, M>>,
33}
34
35impl<'a, M: Fork> MatchSet<'a, M> {
36 pub fn new(initial: ParseBuffer<'a>) -> MatchSet<'a, M> {
37 MatchSet {
38 positions: vec![Position {
39 input: initial,
40 matches: M::new(),
41 state: FragmentState::Ready,
42 }],
43 garbage: HashSet::new(),
44 }
45 }
46
47 pub fn finalise(self) -> syn::parse::Result<Vec<Position<'a, M>>> {
48 if self.positions.is_empty() {
49 return Err(Error::new(Span::call_site(), "No match"));
50 }
51 Ok(self.positions)
52 }
53
54 pub fn fork<F>(&mut self, mut f: F) -> bool
56 where
57 for<'b> F: FnMut(ParseBuffer<'a>, &mut MatchHandler<'b, 'a, M>) -> Result<(), Error>,
58 {
59 debug_assert!(self.garbage.is_empty());
60
61 let mut forked = vec![];
62 for p in self.positions.iter_mut() {
63 if p.state != FragmentState::Ready {
64 continue;
65 }
66 p.state = FragmentState::Exhausted;
67 let forked_input = p.input.fork();
68 let mut match_handler = MatchHandler {
69 outer_position: p,
70 forked: vec![],
71 };
72 if f(forked_input, &mut match_handler).is_ok() {
73 forked.append(&mut match_handler.forked);
74 }
75 }
76
77 self.positions
78 .iter()
79 .filter(|p| p.state == FragmentState::Ready)
80 .count()
81 > 0
82 }
83
84 pub fn reset_states(&mut self) {
85 for p in self.positions.iter_mut() {
86 p.state = FragmentState::Ready;
87 }
88 }
89
90 pub fn expect<F>(&mut self, mut f: F) -> Result<(), Error>
92 where
93 for<'b> F: FnMut(ParseStream<'b>, &'b mut M) -> Result<(), Error>,
94 {
95 debug_assert!(self.garbage.is_empty());
96
97 for (i, p) in self.positions.iter_mut().enumerate() {
98 match f(&p.input, &mut p.matches) {
99 Ok(_) => {}
100 Err(_) => {
101 self.garbage.insert(i);
102 }
103 }
104 }
105
106 self.compact();
107
108 if self.positions.is_empty() {
109 Err(Error::new(Span::call_site(), "no positions passed expect"))
110 } else {
111 Ok(())
112 }
113 }
114
115 fn compact(&mut self) {
116 if self.garbage.is_empty() {
117 return;
118 }
119
120 let mut new = Vec::with_capacity(self.positions.len() - self.garbage.len());
121 for (i, p) in self.positions.drain(..).enumerate() {
122 if !self.garbage.contains(&i) {
123 new.push(p);
124 }
125 }
126
127 self.positions = new;
128 self.garbage = HashSet::new();
129 }
130}
131
132impl<'a, M: Fork> Position<'a, M> {
133 pub fn stream(&'a self) -> ParseStream<'a> {
134 &self.input
135 }
136
137 pub fn fork(&self) -> Position<'a, M> {
138 Position {
139 input: self.input.fork(),
140 matches: self.matches.fork(),
141 state: FragmentState::Ready,
142 }
143 }
144}
145
146impl<'a, 'b: 'a, M: Fork> MatchHandler<'a, 'b, M> {
147 pub fn hoist<MM: Fork<Parent = M>>(&mut self, positions: &[Position<'b, MM>]) {
148 assert!(!positions.is_empty());
149
150 for p in &positions[1..] {
151 let mut new = Position {
152 input: p.input.fork(),
153 matches: self.outer_position.matches.fork(),
154 state: FragmentState::Ready,
155 };
156 p.matches.hoist(&mut new.matches);
157 self.forked.push(new);
158 }
159
160 positions[0].matches.hoist(&mut self.outer_position.matches);
161 let _: Result<proc_macro2::TokenStream, _> = self.outer_position.input.parse();
162 self.outer_position.state = FragmentState::Ready;
163 self.outer_position.input = positions[0].input.fork();
164 }
165
166 pub fn matches(&mut self) -> &mut M {
167 &mut self.outer_position.matches
168 }
169}