diff options
Diffstat (limited to 'crates/mbe/src/expander/matcher.rs')
-rw-r--r-- | crates/mbe/src/expander/matcher.rs | 94 |
1 files changed, 50 insertions, 44 deletions
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 987a4f676..800931cd1 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs | |||
@@ -70,7 +70,7 @@ pub(super) struct Match { | |||
70 | } | 70 | } |
71 | 71 | ||
72 | impl Match { | 72 | impl Match { |
73 | pub(super) fn add_err(&mut self, err: ExpandError) { | 73 | fn add_err(&mut self, err: ExpandError) { |
74 | let prev_err = self.err.take(); | 74 | let prev_err = self.err.take(); |
75 | self.err = prev_err.or(Some(err)); | 75 | self.err = prev_err.or(Some(err)); |
76 | self.err_count += 1; | 76 | self.err_count += 1; |
@@ -79,12 +79,10 @@ impl Match { | |||
79 | 79 | ||
80 | /// Matching errors are added to the `Match`. | 80 | /// Matching errors are added to the `Match`. |
81 | pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | 81 | pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { |
82 | assert!(pattern.delimiter == None); | ||
83 | |||
84 | let mut res = Match::default(); | 82 | let mut res = Match::default(); |
85 | let mut src = TtIter::new(src); | 83 | let mut src = TtIter::new(src); |
86 | 84 | ||
87 | match_subtree(&mut res, pattern, &mut src); | 85 | match_tokens(&mut res, pattern, &mut src); |
88 | 86 | ||
89 | if src.len() > 0 { | 87 | if src.len() > 0 { |
90 | res.unmatched_tts += src.len(); | 88 | res.unmatched_tts += src.len(); |
@@ -94,36 +92,16 @@ pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
94 | res | 92 | res |
95 | } | 93 | } |
96 | 94 | ||
97 | fn match_subtree(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) { | 95 | fn match_tokens(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) { |
98 | for op in pattern.iter() { | 96 | for op in pattern.iter() { |
99 | match op { | 97 | match op { |
100 | Op::Leaf(lhs) => { | 98 | Op::Leaf(lhs) => { |
101 | let rhs = match src.expect_leaf() { | 99 | if let Err(err) = match_leaf(lhs, src) { |
102 | Ok(l) => l, | 100 | res.add_err(err); |
103 | Err(()) => { | 101 | continue; |
104 | res.add_err(err!("expected leaf: `{}`", lhs)); | ||
105 | continue; | ||
106 | } | ||
107 | }; | ||
108 | match (lhs, rhs) { | ||
109 | ( | ||
110 | tt::Leaf::Punct(tt::Punct { char: lhs, .. }), | ||
111 | tt::Leaf::Punct(tt::Punct { char: rhs, .. }), | ||
112 | ) if lhs == rhs => (), | ||
113 | ( | ||
114 | tt::Leaf::Ident(tt::Ident { text: lhs, .. }), | ||
115 | tt::Leaf::Ident(tt::Ident { text: rhs, .. }), | ||
116 | ) if lhs == rhs => (), | ||
117 | ( | ||
118 | tt::Leaf::Literal(tt::Literal { text: lhs, .. }), | ||
119 | tt::Leaf::Literal(tt::Literal { text: rhs, .. }), | ||
120 | ) if lhs == rhs => (), | ||
121 | _ => { | ||
122 | res.add_err(ExpandError::UnexpectedToken); | ||
123 | } | ||
124 | } | 102 | } |
125 | } | 103 | } |
126 | Op::Subtree(lhs) => { | 104 | Op::Subtree { tokens, delimiter: delim } => { |
127 | let rhs = match src.expect_subtree() { | 105 | let rhs = match src.expect_subtree() { |
128 | Ok(s) => s, | 106 | Ok(s) => s, |
129 | Err(()) => { | 107 | Err(()) => { |
@@ -131,12 +109,12 @@ fn match_subtree(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) { | |||
131 | continue; | 109 | continue; |
132 | } | 110 | } |
133 | }; | 111 | }; |
134 | if lhs.delimiter_kind() != rhs.delimiter_kind() { | 112 | if delim.map(|it| it.kind) != rhs.delimiter_kind() { |
135 | res.add_err(err!("mismatched delimiter")); | 113 | res.add_err(err!("mismatched delimiter")); |
136 | continue; | 114 | continue; |
137 | } | 115 | } |
138 | let mut src = TtIter::new(rhs); | 116 | let mut src = TtIter::new(rhs); |
139 | match_subtree(res, lhs, &mut src); | 117 | match_tokens(res, tokens, &mut src); |
140 | if src.len() > 0 { | 118 | if src.len() > 0 { |
141 | res.add_err(err!("leftover tokens")); | 119 | res.add_err(err!("leftover tokens")); |
142 | } | 120 | } |
@@ -162,14 +140,42 @@ fn match_subtree(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) { | |||
162 | res.add_err(err); | 140 | res.add_err(err); |
163 | } | 141 | } |
164 | } | 142 | } |
165 | Op::Repeat { subtree, kind, separator } => { | 143 | Op::Repeat { tokens: subtree, kind, separator } => { |
166 | match_repeat(res, subtree, *kind, separator, src); | 144 | match_repeat(res, subtree, *kind, separator, src); |
167 | } | 145 | } |
168 | } | 146 | } |
169 | } | 147 | } |
170 | } | 148 | } |
171 | 149 | ||
172 | pub(super) fn match_repeat( | 150 | fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> { |
151 | let rhs = match src.expect_leaf() { | ||
152 | Ok(l) => l, | ||
153 | Err(()) => { | ||
154 | return Err(err!("expected leaf: `{}`", lhs)); | ||
155 | } | ||
156 | }; | ||
157 | match (lhs, rhs) { | ||
158 | ( | ||
159 | tt::Leaf::Punct(tt::Punct { char: lhs, .. }), | ||
160 | tt::Leaf::Punct(tt::Punct { char: rhs, .. }), | ||
161 | ) if lhs == rhs => (), | ||
162 | ( | ||
163 | tt::Leaf::Ident(tt::Ident { text: lhs, .. }), | ||
164 | tt::Leaf::Ident(tt::Ident { text: rhs, .. }), | ||
165 | ) if lhs == rhs => (), | ||
166 | ( | ||
167 | tt::Leaf::Literal(tt::Literal { text: lhs, .. }), | ||
168 | tt::Leaf::Literal(tt::Literal { text: rhs, .. }), | ||
169 | ) if lhs == rhs => (), | ||
170 | _ => { | ||
171 | return Err(ExpandError::UnexpectedToken); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | Ok(()) | ||
176 | } | ||
177 | |||
178 | fn match_repeat( | ||
173 | res: &mut Match, | 179 | res: &mut Match, |
174 | pattern: &MetaTemplate, | 180 | pattern: &MetaTemplate, |
175 | kind: RepeatKind, | 181 | kind: RepeatKind, |
@@ -191,7 +197,7 @@ pub(super) fn match_repeat( | |||
191 | } | 197 | } |
192 | 198 | ||
193 | let mut nested = Match::default(); | 199 | let mut nested = Match::default(); |
194 | match_subtree(&mut nested, pattern, &mut fork); | 200 | match_tokens(&mut nested, pattern, &mut fork); |
195 | if nested.err.is_none() { | 201 | if nested.err.is_none() { |
196 | limit -= 1; | 202 | limit -= 1; |
197 | if limit == 0 { | 203 | if limit == 0 { |
@@ -292,8 +298,8 @@ fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &MetaTemplate) { | |||
292 | match op { | 298 | match op { |
293 | Op::Var { name, .. } => buf.push(name.clone()), | 299 | Op::Var { name, .. } => buf.push(name.clone()), |
294 | Op::Leaf(_) => (), | 300 | Op::Leaf(_) => (), |
295 | Op::Subtree(subtree) => collect_vars(buf, subtree), | 301 | Op::Subtree { tokens, .. } => collect_vars(buf, tokens), |
296 | Op::Repeat { subtree, .. } => collect_vars(buf, subtree), | 302 | Op::Repeat { tokens, .. } => collect_vars(buf, tokens), |
297 | } | 303 | } |
298 | } | 304 | } |
299 | } | 305 | } |
@@ -325,7 +331,7 @@ impl<'a> TtIter<'a> { | |||
325 | ok | 331 | ok |
326 | } | 332 | } |
327 | 333 | ||
328 | pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { | 334 | fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { |
329 | match self.peek_n(0) { | 335 | match self.peek_n(0) { |
330 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => { | 336 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => { |
331 | return self.expect_lifetime(); | 337 | return self.expect_lifetime(); |
@@ -386,7 +392,7 @@ impl<'a> TtIter<'a> { | |||
386 | } | 392 | } |
387 | } | 393 | } |
388 | 394 | ||
389 | pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> { | 395 | fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> { |
390 | let punct = self.expect_punct()?; | 396 | let punct = self.expect_punct()?; |
391 | if punct.char != '\'' { | 397 | if punct.char != '\'' { |
392 | return Err(()); | 398 | return Err(()); |
@@ -403,13 +409,13 @@ impl<'a> TtIter<'a> { | |||
403 | .into()) | 409 | .into()) |
404 | } | 410 | } |
405 | 411 | ||
406 | pub(crate) fn expect_fragment( | 412 | fn expect_fragment( |
407 | &mut self, | 413 | &mut self, |
408 | fragment_kind: parser::FragmentKind, | 414 | fragment_kind: parser::FragmentKind, |
409 | ) -> ExpandResult<Option<tt::TokenTree>> { | 415 | ) -> ExpandResult<Option<tt::TokenTree>> { |
410 | pub(crate) struct OffsetTokenSink<'a> { | 416 | struct OffsetTokenSink<'a> { |
411 | pub(crate) cursor: Cursor<'a>, | 417 | cursor: Cursor<'a>, |
412 | pub(crate) error: bool, | 418 | error: bool, |
413 | } | 419 | } |
414 | 420 | ||
415 | impl<'a> TreeSink for OffsetTokenSink<'a> { | 421 | impl<'a> TreeSink for OffsetTokenSink<'a> { |
@@ -465,7 +471,7 @@ impl<'a> TtIter<'a> { | |||
465 | ExpandResult { value: res, err } | 471 | ExpandResult { value: res, err } |
466 | } | 472 | } |
467 | 473 | ||
468 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { | 474 | fn eat_vis(&mut self) -> Option<tt::TokenTree> { |
469 | let mut fork = self.clone(); | 475 | let mut fork = self.clone(); |
470 | match fork.expect_fragment(Visibility) { | 476 | match fork.expect_fragment(Visibility) { |
471 | ExpandResult { value: tt, err: None } => { | 477 | ExpandResult { value: tt, err: None } => { |
@@ -476,7 +482,7 @@ impl<'a> TtIter<'a> { | |||
476 | } | 482 | } |
477 | } | 483 | } |
478 | 484 | ||
479 | pub(crate) fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> { | 485 | fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> { |
480 | let mut fork = self.clone(); | 486 | let mut fork = self.clone(); |
481 | match fork.expect_char(c) { | 487 | match fork.expect_char(c) { |
482 | Ok(_) => { | 488 | Ok(_) => { |