aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r--crates/ra_mbe/src/lib.rs2
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs58
2 files changed, 55 insertions, 5 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index cdca3cafb..768f335fa 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -24,7 +24,7 @@ use ra_syntax::SmolStr;
24 24
25pub use tt::{Delimiter, Punct}; 25pub use tt::{Delimiter, Punct};
26 26
27pub use crate::syntax_bridge::ast_to_token_tree; 27pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list};
28 28
29/// This struct contains AST for a single `macro_rules` definition. What might 29/// This struct contains AST for a single `macro_rules` definition. What might
30/// be very confusing is that AST has almost exactly the same shape as 30/// be very confusing is that AST has almost exactly the same shape as
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 24a043175..521b96d68 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -1,6 +1,6 @@
1use ra_parser::TokenSource; 1use ra_parser::{TokenSource, TreeSink, ParseError};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, 3 AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc,
4 ast, SyntaxKind::*, TextUnit 4 ast, SyntaxKind::*, TextUnit
5}; 5};
6 6
@@ -21,8 +21,12 @@ pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)
21} 21}
22 22
23/// Parses the token tree (result of macro expansion) as a sequence of items 23/// Parses the token tree (result of macro expansion) as a sequence of items
24pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> ast::SourceFile { 24pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> {
25 unimplemented!() 25 let token_source = TtTokenSource::new(tt);
26 let mut tree_sink = TtTreeSink::new(&token_source.tokens);
27 ra_parser::parse(&token_source, &mut tree_sink);
28 let syntax = tree_sink.inner.finish();
29 ast::SourceFile::cast(&syntax).unwrap().to_owned()
26} 30}
27 31
28impl TokenMap { 32impl TokenMap {
@@ -166,3 +170,49 @@ impl TokenSource for TtTokenSource {
166 self.tokens[pos].text == *kw 170 self.tokens[pos].text == *kw
167 } 171 }
168} 172}
173
174#[derive(Default)]
175struct TtTreeSink<'a> {
176 buf: String,
177 tokens: &'a [Tok],
178 text_pos: TextUnit,
179 token_pos: usize,
180 inner: SyntaxTreeBuilder,
181}
182
183impl<'a> TtTreeSink<'a> {
184 fn new(tokens: &'a [Tok]) -> TtTreeSink {
185 TtTreeSink {
186 buf: String::new(),
187 tokens,
188 text_pos: 0.into(),
189 token_pos: 0,
190 inner: SyntaxTreeBuilder::default(),
191 }
192 }
193}
194
195impl<'a> TreeSink for TtTreeSink<'a> {
196 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
197 for _ in 0..n_tokens {
198 self.buf += self.tokens[self.token_pos].text.as_str();
199 self.token_pos += 1;
200 }
201 self.text_pos += TextUnit::of_str(&self.buf);
202 let text = SmolStr::new(self.buf.as_str());
203 self.buf.clear();
204 self.inner.leaf(kind, text)
205 }
206
207 fn start_branch(&mut self, kind: SyntaxKind) {
208 self.inner.start_branch(kind);
209 }
210
211 fn finish_branch(&mut self) {
212 self.inner.finish_branch();
213 }
214
215 fn error(&mut self, error: ParseError) {
216 self.inner.error(error, self.text_pos)
217 }
218}