aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/subtree_parser.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-04-08 15:18:57 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-04-08 15:18:57 +0100
commitac6ab0758731d0555fbf1b1a918abd3e12c8169d (patch)
tree05f568cbd925dbbd578f9414fd9e4ea3634b68e4 /crates/ra_mbe/src/subtree_parser.rs
parent1ca7a744eb512e6b900988cba871dcd3d90d447f (diff)
parent8ed710457875e6f580a0ddf6ab29c6b10d389a41 (diff)
Merge #1105
1105: [WIP] Implement ra_mbe meta variables support r=matklad a=edwin0cheng This PR implements the following meta variable support in `ra_mba` crate (issue #720): - [x] `path` - [ ] `expr` - [ ] `ty` - [ ] `pat` - [ ] `stmt` - [ ] `block` - [ ] `meta` - [ ] `item` *Implementation Details* In the macro expanding lhs phase, if we see a meta variable type, we try to create a `tt:TokenTree` from the remaining input. And then we use a special set of `ra_parser` to parse it to `SyntaxNode`. Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/ra_mbe/src/subtree_parser.rs')
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs
new file mode 100644
index 000000000..ce39a40bb
--- /dev/null
+++ b/crates/ra_mbe/src/subtree_parser.rs
@@ -0,0 +1,61 @@
1use crate::subtree_source::SubtreeTokenSource;
2
3use ra_parser::{TokenSource, TreeSink};
4use ra_syntax::{SyntaxKind};
5
6struct OffsetTokenSink {
7 token_pos: usize,
8}
9
10impl TreeSink for OffsetTokenSink {
11 fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) {
12 self.token_pos += n_tokens as usize;
13 }
14 fn start_node(&mut self, _kind: SyntaxKind) {}
15 fn finish_node(&mut self) {}
16 fn error(&mut self, _error: ra_parser::ParseError) {}
17}
18
19pub(crate) struct Parser<'a> {
20 subtree: &'a tt::Subtree,
21 cur_pos: &'a mut usize,
22}
23
24impl<'a> Parser<'a> {
25 pub fn new(cur_pos: &'a mut usize, subtree: &'a tt::Subtree) -> Parser<'a> {
26 Parser { cur_pos, subtree }
27 }
28
29 pub fn parse_path(self) -> Option<tt::TokenTree> {
30 self.parse(ra_parser::parse_path)
31 }
32
33 fn parse<F>(self, f: F) -> Option<tt::TokenTree>
34 where
35 F: FnOnce(&dyn TokenSource, &mut dyn TreeSink),
36 {
37 let mut src = SubtreeTokenSource::new(self.subtree);
38 src.start_from_nth(*self.cur_pos);
39 let mut sink = OffsetTokenSink { token_pos: 0 };
40
41 f(&src, &mut sink);
42
43 self.finish(sink.token_pos, &mut src)
44 }
45
46 fn finish(self, parsed_token: usize, src: &mut SubtreeTokenSource) -> Option<tt::TokenTree> {
47 let res = src.bump_n(parsed_token);
48 *self.cur_pos += res.len();
49
50 let res: Vec<_> = res.into_iter().cloned().collect();
51
52 match res.len() {
53 0 => None,
54 1 => Some(res[0].clone()),
55 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
56 delimiter: tt::Delimiter::None,
57 token_trees: res,
58 })),
59 }
60 }
61}