diff options
author | Aleksey Kladov <[email protected]> | 2017-12-22 13:28:04 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2017-12-22 13:28:04 +0000 |
commit | 6ff019c25f027be1bf2896ce82659dc8d99515f8 (patch) | |
tree | d1c256805acb5e487d556f4b3a281470a25b8414 | |
parent | b878f3b636365aa9af327fea1aebf97d34cc87dd (diff) |
Add minimal syntax tree implementation
-rw-r--r-- | minirust.rs | 68 | ||||
-rw-r--r-- | rfc.md | 22 |
2 files changed, 88 insertions, 2 deletions
diff --git a/minirust.rs b/minirust.rs new file mode 100644 index 000000000..d92c03bea --- /dev/null +++ b/minirust.rs | |||
@@ -0,0 +1,68 @@ | |||
1 | pub struct NodeKind(u16); | ||
2 | |||
3 | pub struct File { | ||
4 | text: String, | ||
5 | nodes: Vec<NodeData>, | ||
6 | } | ||
7 | |||
8 | struct NodeData { | ||
9 | kind: NodeKind, | ||
10 | range: (u32, u32), | ||
11 | parent: Option<u32>, | ||
12 | first_child: Option<u32>, | ||
13 | next_sibling: Option<u32>, | ||
14 | } | ||
15 | |||
16 | #[derive(Clone, Copy)] | ||
17 | pub struct Node<'f> { | ||
18 | file: &'f File, | ||
19 | idx: u32, | ||
20 | } | ||
21 | |||
22 | pub struct Children<'f> { | ||
23 | next: Option<Node<'f>>, | ||
24 | } | ||
25 | |||
26 | impl File { | ||
27 | pub fn root<'f>(&'f self) -> Node<'f> { | ||
28 | assert!(!self.nodes.is_empty()); | ||
29 | Node { file: self, idx: 0 } | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl<'f> Node<'f> { | ||
34 | pub fn kind(&self) -> NodeKind { | ||
35 | self.data().kind | ||
36 | } | ||
37 | |||
38 | pub fn text(&self) -> &'f str { | ||
39 | let (start, end) = self.data().range; | ||
40 | &self.file.text[start as usize..end as usize] | ||
41 | } | ||
42 | |||
43 | pub fn parent(&self) -> Option<Node<'f>> { | ||
44 | self.as_node(self.data().parent) | ||
45 | } | ||
46 | |||
47 | pub fn children(&self) -> Children<'f> { | ||
48 | Children { next: self.as_node(self.data().first_child) } | ||
49 | } | ||
50 | |||
51 | fn data(&self) -> &'f NodeData { | ||
52 | &self.file.nodes[self.idx as usize] | ||
53 | } | ||
54 | |||
55 | fn as_node(&self, idx: Option<u32>) -> Option<Node<'f>> { | ||
56 | idx.map(|idx| Node { file: self.file, idx }) | ||
57 | } | ||
58 | } | ||
59 | |||
60 | impl<'f> Iterator for Children<'f> { | ||
61 | type Item = Node<'f>; | ||
62 | |||
63 | fn next(&mut self) -> Option<Node<'f>> { | ||
64 | let next = self.next; | ||
65 | self.next = next.and_then(|node| node.as_node(node.data().next_sibling)); | ||
66 | next | ||
67 | } | ||
68 | } | ||
@@ -80,7 +80,10 @@ simpler ones. | |||
80 | 80 | ||
81 | In contrast, for IDEs it is crucial to have a lossless view of the | 81 | In contrast, for IDEs it is crucial to have a lossless view of the |
82 | source code because, for example, it's important to preserve comments | 82 | source code because, for example, it's important to preserve comments |
83 | during refactorings. | 83 | during refactorings. Ideally, IDEs should be able to incrementally |
84 | relex and reparse the file as the user types, because syntax tree is | ||
85 | necessary to correctly handle certain code-editing actions like | ||
86 | autoindentation or joining lines. | ||
84 | 87 | ||
85 | Currently rustc uses the AST approach, which preserves the source code | 88 | Currently rustc uses the AST approach, which preserves the source code |
86 | information to some extent by storing spans in the AST. | 89 | information to some extent by storing spans in the AST. |
@@ -98,7 +101,7 @@ Not applicable. | |||
98 | 101 | ||
99 | This section proposes a new syntax tree data structure, which should | 102 | This section proposes a new syntax tree data structure, which should |
100 | be suitable for both compiler and IDE. It is heavily inspired by [PSI] | 103 | be suitable for both compiler and IDE. It is heavily inspired by [PSI] |
101 | data structure which used in [IntelliJ] based IDEs and in the Kotlin | 104 | data structure which used in [IntelliJ] based IDEs and in the [Kotlin] |
102 | compiler. | 105 | compiler. |
103 | 106 | ||
104 | 107 | ||
@@ -107,6 +110,21 @@ compiler. | |||
107 | [Kotlin]: https://kotlinlang.org/ | 110 | [Kotlin]: https://kotlinlang.org/ |
108 | 111 | ||
109 | 112 | ||
113 | The main idea is to store the minimal amount of information in the | ||
114 | tree itself, and instead lean heavily on the source code string for | ||
115 | the actual data about identifier names, constant values etc. | ||
116 | |||
117 | All nodes in the tree are of the same type and store a constant for | ||
118 | the syntactic category of the element and a range in the source code. | ||
119 | |||
120 | Here is a minimal implementation of this data structure: | ||
121 | |||
122 | |||
123 | ```Rust | ||
124 | ``` | ||
125 | |||
126 | |||
127 | |||
110 | # Drawbacks | 128 | # Drawbacks |
111 | [drawbacks]: #drawbacks | 129 | [drawbacks]: #drawbacks |
112 | 130 | ||