Remove Queier and SubtreeWalk

This commit is contained in:
Edwin Cheng 2019-05-27 22:56:21 +08:00
parent 0d1c607607
commit d833ded3b4
2 changed files with 104 additions and 92 deletions

View file

@ -1,13 +1,8 @@
use ra_parser::{TokenSource, Token}; use ra_parser::{TokenSource, Token};
use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use std::sync::Arc;
use tt::buffer::{TokenBuffer, Cursor}; use tt::buffer::{TokenBuffer, Cursor};
pub(crate) trait Querier {
fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool);
}
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
struct TtToken { struct TtToken {
pub kind: SyntaxKind, pub kind: SyntaxKind,
@ -15,20 +10,47 @@ struct TtToken {
pub text: SmolStr, pub text: SmolStr,
} }
// A wrapper class for ref cell pub(crate) struct SubtreeTokenSource<'a> {
#[derive(Debug)]
pub(crate) struct SubtreeWalk<'a> {
start: Cursor<'a>, start: Cursor<'a>,
cursor: Cell<Cursor<'a>>, cursor: Cell<Cursor<'a>>,
cached: RefCell<Vec<Option<TtToken>>>, cached: RefCell<Vec<Option<TtToken>>>,
curr: (Token, usize),
} }
impl<'a> SubtreeWalk<'a> { impl<'a> SubtreeTokenSource<'a> {
fn new(cursor: Cursor<'a>) -> Self { // Helper function used in test
SubtreeWalk { #[allow(unused)]
pub fn text(&self) -> SmolStr {
match self.get(self.curr.1) {
Some(tt) => tt.text,
_ => SmolStr::new(""),
}
}
}
impl<'a> SubtreeTokenSource<'a> {
pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
let cursor = buffer.begin();
let mut res = SubtreeTokenSource {
curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
start: cursor, start: cursor,
cursor: Cell::new(cursor), cursor: Cell::new(cursor),
cached: RefCell::new(Vec::with_capacity(10)), cached: RefCell::new(Vec::with_capacity(10)),
};
res.curr = (res.mk_token(0), 0);
res
}
pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<tt::TokenTree> {
let res = self.collect_token_trees(parsed_tokens);
res
}
fn mk_token(&self, pos: usize) -> Token {
match self.get(pos) {
Some(tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
None => Token { kind: EOF, is_jointed_to_next: false },
} }
} }
@ -109,46 +131,6 @@ impl<'a> SubtreeWalk<'a> {
} }
} }
impl<'a> Querier for SubtreeWalk<'a> {
fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool) {
self.get(uidx)
.map(|tkn| (tkn.kind, tkn.text, tkn.is_joint_to_next))
.unwrap_or_else(|| (SyntaxKind::EOF, "".into(), false))
}
}
pub(crate) struct SubtreeTokenSource<'a> {
walker: Arc<SubtreeWalk<'a>>,
curr: (Token, usize),
}
impl<'a> SubtreeTokenSource<'a> {
pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
let mut res = SubtreeTokenSource {
walker: Arc::new(SubtreeWalk::new(buffer.begin())),
curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
};
res.curr = (res.mk_token(0), 0);
res
}
pub fn querier(&self) -> Arc<SubtreeWalk<'a>> {
self.walker.clone()
}
pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<tt::TokenTree> {
let res = self.walker.collect_token_trees(parsed_tokens);
res
}
fn mk_token(&self, pos: usize) -> Token {
match self.walker.get(pos) {
Some(tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
None => Token { kind: EOF, is_jointed_to_next: false },
}
}
}
impl<'a> TokenSource for SubtreeTokenSource<'a> { impl<'a> TokenSource for SubtreeTokenSource<'a> {
fn current(&self) -> Token { fn current(&self) -> Token {
self.curr.0 self.curr.0
@ -170,7 +152,7 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> {
/// Is the current token a specified keyword? /// Is the current token a specified keyword?
fn is_keyword(&self, kw: &str) -> bool { fn is_keyword(&self, kw: &str) -> bool {
match self.walker.get(self.curr.1) { match self.get(self.curr.1) {
Some(t) => t.text == *kw, Some(t) => t.text == *kw,
_ => false, _ => false,
} }

View file

@ -3,8 +3,9 @@ use ra_syntax::{
AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc, SyntaxElement, AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc, SyntaxElement,
ast, SyntaxKind::*, TextUnit, T ast, SyntaxKind::*, TextUnit, T
}; };
use tt::buffer::Cursor;
use crate::subtree_source::{SubtreeTokenSource, Querier}; use crate::subtree_source::{SubtreeTokenSource};
use crate::ExpandError; use crate::ExpandError;
/// Maps `tt::TokenId` to the relative range of the original token. /// Maps `tt::TokenId` to the relative range of the original token.
@ -51,8 +52,7 @@ where
{ {
let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]);
let mut token_source = SubtreeTokenSource::new(&buffer); let mut token_source = SubtreeTokenSource::new(&buffer);
let querier = token_source.querier(); let mut tree_sink = TtTreeSink::new(buffer.begin());
let mut tree_sink = TtTreeSink::new(querier.as_ref());
f(&mut token_source, &mut tree_sink); f(&mut token_source, &mut tree_sink);
if tree_sink.roots.len() != 1 { if tree_sink.roots.len() != 1 {
return Err(ExpandError::ConversionError); return Err(ExpandError::ConversionError);
@ -259,11 +259,10 @@ fn convert_tt(
Some(res) Some(res)
} }
struct TtTreeSink<'a, Q: Querier> { struct TtTreeSink<'a> {
buf: String, buf: String,
src_querier: &'a Q, cursor: Cursor<'a>,
text_pos: TextUnit, text_pos: TextUnit,
token_pos: usize,
inner: SyntaxTreeBuilder, inner: SyntaxTreeBuilder,
// Number of roots // Number of roots
@ -271,52 +270,79 @@ struct TtTreeSink<'a, Q: Querier> {
roots: smallvec::SmallVec<[usize; 1]>, roots: smallvec::SmallVec<[usize; 1]>,
} }
impl<'a, Q: Querier> TtTreeSink<'a, Q> { impl<'a> TtTreeSink<'a> {
fn new(src_querier: &'a Q) -> Self { fn new(cursor: Cursor<'a>) -> Self {
TtTreeSink { TtTreeSink {
buf: String::new(), buf: String::new(),
src_querier, cursor,
text_pos: 0.into(), text_pos: 0.into(),
token_pos: 0,
inner: SyntaxTreeBuilder::default(), inner: SyntaxTreeBuilder::default(),
roots: smallvec::SmallVec::new(), roots: smallvec::SmallVec::new(),
} }
} }
} }
fn is_delimiter(kind: SyntaxKind) -> bool { fn delim_to_str(d: tt::Delimiter, closing: bool) -> SmolStr {
match kind { let texts = match d {
T!['('] | T!['['] | T!['{'] | T![')'] | T![']'] | T!['}'] => true, tt::Delimiter::Parenthesis => "()",
_ => false, tt::Delimiter::Brace => "{}",
} tt::Delimiter::Bracket => "[]",
tt::Delimiter::None => "",
};
let idx = closing as usize;
let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
text.into()
} }
impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { impl<'a> TreeSink for TtTreeSink<'a> {
fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
if kind == L_DOLLAR || kind == R_DOLLAR { if kind == L_DOLLAR || kind == R_DOLLAR {
self.token_pos += n_tokens as usize; if let Some(_) = self.cursor.end() {
self.cursor = self.cursor.bump();
} else {
self.cursor = self.cursor.subtree().unwrap();
}
return; return;
} }
for _ in 0..n_tokens { for _ in 0..n_tokens {
self.buf += &self.src_querier.token(self.token_pos).1; if self.cursor.eof() {
self.token_pos += 1; break;
}
match self.cursor.token_tree() {
Some(tt::TokenTree::Leaf(leaf)) => {
self.cursor = self.cursor.bump();
self.buf += &format!("{}", leaf);
}
Some(tt::TokenTree::Subtree(subtree)) => {
self.cursor = self.cursor.subtree().unwrap();
self.buf += &delim_to_str(subtree.delimiter, false);
}
None => {
if let Some(parent) = self.cursor.end() {
self.cursor = self.cursor.bump();
self.buf += &delim_to_str(parent.delimiter, true);
}
}
};
} }
self.text_pos += TextUnit::of_str(&self.buf); self.text_pos += TextUnit::of_str(&self.buf);
let text = SmolStr::new(self.buf.as_str()); let text = SmolStr::new(self.buf.as_str());
self.buf.clear(); self.buf.clear();
self.inner.token(kind, text); self.inner.token(kind, text);
// Add a white space between tokens, only if both are not delimiters // Add whitespace between adjoint puncts
if !is_delimiter(kind) { let next = self.cursor.bump();
let (last_kind, _, last_joint_to_next) = self.src_querier.token(self.token_pos - 1); if let (
if !last_joint_to_next && last_kind.is_punct() { Some(tt::TokenTree::Leaf(tt::Leaf::Punct(curr))),
let (cur_kind, _, _) = self.src_querier.token(self.token_pos); Some(tt::TokenTree::Leaf(tt::Leaf::Punct(_))),
if !is_delimiter(cur_kind) { ) = (self.cursor.token_tree(), next.token_tree())
if cur_kind.is_punct() { {
self.inner.token(WHITESPACE, " ".into()); if curr.spacing == tt::Spacing::Alone {
} self.inner.token(WHITESPACE, " ".into());
}
} }
} }
} }
@ -344,6 +370,7 @@ impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> {
mod tests { mod tests {
use super::*; use super::*;
use crate::tests::{expand, create_rules}; use crate::tests::{expand, create_rules};
use ra_parser::TokenSource;
#[test] #[test]
fn convert_tt_token_source() { fn convert_tt_token_source() {
@ -363,24 +390,27 @@ mod tests {
); );
let expansion = expand(&rules, "literals!(foo)"); let expansion = expand(&rules, "literals!(foo)");
let buffer = tt::buffer::TokenBuffer::new(&[expansion.clone().into()]); let buffer = tt::buffer::TokenBuffer::new(&[expansion.clone().into()]);
let tt_src = SubtreeTokenSource::new(&buffer); let mut tt_src = SubtreeTokenSource::new(&buffer);
let mut tokens = vec![];
let query = tt_src.querier(); while tt_src.current().kind != EOF {
tokens.push((tt_src.current().kind, tt_src.text()));
tt_src.bump();
}
// [${] // [${]
// [let] [a] [=] ['c'] [;] // [let] [a] [=] ['c'] [;]
assert_eq!(query.token(2 + 3).1, "'c'"); assert_eq!(tokens[2 + 3].1, "'c'");
assert_eq!(query.token(2 + 3).0, CHAR); assert_eq!(tokens[2 + 3].0, CHAR);
// [let] [c] [=] [1000] [;] // [let] [c] [=] [1000] [;]
assert_eq!(query.token(2 + 5 + 3).1, "1000"); assert_eq!(tokens[2 + 5 + 3].1, "1000");
assert_eq!(query.token(2 + 5 + 3).0, INT_NUMBER); assert_eq!(tokens[2 + 5 + 3].0, INT_NUMBER);
// [let] [f] [=] [12E+99_f64] [;] // [let] [f] [=] [12E+99_f64] [;]
assert_eq!(query.token(2 + 10 + 3).1, "12E+99_f64"); assert_eq!(tokens[2 + 10 + 3].1, "12E+99_f64");
assert_eq!(query.token(2 + 10 + 3).0, FLOAT_NUMBER); assert_eq!(tokens[2 + 10 + 3].0, FLOAT_NUMBER);
// [let] [s] [=] ["rust1"] [;] // [let] [s] [=] ["rust1"] [;]
assert_eq!(query.token(2 + 15 + 3).1, "\"rust1\""); assert_eq!(tokens[2 + 15 + 3].1, "\"rust1\"");
assert_eq!(query.token(2 + 15 + 3).0, STRING); assert_eq!(tokens[2 + 15 + 3].0, STRING);
} }
#[test] #[test]