aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander/matcher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander/matcher.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs361
1 files changed, 242 insertions, 119 deletions
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs
index 100a3b0e0..aff953102 100644
--- a/crates/ra_mbe/src/mbe_expander/matcher.rs
+++ b/crates/ra_mbe/src/mbe_expander/matcher.rs
@@ -1,11 +1,14 @@
1use crate::{ 1use crate::{
2 mbe_expander::{Binding, Bindings, Fragment}, 2 mbe_expander::{Binding, Bindings, Fragment},
3 tt_cursor::TtCursor, 3 parser::{parse_pattern, Op, RepeatKind, Separator},
4 subtree_source::SubtreeTokenSource,
5 tt_iter::TtIter,
4 ExpandError, 6 ExpandError,
5}; 7};
6 8
7use ra_parser::FragmentKind::*; 9use ra_parser::{FragmentKind::*, TreeSink};
8use ra_syntax::SmolStr; 10use ra_syntax::{SmolStr, SyntaxKind};
11use tt::buffer::{Cursor, TokenBuffer};
9 12
10impl Bindings { 13impl Bindings {
11 fn push_optional(&mut self, name: &SmolStr) { 14 fn push_optional(&mut self, name: &SmolStr) {
@@ -42,121 +45,247 @@ impl Bindings {
42 } 45 }
43 Ok(()) 46 Ok(())
44 } 47 }
48}
45 49
46 fn merge(&mut self, nested: Bindings) { 50macro_rules! err {
47 self.inner.extend(nested.inner); 51 () => {
48 } 52 ExpandError::BindingError(format!(""))
53 };
54 ($($tt:tt)*) => {
55 ExpandError::BindingError(format!($($tt)*))
56 };
49} 57}
50 58
51pub(super) fn match_lhs( 59macro_rules! bail {
52 pattern: &crate::Subtree, 60 ($($tt:tt)*) => {
53 input: &mut TtCursor, 61 return Err(err!($($tt)*))
54) -> Result<Bindings, ExpandError> { 62 };
63}
64
65pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Bindings, ExpandError> {
66 assert!(pattern.delimiter == tt::Delimiter::None);
67
55 let mut res = Bindings::default(); 68 let mut res = Bindings::default();
56 for pat in pattern.token_trees.iter() { 69 let mut src = TtIter::new(src);
57 match pat { 70
58 crate::TokenTree::Leaf(leaf) => match leaf { 71 match_subtree(&mut res, pattern, &mut src)?;
59 crate::Leaf::Var(crate::Var { text, kind }) => { 72
60 let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; 73 if src.len() > 0 {
61 match match_meta_var(kind.as_str(), input)? { 74 bail!("leftover tokens");
62 Some(fragment) => { 75 }
63 res.inner.insert(text.clone(), Binding::Fragment(fragment)); 76
64 } 77 Ok(res)
65 None => res.push_optional(text), 78}
66 } 79
80fn match_subtree(
81 bindings: &mut Bindings,
82 pattern: &tt::Subtree,
83 src: &mut TtIter,
84) -> Result<(), ExpandError> {
85 for op in parse_pattern(pattern) {
86 match op? {
87 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => {
88 let rhs = src.expect_leaf().map_err(|()| err!("expected leaf: `{}`", lhs))?;
89 match (lhs, rhs) {
90 (
91 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
92 tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
93 ) if lhs == rhs => (),
94 (
95 tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
96 tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
97 ) if lhs == rhs => (),
98 (
99 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
100 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
101 ) if lhs == rhs => (),
102 _ => Err(ExpandError::UnexpectedToken)?,
67 } 103 }
68 crate::Leaf::Punct(punct) => { 104 }
69 if !input.eat_punct().map(|p| p.char == punct.char).unwrap_or(false) { 105 Op::TokenTree(tt::TokenTree::Subtree(lhs)) => {
70 return Err(ExpandError::UnexpectedToken); 106 let rhs = src.expect_subtree().map_err(|()| err!("expected subtree"))?;
71 } 107 if lhs.delimiter != rhs.delimiter {
108 bail!("mismatched delimiter")
72 } 109 }
73 crate::Leaf::Ident(ident) => { 110 let mut src = TtIter::new(rhs);
74 if input.eat_ident().map(|i| &i.text) != Some(&ident.text) { 111 match_subtree(bindings, lhs, &mut src)?;
75 return Err(ExpandError::UnexpectedToken); 112 if src.len() > 0 {
76 } 113 bail!("leftover tokens");
77 } 114 }
78 crate::Leaf::Literal(literal) => { 115 }
79 if input.eat_literal().map(|i| &i.text) != Some(&literal.text) { 116 Op::Var { name, kind } => {
80 return Err(ExpandError::UnexpectedToken); 117 let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?;
118 match match_meta_var(kind.as_str(), src)? {
119 Some(fragment) => {
120 bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
81 } 121 }
122 None => bindings.push_optional(name),
82 } 123 }
124 ()
125 }
126 Op::Repeat { subtree, kind, separator } => {
127 match_repeat(bindings, subtree, kind, separator, src)?
128 }
129 }
130 }
131 Ok(())
132}
133
134impl<'a> TtIter<'a> {
135 fn eat_separator(&mut self, separator: &Separator) -> bool {
136 let mut fork = self.clone();
137 let ok = match separator {
138 Separator::Ident(lhs) => match fork.expect_ident() {
139 Ok(rhs) => rhs.text == lhs.text,
140 _ => false,
83 }, 141 },
84 crate::TokenTree::Repeat(crate::Repeat { subtree, kind, separator }) => { 142 Separator::Literal(lhs) => match fork.expect_literal() {
85 // Dirty hack to make macro-expansion terminate. 143 Ok(rhs) => rhs.text == lhs.text,
86 // This should be replaced by a propper macro-by-example implementation 144 _ => false,
87 let mut limit = 65536; 145 },
88 let mut counter = 0; 146 Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() {
89 147 Ok(rhs) => rhs.char == lhs.char,
90 let mut memento = input.save(); 148 _ => false,
91 149 }),
92 loop { 150 };
93 match match_lhs(subtree, input) { 151 if ok {
94 Ok(nested) => { 152 *self = fork;
95 limit -= 1; 153 }
96 if limit == 0 { 154 ok
97 log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", subtree, input, kind, separator); 155 }
98 break;
99 }
100
101 memento = input.save();
102 res.push_nested(counter, nested)?;
103 counter += 1;
104 if counter == 1 {
105 if let crate::RepeatKind::ZeroOrOne = kind {
106 break;
107 }
108 }
109
110 if let Some(separator) = separator {
111 if !input
112 .eat_seperator()
113 .map(|sep| sep == *separator)
114 .unwrap_or(false)
115 {
116 input.rollback(memento);
117 break;
118 }
119 }
120 }
121 Err(_) => {
122 input.rollback(memento);
123 break;
124 }
125 }
126 }
127 156
128 match kind { 157 pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> {
129 crate::RepeatKind::OneOrMore if counter == 0 => { 158 let ident = self.expect_ident()?;
130 return Err(ExpandError::UnexpectedToken); 159 // check if it start from "`"
131 } 160 if ident.text.chars().next() != Some('\'') {
132 _ if counter == 0 => { 161 return Err(());
133 // Collect all empty variables in subtrees 162 }
134 collect_vars(subtree).iter().for_each(|s| res.push_empty(s)); 163 Ok(ident)
135 } 164 }
136 _ => {} 165
166 pub(crate) fn expect_fragment(
167 &mut self,
168 fragment_kind: ra_parser::FragmentKind,
169 ) -> Result<tt::TokenTree, ()> {
170 pub(crate) struct OffsetTokenSink<'a> {
171 pub(crate) cursor: Cursor<'a>,
172 pub(crate) error: bool,
173 }
174
175 impl<'a> TreeSink for OffsetTokenSink<'a> {
176 fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) {
177 for _ in 0..n_tokens {
178 self.cursor = self.cursor.bump_subtree();
137 } 179 }
138 } 180 }
139 crate::TokenTree::Subtree(subtree) => { 181 fn start_node(&mut self, _kind: SyntaxKind) {}
140 let input_subtree = 182 fn finish_node(&mut self) {}
141 input.eat_subtree().map_err(|_| ExpandError::UnexpectedToken)?; 183 fn error(&mut self, _error: ra_parser::ParseError) {
142 if subtree.delimiter != input_subtree.delimiter { 184 self.error = true;
143 return Err(ExpandError::UnexpectedToken); 185 }
186 }
187
188 let buffer = TokenBuffer::new(self.inner.as_slice());
189 let mut src = SubtreeTokenSource::new(&buffer);
190 let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false };
191
192 ra_parser::parse_fragment(&mut src, &mut sink, fragment_kind);
193
194 if !sink.cursor.is_root() || sink.error {
195 return Err(());
196 }
197
198 let mut curr = buffer.begin();
199 let mut res = vec![];
200
201 while curr != sink.cursor {
202 if let Some(token) = curr.token_tree() {
203 res.push(token);
204 }
205 curr = curr.bump();
206 }
207 self.inner = self.inner.as_slice()[res.len()..].iter();
208 match res.len() {
209 0 => Err(()),
210 1 => Ok(res[0].clone()),
211 _ => Ok(tt::TokenTree::Subtree(tt::Subtree {
212 delimiter: tt::Delimiter::None,
213 token_trees: res.into_iter().cloned().collect(),
214 })),
215 }
216 }
217
218 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
219 let mut fork = self.clone();
220 match fork.expect_fragment(Visibility) {
221 Ok(tt) => {
222 *self = fork;
223 Some(tt)
224 }
225 Err(()) => None,
226 }
227 }
228}
229
230pub(super) fn match_repeat(
231 bindings: &mut Bindings,
232 pattern: &tt::Subtree,
233 kind: RepeatKind,
234 separator: Option<Separator>,
235 src: &mut TtIter,
236) -> Result<(), ExpandError> {
237 // Dirty hack to make macro-expansion terminate.
238 // This should be replaced by a propper macro-by-example implementation
239 let mut limit = 65536;
240 let mut counter = 0;
241
242 for i in 0.. {
243 let mut fork = src.clone();
244
245 if let Some(separator) = &separator {
246 if i != 0 && !fork.eat_separator(separator) {
247 break;
248 }
249 }
250
251 let mut nested = Bindings::default();
252 match match_subtree(&mut nested, pattern, &mut fork) {
253 Ok(()) => {
254 limit -= 1;
255 if limit == 0 {
256 log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", pattern, src, kind, separator);
257 break;
144 } 258 }
259 *src = fork;
145 260
146 let mut input = TtCursor::new(input_subtree); 261 bindings.push_nested(counter, nested)?;
147 let bindings = match_lhs(&subtree, &mut input)?; 262 counter += 1;
148 if !input.is_eof() { 263 if counter == 1 {
149 return Err(ExpandError::UnexpectedToken); 264 if let RepeatKind::ZeroOrOne = kind {
265 break;
266 }
150 } 267 }
268 }
269 Err(_) => break,
270 }
271 }
151 272
152 res.merge(bindings); 273 match (kind, counter) {
274 (RepeatKind::OneOrMore, 0) => return Err(ExpandError::UnexpectedToken),
275 (_, 0) => {
276 // Collect all empty variables in subtrees
277 let mut vars = Vec::new();
278 collect_vars(&mut vars, pattern)?;
279 for var in vars {
280 bindings.push_empty(&var)
153 } 281 }
154 } 282 }
283 _ => (),
155 } 284 }
156 Ok(res) 285 Ok(())
157} 286}
158 287
159fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<Fragment>, ExpandError> { 288fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, ExpandError> {
160 let fragment = match kind { 289 let fragment = match kind {
161 "path" => Path, 290 "path" => Path,
162 "expr" => Expr, 291 "expr" => Expr,
@@ -169,17 +298,20 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<Fragment>,
169 _ => { 298 _ => {
170 let tt = match kind { 299 let tt = match kind {
171 "ident" => { 300 "ident" => {
172 let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); 301 let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone();
173 tt::Leaf::from(ident).into() 302 tt::Leaf::from(ident).into()
174 } 303 }
175 "tt" => input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(), 304 "tt" => input.next().ok_or_else(|| err!())?.clone(),
176 "lifetime" => input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(), 305 "lifetime" => {
306 let ident = input.expect_lifetime().map_err(|()| err!())?;
307 tt::Leaf::Ident(ident.clone()).into()
308 }
177 "literal" => { 309 "literal" => {
178 let literal = input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); 310 let literal = input.expect_literal().map_err(|()| err!())?.clone();
179 tt::Leaf::from(literal).into() 311 tt::Leaf::from(literal).into()
180 } 312 }
181 // `vis` is optional 313 // `vis` is optional
182 "vis" => match input.try_eat_vis() { 314 "vis" => match input.eat_vis() {
183 Some(vis) => vis, 315 Some(vis) => vis,
184 None => return Ok(None), 316 None => return Ok(None),
185 }, 317 },
@@ -188,28 +320,19 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<Fragment>,
188 return Ok(Some(Fragment::Tokens(tt))); 320 return Ok(Some(Fragment::Tokens(tt)));
189 } 321 }
190 }; 322 };
191 let tt = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; 323 let tt = input.expect_fragment(fragment).map_err(|()| err!())?;
192 let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) }; 324 let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) };
193 Ok(Some(fragment)) 325 Ok(Some(fragment))
194} 326}
195 327
196fn collect_vars(subtree: &crate::Subtree) -> Vec<SmolStr> { 328fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> {
197 let mut res = Vec::new(); 329 for op in parse_pattern(pattern) {
198 330 match op? {
199 for tkn in subtree.token_trees.iter() { 331 Op::Var { name, .. } => buf.push(name.clone()),
200 match tkn { 332 Op::TokenTree(tt::TokenTree::Leaf(_)) => (),
201 crate::TokenTree::Leaf(crate::Leaf::Var(crate::Var { text, .. })) => { 333 Op::TokenTree(tt::TokenTree::Subtree(subtree)) => collect_vars(buf, subtree)?,
202 res.push(text.clone()); 334 Op::Repeat { subtree, .. } => collect_vars(buf, subtree)?,
203 }
204 crate::TokenTree::Subtree(subtree) => {
205 res.extend(collect_vars(subtree));
206 }
207 crate::TokenTree::Repeat(crate::Repeat { subtree, .. }) => {
208 res.extend(collect_vars(subtree));
209 }
210 _ => {}
211 } 335 }
212 } 336 }
213 337 Ok(())
214 res
215} 338}