implement tt -> ast

This commit is contained in:
Aleksey Kladov 2019-02-23 17:21:56 +03:00
parent 83d6be6cec
commit 8eac450f41
2 changed files with 55 additions and 5 deletions

View File

@ -24,7 +24,7 @@ use ra_syntax::SmolStr;
pub use tt::{Delimiter, Punct};
pub use crate::syntax_bridge::ast_to_token_tree;
pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list};
/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as

View File

@ -1,6 +1,6 @@
use ra_parser::TokenSource;
use ra_parser::{TokenSource, TreeSink, ParseError};
use ra_syntax::{
AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr,
AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc,
ast, SyntaxKind::*, TextUnit
};
@ -21,8 +21,12 @@ pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)
}
/// Parses the token tree (result of macro expansion) as a sequence of items
pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> ast::SourceFile {
unimplemented!()
pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> {
let token_source = TtTokenSource::new(tt);
let mut tree_sink = TtTreeSink::new(&token_source.tokens);
ra_parser::parse(&token_source, &mut tree_sink);
let syntax = tree_sink.inner.finish();
ast::SourceFile::cast(&syntax).unwrap().to_owned()
}
impl TokenMap {
@ -166,3 +170,49 @@ impl TokenSource for TtTokenSource {
self.tokens[pos].text == *kw
}
}
#[derive(Default)]
struct TtTreeSink<'a> {
buf: String,
tokens: &'a [Tok],
text_pos: TextUnit,
token_pos: usize,
inner: SyntaxTreeBuilder,
}
impl<'a> TtTreeSink<'a> {
fn new(tokens: &'a [Tok]) -> TtTreeSink {
TtTreeSink {
buf: String::new(),
tokens,
text_pos: 0.into(),
token_pos: 0,
inner: SyntaxTreeBuilder::default(),
}
}
}
impl<'a> TreeSink for TtTreeSink<'a> {
fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8) {
for _ in 0..n_tokens {
self.buf += self.tokens[self.token_pos].text.as_str();
self.token_pos += 1;
}
self.text_pos += TextUnit::of_str(&self.buf);
let text = SmolStr::new(self.buf.as_str());
self.buf.clear();
self.inner.leaf(kind, text)
}
fn start_branch(&mut self, kind: SyntaxKind) {
self.inner.start_branch(kind);
}
fn finish_branch(&mut self) {
self.inner.finish_branch();
}
fn error(&mut self, error: ParseError) {
self.inner.error(error, self.text_pos)
}
}