@@ -37,110 +37,39 @@ pub trait FromTree: Sized {
37
37
fn from_tree ( top : & Tree ) -> Result < Self , Error > ;
38
38
}
39
39
40
- impl < ' a > Tree < ' a > {
41
- /// Parse an expression with round brackets
42
- pub fn from_slice ( sl : & ' a str ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
43
- // Parsing TapTree or just miniscript
44
- Self :: from_slice_helper_round ( sl, 0u32 )
45
- }
46
-
47
- fn from_slice_helper_round ( mut sl : & ' a str , depth : u32 ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
48
- if depth >= MAX_RECURSION_DEPTH {
49
- return Err ( Error :: MaxRecursiveDepthExceeded ) ;
50
- }
51
- enum Found {
52
- Nothing ,
53
- Lparen ( usize ) ,
54
- Comma ( usize ) ,
55
- Rparen ( usize ) ,
56
- }
40
+ enum Found {
41
+ Nothing ,
42
+ LBracket ( usize ) , // Either a left ( or {
43
+ Comma ( usize ) ,
44
+ RBracket ( usize ) , // Either a right ) or }
45
+ }
57
46
58
- let mut found = Found :: Nothing ;
47
+ fn next_expr ( sl : & str , delim : char ) -> Found {
48
+ let mut found = Found :: Nothing ;
49
+ if delim == '(' {
59
50
for ( n, ch) in sl. char_indices ( ) {
60
51
match ch {
61
52
'(' => {
62
- found = Found :: Lparen ( n) ;
53
+ found = Found :: LBracket ( n) ;
63
54
break ;
64
55
}
65
56
',' => {
66
57
found = Found :: Comma ( n) ;
67
58
break ;
68
59
}
69
60
')' => {
70
- found = Found :: Rparen ( n) ;
61
+ found = Found :: RBracket ( n) ;
71
62
break ;
72
63
}
73
64
_ => { }
74
65
}
75
66
}
76
-
77
- match found {
78
- // String-ending terminal
79
- Found :: Nothing => Ok ( (
80
- Tree {
81
- name : & sl[ ..] ,
82
- args : vec ! [ ] ,
83
- } ,
84
- "" ,
85
- ) ) ,
86
- // Terminal
87
- Found :: Comma ( n) | Found :: Rparen ( n) => Ok ( (
88
- Tree {
89
- name : & sl[ ..n] ,
90
- args : vec ! [ ] ,
91
- } ,
92
- & sl[ n..] ,
93
- ) ) ,
94
- // Function call
95
- Found :: Lparen ( n) => {
96
- let mut ret = Tree {
97
- name : & sl[ ..n] ,
98
- args : vec ! [ ] ,
99
- } ;
100
-
101
- sl = & sl[ n + 1 ..] ;
102
- loop {
103
- let ( arg, new_sl) = Tree :: from_slice_helper_round ( sl, depth + 1 ) ?;
104
- ret. args . push ( arg) ;
105
-
106
- if new_sl. is_empty ( ) {
107
- return Err ( Error :: ExpectedChar ( ')' ) ) ;
108
- }
109
-
110
- sl = & new_sl[ 1 ..] ;
111
- match new_sl. as_bytes ( ) [ 0 ] {
112
- b',' => { }
113
- b')' => break ,
114
- _ => return Err ( Error :: ExpectedChar ( ',' ) ) ,
115
- }
116
- }
117
- Ok ( ( ret, sl) )
118
- }
119
- }
120
- }
121
-
122
- // Helper function to parse expressions with curly braces
123
- pub ( crate ) fn from_slice_helper_curly (
124
- mut sl : & ' a str ,
125
- depth : u32 ,
126
- ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
127
- // contain the context of brackets
128
- if depth >= MAX_RECURSION_DEPTH {
129
- return Err ( Error :: MaxRecursiveDepthExceeded ) ;
130
- }
131
- enum Found {
132
- Nothing ,
133
- Lbrace ( usize ) ,
134
- Comma ( usize ) ,
135
- Rbrace ( usize ) ,
136
- }
137
-
138
- let mut found = Found :: Nothing ;
67
+ } else if delim == '{' {
139
68
let mut new_count = 0 ;
140
69
for ( n, ch) in sl. char_indices ( ) {
141
70
match ch {
142
71
'{' => {
143
- found = Found :: Lbrace ( n) ;
72
+ found = Found :: LBracket ( n) ;
144
73
break ;
145
74
}
146
75
'(' => {
@@ -156,14 +85,44 @@ impl<'a> Tree<'a> {
156
85
new_count -= 1 ;
157
86
}
158
87
'}' => {
159
- found = Found :: Rbrace ( n) ;
88
+ found = Found :: RBracket ( n) ;
160
89
break ;
161
90
}
162
91
_ => { }
163
92
}
164
93
}
94
+ } else {
95
+ unreachable ! ( "Internal: delimiters in parsing must be '(' or '{'" ) ;
96
+ }
97
+ found
98
+ }
99
+
100
+ // Get the corresponding delim
101
+ fn closing_delim ( delim : char ) -> char {
102
+ match delim {
103
+ '(' => ')' ,
104
+ '{' => '}' ,
105
+ _ => unreachable ! ( "Unknown delimiter" ) ,
106
+ }
107
+ }
165
108
166
- match found {
109
+ impl < ' a > Tree < ' a > {
110
+ /// Parse an expression with round brackets
111
+ pub fn from_slice ( sl : & ' a str ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
112
+ // Parsing TapTree or just miniscript
113
+ Self :: from_slice_delim ( sl, 0u32 , '(' )
114
+ }
115
+
116
+ pub ( crate ) fn from_slice_delim (
117
+ mut sl : & ' a str ,
118
+ depth : u32 ,
119
+ delim : char ,
120
+ ) -> Result < ( Tree < ' a > , & ' a str ) , Error > {
121
+ if depth >= MAX_RECURSION_DEPTH {
122
+ return Err ( Error :: MaxRecursiveDepthExceeded ) ;
123
+ }
124
+
125
+ match next_expr ( sl, delim) {
167
126
// String-ending terminal
168
127
Found :: Nothing => Ok ( (
169
128
Tree {
@@ -173,34 +132,39 @@ impl<'a> Tree<'a> {
173
132
"" ,
174
133
) ) ,
175
134
// Terminal
176
- Found :: Comma ( n) | Found :: Rbrace ( n) => Ok ( (
135
+ Found :: Comma ( n) | Found :: RBracket ( n) => Ok ( (
177
136
Tree {
178
137
name : & sl[ ..n] ,
179
138
args : vec ! [ ] ,
180
139
} ,
181
140
& sl[ n..] ,
182
141
) ) ,
183
142
// Function call
184
- Found :: Lbrace ( n) => {
143
+ Found :: LBracket ( n) => {
185
144
let mut ret = Tree {
186
- name : & sl[ ..n] , // Would be empty for left and right assignments
145
+ name : & sl[ ..n] ,
187
146
args : vec ! [ ] ,
188
147
} ;
189
148
190
149
sl = & sl[ n + 1 ..] ;
191
150
loop {
192
- let ( arg, new_sl) = Tree :: from_slice_helper_curly ( sl, depth + 1 ) ?;
151
+ let ( arg, new_sl) = Tree :: from_slice_delim ( sl, depth + 1 , delim ) ?;
193
152
ret. args . push ( arg) ;
194
153
195
154
if new_sl. is_empty ( ) {
196
- return Err ( Error :: ExpectedChar ( '}' ) ) ;
155
+ return Err ( Error :: ExpectedChar ( closing_delim ( delim ) ) ) ;
197
156
}
198
157
199
158
sl = & new_sl[ 1 ..] ;
200
159
match new_sl. as_bytes ( ) [ 0 ] {
201
160
b',' => { }
202
- b'}' => break ,
203
- _ => return Err ( Error :: ExpectedChar ( ',' ) ) ,
161
+ last_byte => {
162
+ if last_byte == closing_delim ( delim) as u8 {
163
+ break ;
164
+ } else {
165
+ return Err ( Error :: ExpectedChar ( closing_delim ( delim) ) ) ;
166
+ }
167
+ }
204
168
}
205
169
}
206
170
Ok ( ( ret, sl) )
0 commit comments