diff options
Diffstat (limited to 'crates/mbe/src')
-rw-r--r-- | crates/mbe/src/lib.rs | 48 | ||||
-rw-r--r-- | crates/mbe/src/mbe_expander.rs | 15 | ||||
-rw-r--r-- | crates/mbe/src/mbe_expander/matcher.rs | 9 | ||||
-rw-r--r-- | crates/mbe/src/mbe_expander/transcriber.rs | 18 |
4 files changed, 62 insertions, 28 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index f854ca09a..2d0763c47 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -12,6 +12,8 @@ mod subtree_source; | |||
12 | #[cfg(test)] | 12 | #[cfg(test)] |
13 | mod tests; | 13 | mod tests; |
14 | 14 | ||
15 | use std::fmt; | ||
16 | |||
15 | pub use tt::{Delimiter, Punct}; | 17 | pub use tt::{Delimiter, Punct}; |
16 | 18 | ||
17 | use crate::{ | 19 | use crate::{ |
@@ -33,6 +35,7 @@ pub enum ExpandError { | |||
33 | ConversionError, | 35 | ConversionError, |
34 | InvalidRepeat, | 36 | InvalidRepeat, |
35 | ProcMacroError(tt::ExpansionError), | 37 | ProcMacroError(tt::ExpansionError), |
38 | Other(String), | ||
36 | } | 39 | } |
37 | 40 | ||
38 | impl From<tt::ExpansionError> for ExpandError { | 41 | impl From<tt::ExpansionError> for ExpandError { |
@@ -41,6 +44,20 @@ impl From<tt::ExpansionError> for ExpandError { | |||
41 | } | 44 | } |
42 | } | 45 | } |
43 | 46 | ||
47 | impl fmt::Display for ExpandError { | ||
48 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
49 | match self { | ||
50 | ExpandError::NoMatchingRule => f.write_str("no rule matches input tokens"), | ||
51 | ExpandError::UnexpectedToken => f.write_str("unexpected token in input"), | ||
52 | ExpandError::BindingError(e) => f.write_str(e), | ||
53 | ExpandError::ConversionError => f.write_str("could not convert tokens"), | ||
54 | ExpandError::InvalidRepeat => f.write_str("invalid repeat expression"), | ||
55 | ExpandError::ProcMacroError(e) => e.fmt(f), | ||
56 | ExpandError::Other(e) => f.write_str(e), | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
44 | pub use crate::syntax_bridge::{ | 61 | pub use crate::syntax_bridge::{ |
45 | ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, | 62 | ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, |
46 | TokenMap, | 63 | TokenMap, |
@@ -246,33 +263,42 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> { | |||
246 | Ok(()) | 263 | Ok(()) |
247 | } | 264 | } |
248 | 265 | ||
249 | #[derive(Debug)] | 266 | #[derive(Debug, Clone, Eq, PartialEq)] |
250 | pub struct ExpandResult<T>(pub T, pub Option<ExpandError>); | 267 | pub struct ExpandResult<T> { |
268 | pub value: T, | ||
269 | pub err: Option<ExpandError>, | ||
270 | } | ||
251 | 271 | ||
252 | impl<T> ExpandResult<T> { | 272 | impl<T> ExpandResult<T> { |
253 | pub fn ok(t: T) -> ExpandResult<T> { | 273 | pub fn ok(value: T) -> Self { |
254 | ExpandResult(t, None) | 274 | Self { value, err: None } |
275 | } | ||
276 | |||
277 | pub fn only_err(err: ExpandError) -> Self | ||
278 | where | ||
279 | T: Default, | ||
280 | { | ||
281 | Self { value: Default::default(), err: Some(err) } | ||
255 | } | 282 | } |
256 | 283 | ||
257 | pub fn only_err(err: ExpandError) -> ExpandResult<T> | 284 | pub fn str_err(err: String) -> Self |
258 | where | 285 | where |
259 | T: Default, | 286 | T: Default, |
260 | { | 287 | { |
261 | ExpandResult(Default::default(), Some(err)) | 288 | Self::only_err(ExpandError::Other(err)) |
262 | } | 289 | } |
263 | 290 | ||
264 | pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> { | 291 | pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> { |
265 | ExpandResult(f(self.0), self.1) | 292 | ExpandResult { value: f(self.value), err: self.err } |
266 | } | 293 | } |
267 | 294 | ||
268 | pub fn result(self) -> Result<T, ExpandError> { | 295 | pub fn result(self) -> Result<T, ExpandError> { |
269 | self.1.map(Err).unwrap_or(Ok(self.0)) | 296 | self.err.map(Err).unwrap_or(Ok(self.value)) |
270 | } | 297 | } |
271 | } | 298 | } |
272 | 299 | ||
273 | impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> { | 300 | impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> { |
274 | fn from(result: Result<T, ExpandError>) -> ExpandResult<T> { | 301 | fn from(result: Result<T, ExpandError>) -> Self { |
275 | result | 302 | result.map_or_else(|e| Self::only_err(e), |it| Self::ok(it)) |
276 | .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None)) | ||
277 | } | 303 | } |
278 | } | 304 | } |
diff --git a/crates/mbe/src/mbe_expander.rs b/crates/mbe/src/mbe_expander.rs index 1ad8b9f8a..97bce0536 100644 --- a/crates/mbe/src/mbe_expander.rs +++ b/crates/mbe/src/mbe_expander.rs | |||
@@ -28,10 +28,10 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt:: | |||
28 | // If we find a rule that applies without errors, we're done. | 28 | // If we find a rule that applies without errors, we're done. |
29 | // Unconditionally returning the transcription here makes the | 29 | // Unconditionally returning the transcription here makes the |
30 | // `test_repeat_bad_var` test fail. | 30 | // `test_repeat_bad_var` test fail. |
31 | let ExpandResult(res, transcribe_err) = | 31 | let ExpandResult { value, err: transcribe_err } = |
32 | transcriber::transcribe(&rule.rhs, &new_match.bindings); | 32 | transcriber::transcribe(&rule.rhs, &new_match.bindings); |
33 | if transcribe_err.is_none() { | 33 | if transcribe_err.is_none() { |
34 | return ExpandResult::ok(res); | 34 | return ExpandResult::ok(value); |
35 | } | 35 | } |
36 | } | 36 | } |
37 | // Use the rule if we matched more tokens, or had fewer errors | 37 | // Use the rule if we matched more tokens, or had fewer errors |
@@ -47,11 +47,11 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt:: | |||
47 | } | 47 | } |
48 | if let Some((match_, rule)) = match_ { | 48 | if let Some((match_, rule)) = match_ { |
49 | // if we got here, there was no match without errors | 49 | // if we got here, there was no match without errors |
50 | let ExpandResult(result, transcribe_err) = | 50 | let ExpandResult { value, err: transcribe_err } = |
51 | transcriber::transcribe(&rule.rhs, &match_.bindings); | 51 | transcriber::transcribe(&rule.rhs, &match_.bindings); |
52 | ExpandResult(result, match_.err.or(transcribe_err)) | 52 | ExpandResult { value, err: match_.err.or(transcribe_err) } |
53 | } else { | 53 | } else { |
54 | ExpandResult(tt::Subtree::default(), Some(ExpandError::NoMatchingRule)) | 54 | ExpandResult::only_err(ExpandError::NoMatchingRule) |
55 | } | 55 | } |
56 | } | 56 | } |
57 | 57 | ||
@@ -143,7 +143,10 @@ mod tests { | |||
143 | } | 143 | } |
144 | 144 | ||
145 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { | 145 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { |
146 | assert_eq!(expand_first(&create_rules(&format_macro(macro_body)), invocation).1, Some(err)); | 146 | assert_eq!( |
147 | expand_first(&create_rules(&format_macro(macro_body)), invocation).err, | ||
148 | Some(err) | ||
149 | ); | ||
147 | } | 150 | } |
148 | 151 | ||
149 | fn format_macro(macro_body: &str) -> String { | 152 | fn format_macro(macro_body: &str) -> String { |
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs index 39a8eefbd..3f8445897 100644 --- a/crates/mbe/src/mbe_expander/matcher.rs +++ b/crates/mbe/src/mbe_expander/matcher.rs | |||
@@ -158,7 +158,8 @@ fn match_subtree( | |||
158 | continue; | 158 | continue; |
159 | } | 159 | } |
160 | }; | 160 | }; |
161 | let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src); | 161 | let ExpandResult { value: matched, err: match_err } = |
162 | match_meta_var(kind.as_str(), src); | ||
162 | match matched { | 163 | match matched { |
163 | Some(fragment) => { | 164 | Some(fragment) => { |
164 | res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); | 165 | res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); |
@@ -342,17 +343,17 @@ impl<'a> TtIter<'a> { | |||
342 | token_trees: res.into_iter().cloned().collect(), | 343 | token_trees: res.into_iter().cloned().collect(), |
343 | })), | 344 | })), |
344 | }; | 345 | }; |
345 | ExpandResult(res, err) | 346 | ExpandResult { value: res, err } |
346 | } | 347 | } |
347 | 348 | ||
348 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { | 349 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { |
349 | let mut fork = self.clone(); | 350 | let mut fork = self.clone(); |
350 | match fork.expect_fragment(Visibility) { | 351 | match fork.expect_fragment(Visibility) { |
351 | ExpandResult(tt, None) => { | 352 | ExpandResult { value: tt, err: None } => { |
352 | *self = fork; | 353 | *self = fork; |
353 | tt | 354 | tt |
354 | } | 355 | } |
355 | ExpandResult(_, Some(_)) => None, | 356 | ExpandResult { value: _, err: Some(_) } => None, |
356 | } | 357 | } |
357 | } | 358 | } |
358 | } | 359 | } |
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs index c9525c5bf..616119ba9 100644 --- a/crates/mbe/src/mbe_expander/transcriber.rs +++ b/crates/mbe/src/mbe_expander/transcriber.rs | |||
@@ -93,17 +93,18 @@ fn expand_subtree( | |||
93 | match op { | 93 | match op { |
94 | Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()), | 94 | Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()), |
95 | Op::TokenTree(tt::TokenTree::Subtree(tt)) => { | 95 | Op::TokenTree(tt::TokenTree::Subtree(tt)) => { |
96 | let ExpandResult(tt, e) = expand_subtree(ctx, tt, arena); | 96 | let ExpandResult { value: tt, err: e } = expand_subtree(ctx, tt, arena); |
97 | err = err.or(e); | 97 | err = err.or(e); |
98 | arena.push(tt.into()); | 98 | arena.push(tt.into()); |
99 | } | 99 | } |
100 | Op::Var { name, kind: _ } => { | 100 | Op::Var { name, kind: _ } => { |
101 | let ExpandResult(fragment, e) = expand_var(ctx, name); | 101 | let ExpandResult { value: fragment, err: e } = expand_var(ctx, name); |
102 | err = err.or(e); | 102 | err = err.or(e); |
103 | push_fragment(arena, fragment); | 103 | push_fragment(arena, fragment); |
104 | } | 104 | } |
105 | Op::Repeat { subtree, kind, separator } => { | 105 | Op::Repeat { subtree, kind, separator } => { |
106 | let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator, arena); | 106 | let ExpandResult { value: fragment, err: e } = |
107 | expand_repeat(ctx, subtree, kind, separator, arena); | ||
107 | err = err.or(e); | 108 | err = err.or(e); |
108 | push_fragment(arena, fragment) | 109 | push_fragment(arena, fragment) |
109 | } | 110 | } |
@@ -111,7 +112,7 @@ fn expand_subtree( | |||
111 | } | 112 | } |
112 | // drain the elements added in this instance of expand_subtree | 113 | // drain the elements added in this instance of expand_subtree |
113 | let tts = arena.drain(start_elements..arena.len()).collect(); | 114 | let tts = arena.drain(start_elements..arena.len()).collect(); |
114 | ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err) | 115 | ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } |
115 | } | 116 | } |
116 | 117 | ||
117 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | 118 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { |
@@ -152,7 +153,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | |||
152 | ExpandResult::ok(Fragment::Tokens(tt)) | 153 | ExpandResult::ok(Fragment::Tokens(tt)) |
153 | } else { | 154 | } else { |
154 | ctx.bindings.get(&v, &mut ctx.nesting).map_or_else( | 155 | ctx.bindings.get(&v, &mut ctx.nesting).map_or_else( |
155 | |e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)), | 156 | |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) }, |
156 | |b| ExpandResult::ok(b.clone()), | 157 | |b| ExpandResult::ok(b.clone()), |
157 | ) | 158 | ) |
158 | } | 159 | } |
@@ -174,7 +175,7 @@ fn expand_repeat( | |||
174 | let mut counter = 0; | 175 | let mut counter = 0; |
175 | 176 | ||
176 | loop { | 177 | loop { |
177 | let ExpandResult(mut t, e) = expand_subtree(ctx, template, arena); | 178 | let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, arena); |
178 | let nesting_state = ctx.nesting.last_mut().unwrap(); | 179 | let nesting_state = ctx.nesting.last_mut().unwrap(); |
179 | if nesting_state.at_end || !nesting_state.hit { | 180 | if nesting_state.at_end || !nesting_state.hit { |
180 | break; | 181 | break; |
@@ -234,7 +235,10 @@ fn expand_repeat( | |||
234 | let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); | 235 | let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); |
235 | 236 | ||
236 | if RepeatKind::OneOrMore == kind && counter == 0 { | 237 | if RepeatKind::OneOrMore == kind && counter == 0 { |
237 | return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken)); | 238 | return ExpandResult { |
239 | value: Fragment::Tokens(tt), | ||
240 | err: Some(ExpandError::UnexpectedToken), | ||
241 | }; | ||
238 | } | 242 | } |
239 | ExpandResult::ok(Fragment::Tokens(tt)) | 243 | ExpandResult::ok(Fragment::Tokens(tt)) |
240 | } | 244 | } |