diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-08 15:18:57 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-08 15:18:57 +0100 |
commit | ac6ab0758731d0555fbf1b1a918abd3e12c8169d (patch) | |
tree | 05f568cbd925dbbd578f9414fd9e4ea3634b68e4 /crates/ra_mbe/src/subtree_parser.rs | |
parent | 1ca7a744eb512e6b900988cba871dcd3d90d447f (diff) | |
parent | 8ed710457875e6f580a0ddf6ab29c6b10d389a41 (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.rs | 61 |
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 @@ | |||
1 | use crate::subtree_source::SubtreeTokenSource; | ||
2 | |||
3 | use ra_parser::{TokenSource, TreeSink}; | ||
4 | use ra_syntax::{SyntaxKind}; | ||
5 | |||
6 | struct OffsetTokenSink { | ||
7 | token_pos: usize, | ||
8 | } | ||
9 | |||
10 | impl 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 | |||
19 | pub(crate) struct Parser<'a> { | ||
20 | subtree: &'a tt::Subtree, | ||
21 | cur_pos: &'a mut usize, | ||
22 | } | ||
23 | |||
24 | impl<'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 | } | ||