diff options
Diffstat (limited to 'crates/ra_macros/src/mbe_expander.rs')
-rw-r--r-- | crates/ra_macros/src/mbe_expander.rs | 145 |
1 files changed, 124 insertions, 21 deletions
diff --git a/crates/ra_macros/src/mbe_expander.rs b/crates/ra_macros/src/mbe_expander.rs index f55c337da..5d5363261 100644 --- a/crates/ra_macros/src/mbe_expander.rs +++ b/crates/ra_macros/src/mbe_expander.rs | |||
@@ -1,15 +1,16 @@ | |||
1 | use rustc_hash::FxHashMap; | 1 | use rustc_hash::FxHashMap; |
2 | use smol_str::SmolStr; | 2 | use smol_str::SmolStr; |
3 | 3 | ||
4 | use crate::{mbe, tt}; | 4 | use crate::{mbe, tt, tt_cursor::TtCursor}; |
5 | 5 | ||
6 | pub fn exapnd(rules: &mbe::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> { | 6 | pub fn exapnd(rules: &mbe::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> { |
7 | rules.rules.iter().find_map(|it| expand_rule(it, input)) | 7 | rules.rules.iter().find_map(|it| expand_rule(it, input)) |
8 | } | 8 | } |
9 | 9 | ||
10 | fn expand_rule(rule: &mbe::Rule, input: &tt::Subtree) -> Option<tt::Subtree> { | 10 | fn expand_rule(rule: &mbe::Rule, input: &tt::Subtree) -> Option<tt::Subtree> { |
11 | let bindings = match_lhs(&rule.lhs, input)?; | 11 | let mut input = TtCursor::new(input); |
12 | expand_rhs(&rule.rhs, &bindings) | 12 | let bindings = match_lhs(&rule.lhs, &mut input)?; |
13 | expand_subtree(&rule.rhs, &bindings, &mut Vec::new()) | ||
13 | } | 14 | } |
14 | 15 | ||
15 | #[derive(Debug, Default)] | 16 | #[derive(Debug, Default)] |
@@ -23,25 +24,35 @@ enum Binding { | |||
23 | Nested(Vec<Binding>), | 24 | Nested(Vec<Binding>), |
24 | } | 25 | } |
25 | 26 | ||
26 | /* | 27 | impl Bindings { |
27 | 28 | fn get(&self, name: &SmolStr, nesting: &[usize]) -> Option<&tt::TokenTree> { | |
28 | macro_rules! impl_froms { | 29 | let mut b = self.inner.get(name)?; |
29 | ($e:ident: $($v:ident),*) => { | 30 | for &idx in nesting.iter() { |
30 | $( | 31 | b = match b { |
31 | impl From<$v> for $e { | 32 | Binding::Simple(_) => break, |
32 | fn from(it: $v) -> $e { | 33 | Binding::Nested(bs) => bs.get(idx)?, |
33 | $e::$v(it) | 34 | }; |
34 | } | 35 | } |
36 | match b { | ||
37 | Binding::Simple(it) => Some(it), | ||
38 | Binding::Nested(_) => None, | ||
39 | } | ||
40 | } | ||
41 | fn push_nested(&mut self, nested: Bindings) -> Option<()> { | ||
42 | for (key, value) in nested.inner { | ||
43 | if !self.inner.contains_key(&key) { | ||
44 | self.inner.insert(key.clone(), Binding::Nested(Vec::new())); | ||
35 | } | 45 | } |
36 | )* | 46 | match self.inner.get_mut(&key) { |
47 | Some(Binding::Nested(it)) => it.push(value), | ||
48 | _ => return None, | ||
49 | } | ||
50 | } | ||
51 | Some(()) | ||
37 | } | 52 | } |
38 | } | 53 | } |
39 | 54 | ||
40 | impl_froms! (Foo: Bar, Baz) | 55 | fn match_lhs(pattern: &mbe::Subtree, input: &mut TtCursor) -> Option<Bindings> { |
41 | |||
42 | */ | ||
43 | |||
44 | fn match_lhs(pattern: &mbe::Subtree, input: &tt::Subtree) -> Option<Bindings> { | ||
45 | let mut res = Bindings::default(); | 56 | let mut res = Bindings::default(); |
46 | for pat in pattern.token_trees.iter() { | 57 | for pat in pattern.token_trees.iter() { |
47 | match pat { | 58 | match pat { |
@@ -49,18 +60,110 @@ fn match_lhs(pattern: &mbe::Subtree, input: &tt::Subtree) -> Option<Bindings> { | |||
49 | mbe::Leaf::Var(mbe::Var { text, kind }) => { | 60 | mbe::Leaf::Var(mbe::Var { text, kind }) => { |
50 | let kind = kind.clone()?; | 61 | let kind = kind.clone()?; |
51 | match kind.as_str() { | 62 | match kind.as_str() { |
52 | "ident" => (), | 63 | "ident" => { |
64 | let ident = input.eat_ident()?.clone(); | ||
65 | res.inner.insert( | ||
66 | text.clone(), | ||
67 | Binding::Simple(tt::Leaf::from(ident).into()), | ||
68 | ); | ||
69 | } | ||
53 | _ => return None, | 70 | _ => return None, |
54 | } | 71 | } |
55 | } | 72 | } |
73 | mbe::Leaf::Punct(punct) => { | ||
74 | if input.eat_punct()? != punct { | ||
75 | return None; | ||
76 | } | ||
77 | } | ||
56 | _ => return None, | 78 | _ => return None, |
57 | }, | 79 | }, |
80 | mbe::TokenTree::Repeat(mbe::Repeat { | ||
81 | subtree, | ||
82 | kind: _, | ||
83 | separator, | ||
84 | }) => { | ||
85 | while let Some(nested) = match_lhs(subtree, input) { | ||
86 | res.push_nested(nested)?; | ||
87 | if separator.is_some() && !input.is_eof() { | ||
88 | input.eat_punct()?; | ||
89 | } | ||
90 | } | ||
91 | } | ||
58 | _ => {} | 92 | _ => {} |
59 | } | 93 | } |
60 | } | 94 | } |
61 | Some(res) | 95 | Some(res) |
62 | } | 96 | } |
63 | 97 | ||
64 | fn expand_rhs(template: &mbe::Subtree, bindings: &Bindings) -> Option<tt::Subtree> { | 98 | /* |
65 | None | 99 | |
100 | macro_rules! impl_froms { | ||
101 | ($e:ident: $($v:ident),*) => { | ||
102 | $( | ||
103 | impl From<$v> for $e { | ||
104 | fn from(it: $v) -> $e { | ||
105 | $e::$v(it) | ||
106 | } | ||
107 | } | ||
108 | )* | ||
109 | } | ||
110 | } | ||
111 | |||
112 | impl_froms! (Foo: Bar, Baz) | ||
113 | |||
114 | */ | ||
115 | |||
116 | fn expand_subtree( | ||
117 | template: &mbe::Subtree, | ||
118 | bindings: &Bindings, | ||
119 | nesting: &mut Vec<usize>, | ||
120 | ) -> Option<tt::Subtree> { | ||
121 | let token_trees = template | ||
122 | .token_trees | ||
123 | .iter() | ||
124 | .map(|it| expand_tt(it, bindings, nesting)) | ||
125 | .collect::<Option<Vec<_>>>()?; | ||
126 | |||
127 | Some(tt::Subtree { | ||
128 | token_trees, | ||
129 | delimiter: template.delimiter, | ||
130 | }) | ||
131 | } | ||
132 | |||
133 | fn expand_tt( | ||
134 | template: &mbe::TokenTree, | ||
135 | bindings: &Bindings, | ||
136 | nesting: &mut Vec<usize>, | ||
137 | ) -> Option<tt::TokenTree> { | ||
138 | let res: tt::TokenTree = match template { | ||
139 | mbe::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(), | ||
140 | mbe::TokenTree::Repeat(repeat) => { | ||
141 | let mut token_trees = Vec::new(); | ||
142 | nesting.push(0); | ||
143 | while let Some(t) = expand_subtree(&repeat.subtree, bindings, nesting) { | ||
144 | let idx = nesting.pop().unwrap(); | ||
145 | nesting.push(idx + 1); | ||
146 | token_trees.push(t.into()) | ||
147 | } | ||
148 | nesting.pop().unwrap(); | ||
149 | tt::Subtree { | ||
150 | token_trees, | ||
151 | delimiter: tt::Delimiter::None, | ||
152 | } | ||
153 | .into() | ||
154 | } | ||
155 | mbe::TokenTree::Leaf(leaf) => match leaf { | ||
156 | mbe::Leaf::Ident(ident) => tt::Leaf::from(tt::Ident { | ||
157 | text: ident.text.clone(), | ||
158 | }) | ||
159 | .into(), | ||
160 | mbe::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(), | ||
161 | mbe::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(), | ||
162 | mbe::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { | ||
163 | text: l.text.clone(), | ||
164 | }) | ||
165 | .into(), | ||
166 | }, | ||
167 | }; | ||
168 | Some(res) | ||
66 | } | 169 | } |