diff options
Diffstat (limited to 'crates/ra_mbe/src')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 122 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 40 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 32 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 46 |
4 files changed, 82 insertions, 158 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index f185aecb7..adee0cb42 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -1,7 +1,9 @@ | |||
1 | //! This module takes a (parsed) definition of `macro_rules` invocation, a | ||
2 | //! `tt::TokenTree` representing an argument of macro invocation, and produces a | ||
3 | //! `tt::TokenTree` for the result of the expansion. | ||
4 | |||
5 | use ra_parser::FragmentKind::*; | ||
1 | use ra_syntax::SmolStr; | 6 | use ra_syntax::SmolStr; |
2 | /// This module takes a (parsed) definition of `macro_rules` invocation, a | ||
3 | /// `tt::TokenTree` representing an argument of macro invocation, and produces a | ||
4 | /// `tt::TokenTree` for the result of the expansion. | ||
5 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
6 | use tt::TokenId; | 8 | use tt::TokenId; |
7 | 9 | ||
@@ -192,81 +194,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
192 | crate::TokenTree::Leaf(leaf) => match leaf { | 194 | crate::TokenTree::Leaf(leaf) => match leaf { |
193 | crate::Leaf::Var(crate::Var { text, kind }) => { | 195 | crate::Leaf::Var(crate::Var { text, kind }) => { |
194 | let kind = kind.clone().ok_or(ExpandError::UnexpectedToken)?; | 196 | let kind = kind.clone().ok_or(ExpandError::UnexpectedToken)?; |
195 | match kind.as_str() { | 197 | match match_meta_var(kind.as_str(), input)? { |
196 | "ident" => { | 198 | Some(tt) => { |
197 | let ident = | 199 | res.inner.insert(text.clone(), Binding::Simple(tt)); |
198 | input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
199 | res.inner.insert( | ||
200 | text.clone(), | ||
201 | Binding::Simple(tt::Leaf::from(ident).into()), | ||
202 | ); | ||
203 | } | ||
204 | "path" => { | ||
205 | let path = | ||
206 | input.eat_path().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
207 | res.inner.insert(text.clone(), Binding::Simple(path)); | ||
208 | } | ||
209 | "expr" => { | ||
210 | let expr = | ||
211 | input.eat_expr().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
212 | res.inner.insert(text.clone(), Binding::Simple(expr)); | ||
213 | } | ||
214 | "ty" => { | ||
215 | let ty = input.eat_ty().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
216 | res.inner.insert(text.clone(), Binding::Simple(ty)); | ||
217 | } | ||
218 | "pat" => { | ||
219 | let pat = input.eat_pat().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
220 | res.inner.insert(text.clone(), Binding::Simple(pat)); | ||
221 | } | ||
222 | "stmt" => { | ||
223 | let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
224 | res.inner.insert(text.clone(), Binding::Simple(pat)); | ||
225 | } | ||
226 | "block" => { | ||
227 | let block = | ||
228 | input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
229 | res.inner.insert(text.clone(), Binding::Simple(block)); | ||
230 | } | ||
231 | "meta" => { | ||
232 | let meta = | ||
233 | input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
234 | res.inner.insert(text.clone(), Binding::Simple(meta)); | ||
235 | } | ||
236 | "tt" => { | ||
237 | let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
238 | res.inner.insert(text.clone(), Binding::Simple(token)); | ||
239 | } | ||
240 | "item" => { | ||
241 | let item = | ||
242 | input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
243 | res.inner.insert(text.clone(), Binding::Simple(item)); | ||
244 | } | ||
245 | "lifetime" => { | ||
246 | let lifetime = | ||
247 | input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
248 | res.inner.insert(text.clone(), Binding::Simple(lifetime)); | ||
249 | } | 200 | } |
250 | "literal" => { | 201 | None => res.push_optional(text), |
251 | let literal = | ||
252 | input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
253 | |||
254 | res.inner.insert( | ||
255 | text.clone(), | ||
256 | Binding::Simple(tt::Leaf::from(literal).into()), | ||
257 | ); | ||
258 | } | ||
259 | "vis" => { | ||
260 | // `vis` is optional | ||
261 | if let Some(vis) = input.try_eat_vis() { | ||
262 | let vis = vis.clone(); | ||
263 | res.inner.insert(text.clone(), Binding::Simple(vis)); | ||
264 | } else { | ||
265 | res.push_optional(&text); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | _ => return Err(ExpandError::UnexpectedToken), | ||
270 | } | 202 | } |
271 | } | 203 | } |
272 | crate::Leaf::Punct(punct) => { | 204 | crate::Leaf::Punct(punct) => { |
@@ -360,6 +292,42 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
360 | Ok(res) | 292 | Ok(res) |
361 | } | 293 | } |
362 | 294 | ||
295 | fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTree>, ExpandError> { | ||
296 | let fragment = match kind { | ||
297 | "path" => Path, | ||
298 | "expr" => Expr, | ||
299 | "ty" => Type, | ||
300 | "pat" => Pattern, | ||
301 | "stmt" => Statement, | ||
302 | "block" => Block, | ||
303 | "meta" => MetaItem, | ||
304 | "item" => Item, | ||
305 | _ => { | ||
306 | let binding = match kind { | ||
307 | "ident" => { | ||
308 | let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
309 | tt::Leaf::from(ident).into() | ||
310 | } | ||
311 | "tt" => input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(), | ||
312 | "lifetime" => input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(), | ||
313 | "literal" => { | ||
314 | let literal = input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
315 | tt::Leaf::from(literal).into() | ||
316 | } | ||
317 | // `vis` is optional | ||
318 | "vis" => match input.try_eat_vis() { | ||
319 | Some(vis) => vis, | ||
320 | None => return Ok(None), | ||
321 | }, | ||
322 | _ => return Err(ExpandError::UnexpectedToken), | ||
323 | }; | ||
324 | return Ok(Some(binding)); | ||
325 | } | ||
326 | }; | ||
327 | let binding = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; | ||
328 | Ok(Some(binding)) | ||
329 | } | ||
330 | |||
363 | #[derive(Debug)] | 331 | #[derive(Debug)] |
364 | struct ExpandCtx<'a> { | 332 | struct ExpandCtx<'a> { |
365 | bindings: &'a Bindings, | 333 | bindings: &'a Bindings, |
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 5688e7f7f..4440c69ff 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use crate::subtree_source::SubtreeTokenSource; | 1 | use crate::subtree_source::SubtreeTokenSource; |
2 | 2 | ||
3 | use ra_parser::{TokenSource, TreeSink}; | 3 | use ra_parser::{FragmentKind, TokenSource, TreeSink}; |
4 | use ra_syntax::SyntaxKind; | 4 | use ra_syntax::SyntaxKind; |
5 | use tt::buffer::{Cursor, TokenBuffer}; | 5 | use tt::buffer::{Cursor, TokenBuffer}; |
6 | 6 | ||
@@ -52,40 +52,10 @@ impl<'a> Parser<'a> { | |||
52 | Parser { cur_pos, subtree } | 52 | Parser { cur_pos, subtree } |
53 | } | 53 | } |
54 | 54 | ||
55 | pub fn parse_path(self) -> Option<tt::TokenTree> { | 55 | pub fn parse_fragment(self, fragment_kind: FragmentKind) -> Option<tt::TokenTree> { |
56 | self.parse(ra_parser::parse_path) | 56 | self.parse(|token_source, tree_skink| { |
57 | } | 57 | ra_parser::parse_fragment(token_source, tree_skink, fragment_kind) |
58 | 58 | }) | |
59 | pub fn parse_expr(self) -> Option<tt::TokenTree> { | ||
60 | self.parse(ra_parser::parse_expr) | ||
61 | } | ||
62 | |||
63 | pub fn parse_ty(self) -> Option<tt::TokenTree> { | ||
64 | self.parse(ra_parser::parse_ty) | ||
65 | } | ||
66 | |||
67 | pub fn parse_pat(self) -> Option<tt::TokenTree> { | ||
68 | self.parse(ra_parser::parse_pat) | ||
69 | } | ||
70 | |||
71 | pub fn parse_stmt(self) -> Option<tt::TokenTree> { | ||
72 | self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false)) | ||
73 | } | ||
74 | |||
75 | pub fn parse_block(self) -> Option<tt::TokenTree> { | ||
76 | self.parse(ra_parser::parse_block) | ||
77 | } | ||
78 | |||
79 | pub fn parse_meta(self) -> Option<tt::TokenTree> { | ||
80 | self.parse(ra_parser::parse_meta) | ||
81 | } | ||
82 | |||
83 | pub fn parse_item(self) -> Option<tt::TokenTree> { | ||
84 | self.parse(ra_parser::parse_item) | ||
85 | } | ||
86 | |||
87 | pub fn parse_vis(self) -> Option<tt::TokenTree> { | ||
88 | self.parse(ra_parser::parse_vis) | ||
89 | } | 59 | } |
90 | 60 | ||
91 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> | 61 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8225759e7..a380b1cfd 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use ra_parser::{ParseError, TreeSink}; | 1 | use ra_parser::{ |
2 | FragmentKind::{self, *}, | ||
3 | ParseError, TreeSink, | ||
4 | }; | ||
2 | use ra_syntax::{ | 5 | use ra_syntax::{ |
3 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, | 6 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, |
4 | SyntaxTreeBuilder, TextRange, TextUnit, T, | 7 | SyntaxTreeBuilder, TextRange, TextUnit, T, |
@@ -63,33 +66,50 @@ where | |||
63 | Ok(parse) | 66 | Ok(parse) |
64 | } | 67 | } |
65 | 68 | ||
69 | fn fragment_to_syntax_node( | ||
70 | tt: &tt::Subtree, | ||
71 | fragment_kind: FragmentKind, | ||
72 | ) -> Result<Parse<SyntaxNode>, ExpandError> { | ||
73 | let tokens = [tt.clone().into()]; | ||
74 | let buffer = TokenBuffer::new(&tokens); | ||
75 | let mut token_source = SubtreeTokenSource::new(&buffer); | ||
76 | let mut tree_sink = TtTreeSink::new(buffer.begin()); | ||
77 | ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind); | ||
78 | if tree_sink.roots.len() != 1 { | ||
79 | return Err(ExpandError::ConversionError); | ||
80 | } | ||
81 | //FIXME: would be cool to report errors | ||
82 | let parse = tree_sink.inner.finish(); | ||
83 | Ok(parse) | ||
84 | } | ||
85 | |||
66 | /// Parses the token tree (result of macro expansion) to an expression | 86 | /// Parses the token tree (result of macro expansion) to an expression |
67 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { | 87 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { |
68 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_expr)?; | 88 | let parse = fragment_to_syntax_node(tt, Expr)?; |
69 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 89 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
70 | } | 90 | } |
71 | 91 | ||
72 | /// Parses the token tree (result of macro expansion) to a Pattern | 92 | /// Parses the token tree (result of macro expansion) to a Pattern |
73 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { | 93 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { |
74 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_pat)?; | 94 | let parse = fragment_to_syntax_node(tt, Pattern)?; |
75 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 95 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
76 | } | 96 | } |
77 | 97 | ||
78 | /// Parses the token tree (result of macro expansion) to a Type | 98 | /// Parses the token tree (result of macro expansion) to a Type |
79 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { | 99 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { |
80 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_ty)?; | 100 | let parse = fragment_to_syntax_node(tt, Type)?; |
81 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 101 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
82 | } | 102 | } |
83 | 103 | ||
84 | /// Parses the token tree (result of macro expansion) as a sequence of stmts | 104 | /// Parses the token tree (result of macro expansion) as a sequence of stmts |
85 | pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { | 105 | pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { |
86 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_stmts)?; | 106 | let parse = fragment_to_syntax_node(tt, Statements)?; |
87 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 107 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
88 | } | 108 | } |
89 | 109 | ||
90 | /// Parses the token tree (result of macro expansion) as a sequence of items | 110 | /// Parses the token tree (result of macro expansion) as a sequence of items |
91 | pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { | 111 | pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { |
92 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_items)?; | 112 | let parse = fragment_to_syntax_node(tt, Items)?; |
93 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 113 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
94 | } | 114 | } |
95 | 115 | ||
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index 468276397..a69c006c7 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use crate::subtree_parser::Parser; | 1 | use crate::{subtree_parser::Parser, ParseError}; |
2 | use crate::ParseError; | 2 | |
3 | use ra_parser::FragmentKind; | ||
3 | use smallvec::{smallvec, SmallVec}; | 4 | use smallvec::{smallvec, SmallVec}; |
4 | 5 | ||
5 | #[derive(Debug, Clone)] | 6 | #[derive(Debug, Clone)] |
@@ -98,44 +99,9 @@ impl<'a> TtCursor<'a> { | |||
98 | }) | 99 | }) |
99 | } | 100 | } |
100 | 101 | ||
101 | pub(crate) fn eat_path(&mut self) -> Option<tt::TokenTree> { | 102 | pub(crate) fn eat_fragment(&mut self, fragment_kind: FragmentKind) -> Option<tt::TokenTree> { |
102 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
103 | parser.parse_path() | ||
104 | } | ||
105 | |||
106 | pub(crate) fn eat_expr(&mut self) -> Option<tt::TokenTree> { | ||
107 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
108 | parser.parse_expr() | ||
109 | } | ||
110 | |||
111 | pub(crate) fn eat_ty(&mut self) -> Option<tt::TokenTree> { | ||
112 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
113 | parser.parse_ty() | ||
114 | } | ||
115 | |||
116 | pub(crate) fn eat_pat(&mut self) -> Option<tt::TokenTree> { | ||
117 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
118 | parser.parse_pat() | ||
119 | } | ||
120 | |||
121 | pub(crate) fn eat_stmt(&mut self) -> Option<tt::TokenTree> { | ||
122 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
123 | parser.parse_stmt() | ||
124 | } | ||
125 | |||
126 | pub(crate) fn eat_block(&mut self) -> Option<tt::TokenTree> { | ||
127 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
128 | parser.parse_block() | ||
129 | } | ||
130 | |||
131 | pub(crate) fn eat_meta(&mut self) -> Option<tt::TokenTree> { | ||
132 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
133 | parser.parse_meta() | ||
134 | } | ||
135 | |||
136 | pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> { | ||
137 | let parser = Parser::new(&mut self.pos, self.subtree); | 103 | let parser = Parser::new(&mut self.pos, self.subtree); |
138 | parser.parse_item() | 104 | parser.parse_fragment(fragment_kind) |
139 | } | 105 | } |
140 | 106 | ||
141 | pub(crate) fn eat_lifetime(&mut self) -> Option<tt::TokenTree> { | 107 | pub(crate) fn eat_lifetime(&mut self) -> Option<tt::TokenTree> { |
@@ -154,7 +120,7 @@ impl<'a> TtCursor<'a> { | |||
154 | let old_pos = self.pos; | 120 | let old_pos = self.pos; |
155 | let parser = Parser::new(&mut self.pos, self.subtree); | 121 | let parser = Parser::new(&mut self.pos, self.subtree); |
156 | 122 | ||
157 | let res = parser.parse_vis(); | 123 | let res = parser.parse_fragment(FragmentKind::Visibility); |
158 | if res.is_none() { | 124 | if res.is_none() { |
159 | self.pos = old_pos; | 125 | self.pos = old_pos; |
160 | } | 126 | } |