diff options
Diffstat (limited to 'src/tree')
-rw-r--r-- | src/tree/mod.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/tree/mod.rs b/src/tree/mod.rs new file mode 100644 index 000000000..2ac25e795 --- /dev/null +++ b/src/tree/mod.rs | |||
@@ -0,0 +1,101 @@ | |||
1 | use text::{TextUnit, TextRange}; | ||
2 | use syntax_kinds::syntax_info; | ||
3 | |||
4 | use std::fmt; | ||
5 | |||
6 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
7 | pub struct SyntaxKind(pub(crate) u32); | ||
8 | |||
9 | impl SyntaxKind { | ||
10 | fn info(self) -> &'static SyntaxInfo { | ||
11 | syntax_info(self) | ||
12 | } | ||
13 | } | ||
14 | |||
15 | impl fmt::Debug for SyntaxKind { | ||
16 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
17 | let name = self.info().name; | ||
18 | f.write_str(name) | ||
19 | } | ||
20 | } | ||
21 | |||
22 | |||
23 | pub(crate) struct SyntaxInfo { | ||
24 | pub name: &'static str, | ||
25 | } | ||
26 | |||
27 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
28 | pub struct Token { | ||
29 | pub kind: SyntaxKind, | ||
30 | pub len: TextUnit, | ||
31 | } | ||
32 | |||
33 | pub struct File { | ||
34 | text: String, | ||
35 | nodes: Vec<NodeData>, | ||
36 | } | ||
37 | |||
38 | impl File { | ||
39 | pub fn root<'f>(&'f self) -> Node<'f> { | ||
40 | assert!(!self.nodes.is_empty()); | ||
41 | Node { file: self, idx: NodeIdx(0) } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | #[derive(Clone, Copy)] | ||
46 | pub struct Node<'f> { | ||
47 | file: &'f File, | ||
48 | idx: NodeIdx, | ||
49 | } | ||
50 | |||
51 | impl<'f> Node<'f> { | ||
52 | pub fn kind(&self) -> SyntaxKind { | ||
53 | self.data().kind | ||
54 | } | ||
55 | |||
56 | pub fn text(&self) -> &'f str { | ||
57 | let range = self.data().range; | ||
58 | &self.file.text.as_str()[range] | ||
59 | } | ||
60 | |||
61 | pub fn parent(&self) -> Option<Node<'f>> { | ||
62 | self.as_node(self.data().parent) | ||
63 | } | ||
64 | |||
65 | pub fn children(&self) -> Children<'f> { | ||
66 | Children { next: self.as_node(self.data().first_child) } | ||
67 | } | ||
68 | |||
69 | fn data(&self) -> &'f NodeData { | ||
70 | &self.file.nodes[self.idx.0 as usize] | ||
71 | } | ||
72 | |||
73 | fn as_node(&self, idx: Option<NodeIdx>) -> Option<Node<'f>> { | ||
74 | idx.map(|idx| Node { file: self.file, idx }) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | pub struct Children<'f> { | ||
79 | next: Option<Node<'f>>, | ||
80 | } | ||
81 | |||
82 | impl<'f> Iterator for Children<'f> { | ||
83 | type Item = Node<'f>; | ||
84 | |||
85 | fn next(&mut self) -> Option<Node<'f>> { | ||
86 | let next = self.next; | ||
87 | self.next = next.and_then(|node| node.as_node(node.data().next_sibling)); | ||
88 | next | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #[derive(Clone, Copy)] | ||
93 | struct NodeIdx(u32); | ||
94 | |||
95 | struct NodeData { | ||
96 | kind: SyntaxKind, | ||
97 | range: TextRange, | ||
98 | parent: Option<NodeIdx>, | ||
99 | first_child: Option<NodeIdx>, | ||
100 | next_sibling: Option<NodeIdx>, | ||
101 | } | ||