aboutsummaryrefslogtreecommitdiff
path: root/src/yellow
diff options
context:
space:
mode:
Diffstat (limited to 'src/yellow')
-rw-r--r--src/yellow/green.rs194
-rw-r--r--src/yellow/mod.rs42
-rw-r--r--src/yellow/red.rs87
-rw-r--r--src/yellow/syntax.rs132
4 files changed, 455 insertions, 0 deletions
diff --git a/src/yellow/green.rs b/src/yellow/green.rs
new file mode 100644
index 000000000..ede23b719
--- /dev/null
+++ b/src/yellow/green.rs
@@ -0,0 +1,194 @@
1use std::sync::Arc;
2use text_unit::TextUnit;
3use SyntaxKind;
4
5type TokenText = String;
6
7#[derive(Debug)]
8pub(crate) struct GreenNode {
9 kind: SyntaxKind,
10 data: GreenNodeData,
11}
12
13impl GreenNode {
14 pub(crate) fn new_leaf(kind: SyntaxKind, text: TokenText) -> GreenNode {
15 GreenNode {
16 kind,
17 data: GreenNodeData::Leaf(GreenLeaf { text }),
18 }
19 }
20
21 pub(crate) fn new_branch(
22 kind: SyntaxKind,
23 ) -> GreenNode {
24 let branch = GreenBranch {
25 text_len: 0.into(),
26 leading_trivia: Trivias::default(),
27 children: Vec::new(),
28 };
29 GreenNode {
30 kind,
31 data: GreenNodeData::Branch(branch),
32 }
33 }
34
35 pub(crate) fn push_trivia(&mut self, kind: SyntaxKind, text: TokenText) {
36 let branch = match &mut self.data {
37 GreenNodeData::Branch(branch) => branch,
38 _ => panic!()
39 };
40 branch.text_len += TextUnit::of_str(&text);
41 let leading = &mut branch.leading_trivia;
42 branch.children.last_mut().map(|(_, t)| t).unwrap_or(leading)
43 .push(Arc::new(GreenTrivia { kind, text }));
44 }
45
46 pub(crate) fn push_child(&mut self, node: Arc<GreenNode>) {
47 let branch = match &mut self.data {
48 GreenNodeData::Branch(branch) => branch,
49 _ => panic!()
50 };
51 branch.text_len += node.text_len();
52 branch.children.push((node, Trivias::default()));
53 }
54
55 pub(crate) fn kind(&self) -> SyntaxKind {
56 self.kind
57 }
58
59 pub(crate) fn text_len(&self) -> TextUnit {
60 match &self.data {
61 GreenNodeData::Leaf(l) => l.text_len(),
62 GreenNodeData::Branch(b) => b.text_len(),
63 }
64 }
65
66 pub(crate) fn text(&self) -> String {
67 let mut buff = String::new();
68 go(self, &mut buff);
69 return buff;
70 fn go(node: &GreenNode, buff: &mut String) {
71 match &node.data {
72 GreenNodeData::Leaf(l) => buff.push_str(&l.text),
73 GreenNodeData::Branch(branch) => {
74 add_trivia(&branch.leading_trivia, buff);
75 branch.children.iter().for_each(|(child, trivias)| {
76 go(child, buff);
77 add_trivia(trivias, buff);
78 })
79 }
80 }
81 }
82
83 fn add_trivia(trivias: &Trivias, buff: &mut String) {
84 trivias.iter().for_each(|t| buff.push_str(&t.text))
85 }
86 }
87
88 pub(crate) fn n_children(&self) -> usize {
89 match &self.data {
90 GreenNodeData::Leaf(_) => 0,
91 GreenNodeData::Branch(branch) => branch.children.len(),
92 }
93 }
94
95 pub(crate) fn nth_child(&self, idx: usize) -> &Arc<GreenNode> {
96 match &self.data {
97 GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"),
98 GreenNodeData::Branch(branch) => &branch.children[idx].0,
99 }
100 }
101
102 pub(crate) fn nth_trivias(&self, idx: usize) -> &Trivias {
103 match &self.data {
104 GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"),
105 GreenNodeData::Branch(branch) => if idx == 0 {
106 &branch.leading_trivia
107 } else {
108 &branch.children[idx - 1].1
109 },
110 }
111 }
112
113 pub(crate) fn is_leaf(&self) -> bool {
114 match self.data {
115 GreenNodeData::Leaf(_) => true,
116 GreenNodeData::Branch(_) => false
117 }
118 }
119
120 pub(crate) fn leaf_text(&self) -> &str {
121 match &self.data {
122 GreenNodeData::Leaf(l) => l.text.as_str(),
123 GreenNodeData::Branch(_) => panic!("not a leaf")
124 }
125 }
126}
127
128#[derive(Debug)]
129enum GreenNodeData {
130 Leaf(GreenLeaf),
131 Branch(GreenBranch),
132}
133
134#[derive(Debug)]
135struct GreenLeaf {
136 text: TokenText
137}
138
139#[derive(Debug)]
140struct GreenBranch {
141 text_len: TextUnit,
142 leading_trivia: Trivias,
143 children: Vec<(Arc<GreenNode>, Trivias)>,
144}
145
146#[derive(Debug)]
147pub(crate) struct GreenTrivia {
148 pub(crate) kind: SyntaxKind,
149 pub(crate) text: TokenText,
150}
151
152type Trivias = Vec<Arc<GreenTrivia>>;
153
154
155pub(crate) trait TextLen {
156 fn text_len(&self) -> TextUnit;
157}
158
159impl TextLen for GreenTrivia {
160 fn text_len(&self) -> TextUnit {
161 TextUnit::of_str(&self.text)
162 }
163}
164
165impl<T: TextLen> TextLen for Arc<T> {
166 fn text_len(&self) -> TextUnit {
167 let this: &T = self;
168 this.text_len()
169 }
170}
171
172impl TextLen for GreenNode {
173 fn text_len(&self) -> TextUnit {
174 self.text_len()
175 }
176}
177
178impl TextLen for GreenLeaf {
179 fn text_len(&self) -> TextUnit {
180 TextUnit::of_str(&self.text)
181 }
182}
183
184impl TextLen for GreenBranch {
185 fn text_len(&self) -> TextUnit {
186 self.text_len
187 }
188}
189
190impl<T: TextLen> TextLen for [T] {
191 fn text_len(&self) -> TextUnit {
192 self.iter().map(TextLen::text_len).sum()
193 }
194}
diff --git a/src/yellow/mod.rs b/src/yellow/mod.rs
new file mode 100644
index 000000000..236328a7f
--- /dev/null
+++ b/src/yellow/mod.rs
@@ -0,0 +1,42 @@
1mod green;
2mod red;
3mod syntax;
4
5use std::{
6 sync::{Arc, Weak},
7 ops::Deref,
8 mem
9};
10pub(crate) use self::{
11 green::{GreenNode, TextLen},
12 red::RedNode,
13 syntax::SError,
14};
15pub use self::syntax::SyntaxNode;
16
17// This could be just `*const T`, but we use `Weak` for additional checks
18#[derive(Debug)]
19pub(crate) struct Ptr<T>(Weak<T>);
20
21impl<T> Clone for Ptr<T> {
22 fn clone(&self) -> Self {
23 Ptr(self.0.clone())
24 }
25}
26
27impl<T> Ptr<T> {
28 fn clone(self_: &Ptr<T>) -> Ptr<T> {
29 Ptr(Weak::clone(&self_.0))
30 }
31
32 fn new(arc: &Arc<T>) -> Ptr<T> {
33 Ptr(Arc::downgrade(arc))
34 }
35
36 unsafe fn get(&self) -> &T {
37 let t = self.0.upgrade()
38 .expect("caller must guarantee that Ptr is not null");
39 let t: &T = &*t;
40 mem::transmute(t)
41 }
42}
diff --git a/src/yellow/red.rs b/src/yellow/red.rs
new file mode 100644
index 000000000..feba99faa
--- /dev/null
+++ b/src/yellow/red.rs
@@ -0,0 +1,87 @@
1use std::sync::{Arc, Weak, RwLock};
2use {
3 TextUnit, SyntaxKind, TextRange,
4 yellow::{Ptr, GreenNode, TextLen}
5};
6
7#[derive(Debug)]
8pub(crate) struct RedNode {
9 green: Arc<GreenNode>,
10 parent: Option<ParentData>,
11 children: RwLock<Vec<Option<Arc<RedNode>>>>,
12}
13
14#[derive(Debug)]
15struct ParentData {
16 parent: Ptr<RedNode>,
17 start_offset: TextUnit,
18 index_in_parent: usize,
19}
20
21impl RedNode {
22 pub fn new_root(
23 green: Arc<GreenNode>,
24 ) -> RedNode {
25 RedNode::new(green, None)
26 }
27
28 fn new_child(
29 green: Arc<GreenNode>,
30 parent: Ptr<RedNode>,
31 start_offset: TextUnit,
32 index_in_parent: usize
33 ) -> RedNode {
34 let parent_data = ParentData {
35 parent,
36 start_offset,
37 index_in_parent
38 };
39 RedNode::new(green, Some(parent_data))
40 }
41
42 fn new(
43 green: Arc<GreenNode>,
44 parent: Option<ParentData>,
45 ) -> RedNode {
46 let children = vec![None; green.n_children()];
47 RedNode { green, parent, children: RwLock::new(children) }
48 }
49
50 pub(crate) fn green(&self) -> &GreenNode {
51 &self.green
52 }
53
54 pub(crate) fn start_offset(&self) -> TextUnit {
55 match &self.parent {
56 None => 0.into(),
57 Some(p) => p.start_offset,
58 }
59 }
60
61 pub(crate) fn n_children(&self) -> usize {
62 self.green.n_children()
63 }
64
65 pub(crate) fn nth_child(&self, me: Ptr<RedNode>, n: usize) -> Arc<RedNode> {
66 match &self.children.read().unwrap()[n] {
67 Some(child) => return child.clone(),
68 None => (),
69 }
70 let mut children = self.children.write().unwrap();
71 if children[n].is_none() {
72 let start_offset = {
73 let mut acc = self.start_offset();
74 for i in 0..n {
75 acc += self.green.nth_trivias(i).text_len();
76 acc += self.green.nth_child(i).text_len();
77 }
78 acc += self.green.nth_trivias(n).text_len();
79 acc
80 };
81 let green = self.green.nth_child(n).clone();
82 let child = RedNode::new_child(green, me, start_offset, n);
83 children[n] = Some(Arc::new(child))
84 }
85 children[n].as_ref().unwrap().clone()
86 }
87}
diff --git a/src/yellow/syntax.rs b/src/yellow/syntax.rs
new file mode 100644
index 000000000..0c9ffeb14
--- /dev/null
+++ b/src/yellow/syntax.rs
@@ -0,0 +1,132 @@
1use std::{
2 fmt,
3 sync::Arc,
4};
5
6use {
7 TextRange, TextUnit, SyntaxKind,
8 yellow::{Ptr, RedNode, GreenNode, TextLen},
9};
10use yellow::green::GreenTrivia;
11
12#[derive(Clone)]
13pub struct SyntaxNode {
14 pub(crate) root: SyntaxRoot,
15 red: Ptr<RedNode>,
16 trivia_pos: Option<(usize, usize)>,
17}
18
19#[derive(Clone)]
20pub struct SyntaxRoot {
21 red: Arc<RedNode>,
22 pub(crate) errors: Arc<Vec<SError>>,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
26pub(crate) struct SError {
27 pub(crate) message: String,
28 pub(crate) offset: TextUnit,
29}
30
31impl SyntaxNode {
32 pub(crate) fn new(root: Arc<GreenNode>, errors: Vec<SError>) -> SyntaxNode {
33 let root = Arc::new(RedNode::new_root(root));
34 let red = Ptr::new(&root);
35 let root = SyntaxRoot { red: root, errors: Arc::new(errors) };
36 SyntaxNode { root, red, trivia_pos: None }
37 }
38
39 pub fn kind(&self) -> SyntaxKind {
40 let green = self.red().green();
41 match self.trivia_pos {
42 None => green.kind(),
43 Some((i, j)) => green.nth_trivias(i)[j].kind
44 }
45 }
46
47 pub fn range(&self) -> TextRange {
48 let red = self.red();
49 let green = red.green();
50 match self.trivia_pos {
51 None => TextRange::offset_len(red.start_offset(), red.green().text_len()),
52 Some((i, j)) => {
53 let trivias = green.nth_trivias(i);
54 let offset = if i == 0 {
55 red.start_offset()
56 } else {
57 let prev_child = red.nth_child(Ptr::clone(&self.red), i - 1);
58 let mut offset = prev_child.start_offset() + prev_child.green().text_len();
59 for k in 0..j {
60 offset += &trivias[k].text_len();
61 }
62 offset
63 };
64 TextRange::offset_len(offset, trivias[j].text_len())
65 }
66 }
67 }
68
69 pub fn text(&self) -> String {
70 let green = self.red().green();
71 match self.trivia_pos {
72 None => green.text(),
73 Some((i, j)) => green.nth_trivias(i)[j].text.clone()
74 }
75 }
76
77 pub fn children(&self) -> Vec<SyntaxNode> {
78 let mut res = Vec::new();
79 let red = self.red();
80 let green = red.green();
81 if green.is_leaf() || self.trivia_pos.is_some() {
82 return Vec::new();
83 }
84 for (j, _) in green.nth_trivias(0).iter().enumerate() {
85 res.push(SyntaxNode {
86 root: self.root.clone(),
87 red: Ptr::clone(&self.red),
88 trivia_pos: Some((0, j)),
89 })
90 }
91
92 let n_children = red.n_children();
93 for i in 0..n_children {
94 res.push(SyntaxNode {
95 root: self.root.clone(),
96 red: Ptr::new(&red.nth_child(Ptr::clone(&self.red), i)),
97 trivia_pos: None,
98 });
99 for (j, _) in green.nth_trivias(i + 1).iter().enumerate() {
100 res.push(SyntaxNode {
101 root: self.root.clone(),
102 red: self.red.clone(),
103 trivia_pos: Some((i + 1, j)),
104 })
105 }
106 }
107 res
108 }
109
110 fn red(&self) -> &RedNode {
111 // Safe b/c root ptr keeps red alive
112 unsafe { self.red.get() }
113 }
114}
115
116impl fmt::Debug for SyntaxNode {
117 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
118 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
119 if has_short_text(self.kind()) {
120 write!(fmt, " \"{}\"", self.text())?;
121 }
122 Ok(())
123 }
124}
125
126fn has_short_text(kind: SyntaxKind) -> bool {
127 use syntax_kinds::*;
128 match kind {
129 IDENT | LIFETIME => true,
130 _ => false,
131 }
132}