aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_macros/src/mbe_expander.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_macros/src/mbe_expander.rs')
-rw-r--r--crates/ra_macros/src/mbe_expander.rs145
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 @@
1use rustc_hash::FxHashMap; 1use rustc_hash::FxHashMap;
2use smol_str::SmolStr; 2use smol_str::SmolStr;
3 3
4use crate::{mbe, tt}; 4use crate::{mbe, tt, tt_cursor::TtCursor};
5 5
6pub fn exapnd(rules: &mbe::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> { 6pub 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
10fn expand_rule(rule: &mbe::Rule, input: &tt::Subtree) -> Option<tt::Subtree> { 10fn 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/* 27impl Bindings {
27 28 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Option<&tt::TokenTree> {
28macro_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
40impl_froms! (Foo: Bar, Baz) 55fn match_lhs(pattern: &mbe::Subtree, input: &mut TtCursor) -> Option<Bindings> {
41
42*/
43
44fn 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
64fn expand_rhs(template: &mbe::Subtree, bindings: &Bindings) -> Option<tt::Subtree> { 98/*
65 None 99
100macro_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
112impl_froms! (Foo: Bar, Baz)
113
114*/
115
116fn 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
133fn 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}