aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/subtree_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/subtree_parser.rs')
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs59
1 files changed, 59 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..48eee6fa7
--- /dev/null
+++ b/crates/ra_mbe/src/subtree_parser.rs
@@ -0,0 +1,59 @@
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 pos: &'a mut usize,
22}
23
24impl<'a> Parser<'a> {
25 pub fn new(pos: &'a mut usize, subtree: &'a tt::Subtree) -> Parser<'a> {
26 Parser { 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.advance(*self.pos, true);
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, self.pos);
48 let res: Vec<_> = res.into_iter().cloned().collect();
49
50 match res.len() {
51 0 => None,
52 1 => Some(res[0].clone()),
53 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
54 delimiter: tt::Delimiter::None,
55 token_trees: res,
56 })),
57 }
58 }
59}