@@ -54,63 +54,83 @@ impl Node {
54
54
}
55
55
}
56
56
57
- pub fn create_cursor ( & self , text_offset : TextIndex ) -> Cursor {
57
+ /// Creates a [`Cursor`] that starts at the current node as the root and a given initial `text_offset`.
58
+ pub fn cursor_with_offset ( & self , text_offset : TextIndex ) -> Cursor {
58
59
Cursor :: new ( self . clone ( ) , text_offset)
59
60
}
60
61
62
+ /// Reconstructs the original source code from the parse tree.
63
+ pub fn unparse ( self ) -> String {
64
+ match self {
65
+ Self :: Rule ( rule) => rule. unparse ( ) ,
66
+ Self :: Token ( token) => token. text . clone ( ) ,
67
+ }
68
+ }
69
+
61
70
pub fn as_rule ( & self ) -> Option < & Rc < RuleNode > > {
62
71
match self {
63
72
Self :: Rule ( node) => Some ( node) ,
64
73
_ => None ,
65
74
}
66
75
}
67
76
77
+ pub fn into_rule ( self ) -> Option < Rc < RuleNode > > {
78
+ match self {
79
+ Self :: Rule ( node) => Some ( node) ,
80
+ _ => None ,
81
+ }
82
+ }
83
+
68
84
pub fn as_token ( & self ) -> Option < & Rc < TokenNode > > {
69
85
match self {
70
86
Self :: Token ( node) => Some ( node) ,
71
87
_ => None ,
72
88
}
73
89
}
74
90
75
- pub fn as_token_with_kind ( & self , kinds : & [ TokenKind ] ) -> Option < & Rc < TokenNode > > {
76
- if let Node :: Token ( token_node) = self {
77
- if kinds. contains ( & token_node. kind ) {
78
- return Some ( token_node) ;
79
- }
91
+ pub fn into_token ( self ) -> Option < Rc < TokenNode > > {
92
+ match self {
93
+ Self :: Token ( node) => Some ( node) ,
94
+ _ => None ,
80
95
}
81
- return None ;
82
96
}
83
97
84
- pub fn as_token_matching < F : Fn ( & Rc < TokenNode > ) -> bool > (
85
- & self ,
86
- predicate : F ,
87
- ) -> Option < & Rc < TokenNode > > {
88
- if let Node :: Token ( token_node) = self {
89
- if predicate ( & token_node) {
90
- return Some ( token_node) ;
91
- }
92
- }
93
- return None ;
98
+ pub fn as_token_with_kind ( & self , kinds : & [ TokenKind ] ) -> Option < & Rc < TokenNode > > {
99
+ self . as_token ( ) . filter ( |token| kinds. contains ( & token. kind ) )
94
100
}
95
101
96
102
pub fn as_rule_with_kind ( & self , kinds : & [ RuleKind ] ) -> Option < & Rc < RuleNode > > {
97
- if let Node :: Rule ( rule_node) = self {
98
- if kinds. contains ( & rule_node. kind ) {
99
- return Some ( rule_node) ;
100
- }
101
- }
102
- return None ;
103
+ self . as_rule ( ) . filter ( |rule| kinds. contains ( & rule. kind ) )
103
104
}
105
+ }
104
106
105
- pub fn as_rule_matching < F : Fn ( & Rc < RuleNode > ) -> bool > (
106
- & self ,
107
- predicate : F ,
108
- ) -> Option < & Rc < RuleNode > > {
109
- if let Node :: Rule ( rule_node) = self {
110
- if predicate ( & rule_node) {
111
- return Some ( rule_node) ;
112
- }
113
- }
114
- return None ;
107
+ impl From < Rc < RuleNode > > for Node {
108
+ fn from ( node : Rc < RuleNode > ) -> Self {
109
+ Self :: Rule ( node)
110
+ }
111
+ }
112
+
113
+ impl From < Rc < TokenNode > > for Node {
114
+ fn from ( node : Rc < TokenNode > ) -> Self {
115
+ Self :: Token ( node)
116
+ }
117
+ }
118
+
119
+ impl RuleNode {
120
+ /// Creates a [`Cursor`] that starts at the current node as the root and a given initial `text_offset`.
121
+ pub fn cursor_with_offset ( self : Rc < Self > , text_offset : TextIndex ) -> Cursor {
122
+ Cursor :: new ( Node :: Rule ( self ) , text_offset)
123
+ }
124
+
125
+ /// Reconstructs the original source code from the parse tree.
126
+ pub fn unparse ( self : Rc < Self > ) -> String {
127
+ let acc = String :: with_capacity ( self . text_len . utf8 ) ;
128
+
129
+ self . cursor_with_offset ( TextIndex :: ZERO )
130
+ . filter_map ( Node :: into_token)
131
+ . fold ( acc, |mut acc, token| {
132
+ acc. push_str ( & token. text ) ;
133
+ acc
134
+ } )
115
135
}
116
136
}
0 commit comments