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.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}