diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-27 08:28:13 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-27 08:28:13 +0100 |
commit | ce694ae11854a806031db98c51c068253f927519 (patch) | |
tree | 2996ecd85ff9aa57b6f208e83d42dd03a7370d1e /crates/ra_mbe | |
parent | 4f4e50db908ba44f113faeb356ae2b3d0788d308 (diff) | |
parent | 90764fc54b2be1e0fc5d6ac9c9e960d7bb059b14 (diff) |
Merge #1328
1328: Change TokenSource to iteration based r=matklad a=edwin0cheng
This PR change the `TokenSource` trait from random access to be an iteration based trait:
```rust
/// `TokenSource` abstracts the source of the tokens parser operates one.
///
/// Hopefully this will allow us to treat text and token trees in the same way!
pub trait TokenSource {
fn current(&self) -> Token;
/// Lookahead n token
fn lookahead_nth(&self, n: usize) -> Token;
/// bump cursor to next token
fn bump(&mut self);
/// Is the current token a specified keyword?
fn is_keyword(&self, kw: &str) -> bool;
}
/// `TokenCursor` abstracts the cursor of `TokenSource` operates one.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Token {
/// What is the current token?
pub kind: SyntaxKind,
/// Is the current token joined to the next one (`> >` vs `>>`).
pub is_jointed_to_next: bool,
}
```
Note that the refactoring based on this new trait will be separated to incoming PRs
Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_source.rs | 59 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 63 |
3 files changed, 59 insertions, 67 deletions
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 709b87a38..9cc989b23 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -68,13 +68,13 @@ impl<'a> Parser<'a> { | |||
68 | 68 | ||
69 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> | 69 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> |
70 | where | 70 | where |
71 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), | 71 | F: FnOnce(&mut dyn TokenSource, &mut dyn TreeSink), |
72 | { | 72 | { |
73 | let buffer = TokenBuffer::new(&self.subtree.token_trees[*self.cur_pos..]); | 73 | let buffer = TokenBuffer::new(&self.subtree.token_trees[*self.cur_pos..]); |
74 | let mut src = SubtreeTokenSource::new(&buffer); | 74 | let mut src = SubtreeTokenSource::new(&buffer); |
75 | let mut sink = OffsetTokenSink { token_pos: 0, error: false }; | 75 | let mut sink = OffsetTokenSink { token_pos: 0, error: false }; |
76 | 76 | ||
77 | f(&src, &mut sink); | 77 | f(&mut src, &mut sink); |
78 | 78 | ||
79 | let r = self.finish(sink.token_pos, &mut src); | 79 | let r = self.finish(sink.token_pos, &mut src); |
80 | if sink.error { | 80 | if sink.error { |
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 972af4a7c..c4f79f38a 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use ra_parser::{TokenSource}; | 1 | use ra_parser::{TokenSource, Token}; |
2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; | 2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; |
3 | use std::cell::{RefCell, Cell}; | 3 | use std::cell::{RefCell, Cell}; |
4 | use std::sync::Arc; | ||
4 | use tt::buffer::{TokenBuffer, Cursor}; | 5 | use tt::buffer::{TokenBuffer, Cursor}; |
5 | 6 | ||
6 | pub(crate) trait Querier { | 7 | pub(crate) trait Querier { |
@@ -65,7 +66,7 @@ impl<'a> SubtreeWalk<'a> { | |||
65 | return cached[pos].clone(); | 66 | return cached[pos].clone(); |
66 | } | 67 | } |
67 | 68 | ||
68 | fn collect_token_trees(&mut self, n: usize) -> Vec<tt::TokenTree> { | 69 | fn collect_token_trees(&self, n: usize) -> Vec<tt::TokenTree> { |
69 | let mut res = vec![]; | 70 | let mut res = vec![]; |
70 | 71 | ||
71 | let mut pos = 0; | 72 | let mut pos = 0; |
@@ -117,43 +118,59 @@ impl<'a> Querier for SubtreeWalk<'a> { | |||
117 | } | 118 | } |
118 | 119 | ||
119 | pub(crate) struct SubtreeTokenSource<'a> { | 120 | pub(crate) struct SubtreeTokenSource<'a> { |
120 | walker: SubtreeWalk<'a>, | 121 | walker: Arc<SubtreeWalk<'a>>, |
122 | curr: (Token, usize), | ||
121 | } | 123 | } |
122 | 124 | ||
123 | impl<'a> SubtreeTokenSource<'a> { | 125 | impl<'a> SubtreeTokenSource<'a> { |
124 | pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> { | 126 | pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> { |
125 | SubtreeTokenSource { walker: SubtreeWalk::new(buffer.begin()) } | 127 | let mut res = SubtreeTokenSource { |
128 | walker: Arc::new(SubtreeWalk::new(buffer.begin())), | ||
129 | curr: (Token { kind: EOF, is_jointed_to_next: false }, 0), | ||
130 | }; | ||
131 | res.curr = (res.mk_token(0), 0); | ||
132 | res | ||
126 | } | 133 | } |
127 | 134 | ||
128 | pub fn querier<'b>(&'a self) -> &'b SubtreeWalk<'a> | 135 | pub fn querier(&self) -> Arc<SubtreeWalk<'a>> { |
129 | where | 136 | self.walker.clone() |
130 | 'a: 'b, | ||
131 | { | ||
132 | &self.walker | ||
133 | } | 137 | } |
134 | 138 | ||
135 | pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<tt::TokenTree> { | 139 | pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<tt::TokenTree> { |
136 | let res = self.walker.collect_token_trees(parsed_tokens); | 140 | let res = self.walker.collect_token_trees(parsed_tokens); |
137 | res | 141 | res |
138 | } | 142 | } |
143 | |||
144 | fn mk_token(&self, pos: usize) -> Token { | ||
145 | match self.walker.get(pos) { | ||
146 | Some(tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next }, | ||
147 | None => Token { kind: EOF, is_jointed_to_next: false }, | ||
148 | } | ||
149 | } | ||
139 | } | 150 | } |
140 | 151 | ||
141 | impl<'a> TokenSource for SubtreeTokenSource<'a> { | 152 | impl<'a> TokenSource for SubtreeTokenSource<'a> { |
142 | fn token_kind(&self, pos: usize) -> SyntaxKind { | 153 | fn current(&self) -> Token { |
143 | if let Some(tok) = self.walker.get(pos) { | 154 | self.curr.0 |
144 | tok.kind | ||
145 | } else { | ||
146 | SyntaxKind::EOF | ||
147 | } | ||
148 | } | 155 | } |
149 | fn is_token_joint_to_next(&self, pos: usize) -> bool { | 156 | |
150 | match self.walker.get(pos) { | 157 | /// Lookahead n token |
151 | Some(t) => t.is_joint_to_next, | 158 | fn lookahead_nth(&self, n: usize) -> Token { |
152 | _ => false, | 159 | self.mk_token(self.curr.1 + n) |
160 | } | ||
161 | |||
162 | /// bump cursor to next token | ||
163 | fn bump(&mut self) { | ||
164 | if self.current().kind == EOF { | ||
165 | return; | ||
153 | } | 166 | } |
167 | |||
168 | self.curr = (self.mk_token(self.curr.1 + 1), self.curr.1 + 1) | ||
154 | } | 169 | } |
155 | fn is_keyword(&self, pos: usize, kw: &str) -> bool { | 170 | |
156 | match self.walker.get(pos) { | 171 | /// Is the current token a specified keyword? |
172 | fn is_keyword(&self, kw: &str) -> bool { | ||
173 | match self.walker.get(self.curr.1) { | ||
157 | Some(t) => t.text == *kw, | 174 | Some(t) => t.text == *kw, |
158 | _ => false, | 175 | _ => false, |
159 | } | 176 | } |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 0a75305b4..0a7e50c4e 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -45,17 +45,25 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke | |||
45 | // | 45 | // |
46 | // | 46 | // |
47 | 47 | ||
48 | /// Parses the token tree (result of macro expansion) to an expression | 48 | fn token_tree_to_syntax_node<F>(tt: &tt::Subtree, f: F) -> Result<TreeArc<SyntaxNode>, ExpandError> |
49 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, ExpandError> { | 49 | where |
50 | F: Fn(&mut ra_parser::TokenSource, &mut ra_parser::TreeSink), | ||
51 | { | ||
50 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 52 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
51 | let token_source = SubtreeTokenSource::new(&buffer); | 53 | let mut token_source = SubtreeTokenSource::new(&buffer); |
52 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 54 | let querier = token_source.querier(); |
53 | ra_parser::parse_expr(&token_source, &mut tree_sink); | 55 | let mut tree_sink = TtTreeSink::new(querier.as_ref()); |
56 | f(&mut token_source, &mut tree_sink); | ||
54 | if tree_sink.roots.len() != 1 { | 57 | if tree_sink.roots.len() != 1 { |
55 | return Err(ExpandError::ConversionError); | 58 | return Err(ExpandError::ConversionError); |
56 | } | 59 | } |
57 | 60 | ||
58 | let syntax = tree_sink.inner.finish(); | 61 | Ok(tree_sink.inner.finish()) |
62 | } | ||
63 | |||
64 | /// Parses the token tree (result of macro expansion) to an expression | ||
65 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, ExpandError> { | ||
66 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_expr)?; | ||
59 | ast::Expr::cast(&syntax) | 67 | ast::Expr::cast(&syntax) |
60 | .map(|m| m.to_owned()) | 68 | .map(|m| m.to_owned()) |
61 | .ok_or_else(|| crate::ExpandError::ConversionError) | 69 | .ok_or_else(|| crate::ExpandError::ConversionError) |
@@ -63,28 +71,13 @@ pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, Expand | |||
63 | 71 | ||
64 | /// Parses the token tree (result of macro expansion) to a Pattern | 72 | /// Parses the token tree (result of macro expansion) to a Pattern |
65 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandError> { | 73 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandError> { |
66 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 74 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_pat)?; |
67 | let token_source = SubtreeTokenSource::new(&buffer); | ||
68 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | ||
69 | ra_parser::parse_pat(&token_source, &mut tree_sink); | ||
70 | if tree_sink.roots.len() != 1 { | ||
71 | return Err(ExpandError::ConversionError); | ||
72 | } | ||
73 | |||
74 | let syntax = tree_sink.inner.finish(); | ||
75 | ast::Pat::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) | 75 | ast::Pat::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) |
76 | } | 76 | } |
77 | 77 | ||
78 | /// Parses the token tree (result of macro expansion) to a Type | 78 | /// Parses the token tree (result of macro expansion) to a Type |
79 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, ExpandError> { | 79 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, ExpandError> { |
80 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 80 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_ty)?; |
81 | let token_source = SubtreeTokenSource::new(&buffer); | ||
82 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | ||
83 | ra_parser::parse_ty(&token_source, &mut tree_sink); | ||
84 | if tree_sink.roots.len() != 1 { | ||
85 | return Err(ExpandError::ConversionError); | ||
86 | } | ||
87 | let syntax = tree_sink.inner.finish(); | ||
88 | ast::TypeRef::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) | 81 | ast::TypeRef::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) |
89 | } | 82 | } |
90 | 83 | ||
@@ -92,14 +85,7 @@ pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, Expan | |||
92 | pub fn token_tree_to_macro_stmts( | 85 | pub fn token_tree_to_macro_stmts( |
93 | tt: &tt::Subtree, | 86 | tt: &tt::Subtree, |
94 | ) -> Result<TreeArc<ast::MacroStmts>, ExpandError> { | 87 | ) -> Result<TreeArc<ast::MacroStmts>, ExpandError> { |
95 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 88 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_macro_stmts)?; |
96 | let token_source = SubtreeTokenSource::new(&buffer); | ||
97 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | ||
98 | ra_parser::parse_macro_stmts(&token_source, &mut tree_sink); | ||
99 | if tree_sink.roots.len() != 1 { | ||
100 | return Err(ExpandError::ConversionError); | ||
101 | } | ||
102 | let syntax = tree_sink.inner.finish(); | ||
103 | ast::MacroStmts::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) | 89 | ast::MacroStmts::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) |
104 | } | 90 | } |
105 | 91 | ||
@@ -107,24 +93,13 @@ pub fn token_tree_to_macro_stmts( | |||
107 | pub fn token_tree_to_macro_items( | 93 | pub fn token_tree_to_macro_items( |
108 | tt: &tt::Subtree, | 94 | tt: &tt::Subtree, |
109 | ) -> Result<TreeArc<ast::MacroItems>, ExpandError> { | 95 | ) -> Result<TreeArc<ast::MacroItems>, ExpandError> { |
110 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 96 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_macro_items)?; |
111 | let token_source = SubtreeTokenSource::new(&buffer); | ||
112 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | ||
113 | ra_parser::parse_macro_items(&token_source, &mut tree_sink); | ||
114 | if tree_sink.roots.len() != 1 { | ||
115 | return Err(ExpandError::ConversionError); | ||
116 | } | ||
117 | let syntax = tree_sink.inner.finish(); | ||
118 | ast::MacroItems::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) | 97 | ast::MacroItems::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) |
119 | } | 98 | } |
120 | 99 | ||
121 | /// Parses the token tree (result of macro expansion) as a sequence of items | 100 | /// Parses the token tree (result of macro expansion) as a sequence of items |
122 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { | 101 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { |
123 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); | 102 | let syntax = token_tree_to_syntax_node(tt, ra_parser::parse).unwrap(); |
124 | let token_source = SubtreeTokenSource::new(&buffer); | ||
125 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | ||
126 | ra_parser::parse(&token_source, &mut tree_sink); | ||
127 | let syntax = tree_sink.inner.finish(); | ||
128 | ast::SourceFile::cast(&syntax).unwrap().to_owned() | 103 | ast::SourceFile::cast(&syntax).unwrap().to_owned() |
129 | } | 104 | } |
130 | 105 | ||