1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
//! # Bracket Parse
//!
//! A Utility for parsing Bracketed lists and sets of strings.
//!
//! It is a relatively lazy way of parsing items from a bracketed string,
//! 
//! "hello(peter,dave)" is easy for it to handle, as are nested brackets.
//!
//! The above will result in something like 
//!
//! >Branch[Leaf("hello"),Branch[Leaf("peter"),Leaf("dave")]]
//! 
//! This is not intended super extensible right now, 
//! though contributions are welcome.
//!
//! The list can also be constructed relatively simply by
//! using chained builder type methods
//!
//! ```
//! use bracket_parse::{Bracket,br};
//! use bracket_parse::Bracket::{Leaf,Branch};
//! use std::str::FromStr;
//!
//! let str1 = Bracket::from_str("hello(peter,dave)").unwrap();
//!
//! //Standard Build method
//! let basic1 = Branch(vec![Leaf("hello".to_string()),
//!                         Branch(vec![Leaf("peter".to_string()),
//!                                     Leaf("dave".to_string())])]);
//!
//! //Chaining Build method
//! let chain1 = br().sib_lf("hello")
//!                    .sib(br().sib_lf("peter").sib_lf("dave"));
//! 
//! assert_eq!(str1,basic1);
//! assert_eq!(str1,chain1);
//! ```
//!
//! It can also handle string input with escapes. Quotes are removed and the string item is
//! considered a single Leaf value;
//!
//! ```
//! use bracket_parse::{Bracket,br,lf};
//! use std::str::FromStr;
//! 
//! let bk = Bracket::from_str(r#""hello" 'matt"' "and \"friends\"""#).unwrap();
//! let chn = br().sib_lf("hello").sib_lf("matt\"").sib_lf("and \"friends\"");
//! assert_eq!(bk,chn);
//!
//! ```


use std::str::FromStr;
use std::fmt;
use std::fmt::Display;
use std::iter::IntoIterator;

pub mod tail;
pub use tail::{Tail};
use tail::EMPTY_BRACKET;

pub mod iter;
pub use iter::*;


#[derive(PartialEq,Debug)]
pub enum Bracket{
    Branch(Vec<Bracket>),
    Leaf(String),
    Empty,
}

pub fn lf(s:&str)->Bracket{
    Bracket::Leaf(s.to_string())
}

pub fn br()->Bracket{
    Bracket::Branch(Vec::new())
}




impl FromStr for Bracket{
    type Err = String;
    fn from_str(s:&str)->Result<Bracket,String>{
        let mut res = Bracket::Empty;
        let mut it = s.chars();
        let mut curr = String::new();
        while let Some(c) = it.next() {
            Bracket::match_char(c,&mut it,&mut curr,&mut res)?;
        }
        if curr.len() >0 {
            res.add_sib_str(curr);
        }
        Ok(res)
    }
}

impl<'a>IntoIterator for &'a Bracket{
    type Item = &'a Bracket;
    type IntoIter = BracketIter<'a>;
    fn into_iter(self)->Self::IntoIter{
        BracketIter::new(self)
    }
}

impl Bracket{
    fn add_sib_str(&mut self,s:String){
        if s.len() == 0 {
            return
        }
        self.add_sibling(Bracket::Leaf(s));
    }

    /// chaining method for quickly creating a tree Adds a sibling to a bracket
    /// if it is a leaf makes it a parent.
    pub fn sib(mut self,s:Self)->Self{
        self.add_sibling(s);
        self
    }

    /// chainging method for easily adding a leaf as a sibling from an &str 
    pub fn sib_lf(self,s:&str)->Self{
        self.sib(lf(s))
    }

    fn add_sibling(&mut self,s:Bracket){
        if s == Bracket::Empty {
            return
        }

        let c:String = match self {
            Bracket::Branch(ref mut v)=>{
                v.push(s);
                return
            }
            Bracket::Empty=>{
                *self = s;
                return 
            }
            Bracket::Leaf(content)=>content.to_string(),
        };

        *self = Bracket::Branch(vec![Bracket::Leaf(c),s]);
    }

    
    fn match_char<I>(c:char,it:&mut I,curr:&mut String,res:&mut Bracket)->Result<(),String>
        where I:Iterator<Item=char>{
            match c {
                '('=>{  // When Non Lexical Lifetimes comes, we can get rid of these curr.clone()s hopefully
                    res.add_sib_str(curr.clone());
                    *curr = String::new();
                    res.add_sibling(Bracket::from_bracket(it,')')?);
                },
                '{'=>{ //Todo make Json-esque prob needs Object Variant 
                    res.add_sib_str(curr.clone());
                    *curr = String::new();
                    res.add_sibling(Bracket::from_bracket(it,'}')?);
                },
                '['=>{
                    res.add_sib_str(curr.clone());
                    *curr = String::new();
                    res.add_sibling(Bracket::from_bracket(it,']')?);
                },
                '"'|'\''=>{
                    res.add_sib_str(curr.clone());
                    *curr = String::new();
                    res.add_sibling(Bracket::from_quotes(it,c)?);
                }
                ' '|','=>{
                    res.add_sib_str(curr.clone());
                    *curr = String::new();
                },
                other=>curr.push(other),
            }
            Ok(())
    }


    fn from_bracket<I:Iterator<Item=char>>(it:&mut I,delim:char)->Result<Bracket,String>{
        let mut res = Bracket::Branch(Vec::new());
        let mut curr = String::new();
        while let Some(c) = it.next() {
            if c == delim {
                res.add_sib_str(curr.clone());
                return Ok(res);
            }
            Bracket::match_char(c,it,&mut curr,&mut res)?;
        }
        Err(format!("Close Delim '{}' not found",delim))
    }

    fn from_quotes<I:Iterator<Item=char>>(it:&mut I,delim:char)->Result<Bracket,String>{
        let mut curr = String::new();
        while let Some(c) = it.next() {
            if c == delim {
                return Ok(Bracket::Leaf(curr));
            }
            match c {
                '\\'=>{
                    match it.next(){
                        Some(c2)=>{
                            curr.push(c2);
                            continue
                        },
                        None=>return Err("Escape before end of string".to_string()),
                    }
                },
                _=> curr.push(c),
            }
        }
        Err(format!("Close Delim '{}' not found",delim))
    }

    pub fn head<'a>(&'a self)->&'a Bracket{
        match self{
            Bracket::Branch(v)=>match v.len(){
                0 => &EMPTY_BRACKET,
                _ => &v[0], 
            }
            _ => &EMPTY_BRACKET,
        }
    }

    pub fn tail<'a>(&'a self)->Tail<'a>{
        match self{
            Bracket::Branch(v)=>match v.len(){
                0|1 =>Tail::Empty,
                _=>Tail::Rest(&v[1..]),
            }
            _=>Tail::Empty,
        }
    }

    pub fn tail_n<'a>(&'a self,n:usize)->Tail<'a>{
        match self{
            Bracket::Branch(v)=>{
                if v.len() <= n {
                    return Tail::Empty;
                }
                Tail::Rest(&v[n..])
            }
            _=>Tail::Empty,
        }
    }

    pub fn tail_h<'a>(&'a self, n:usize)->&'a Bracket{
        match self{
            Bracket::Branch(v)=>{
                if v.len() <= n{
                    return &EMPTY_BRACKET;
                }
                &v[n]
            }
            _=>&EMPTY_BRACKET,
        }
    }

    pub fn head_tail<'a>(&'a self)->(&'a Bracket,Tail<'a>){
        (self.head(),self.tail())
    }

    pub fn match_str<'a>(&'a self)->&'a str{
        match self {
            Bracket::Leaf(ref s)=>s.as_ref(),
            _=>"",
        }
    }

}

impl Display for Bracket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Bracket::Branch(ref v)=>{
                let mut gap = "";
                for b in v {
                    let res = match b {
                        Bracket::Branch(_)=>write!(f,"{}[{}]",gap,b),
                        _=>write!(f,"{}{}",gap,b),
                    };
                    if res.is_err(){
                        return res;
                    }
                    gap = " ";
                }
                Ok(())
            },
            Bracket::Leaf(s)=>{
                //TODO handle Escapes
                write!(f,"\"{}\"",s)
            },
            _=>{ write!(f,"--EMPTY--") },
        }
    }

}



#[cfg(test)]
mod tests {
    use super::{Bracket,br,lf};
    use std::str::FromStr;
    #[test]
    fn spaces() {
        let b1 = Bracket::from_str("matt dave (andy steve)").unwrap();
        let c1 = br().sib_lf("matt").sib_lf("dave").sib(
                            br().sib_lf("andy").sib_lf("steve")
                        );
                                        
        let b2 = Bracket::from_str("matt dave( andy steve)").unwrap();
        let b3 = Bracket::from_str(" matt   dave  (   andy    steve  )  ").unwrap();
        assert_eq!(b1,c1);
        assert_eq!(b1,b2);
        assert_eq!(b1,b3);
    }

    #[test]
    fn empty_parent(){
        let b1 = Bracket::from_str("matt () dave").unwrap();
        let c1 = br().sib_lf("matt").sib(br()).sib_lf("dave");
        assert_eq!(b1,c1);
    }

    #[test]
    fn many_parent(){
        let b1 = Bracket::from_str("matt ({[() ()]})").unwrap();
        let c1 = lf("matt")
                    .sib(
                        br().sib(
                            br().sib(
                                br().sib(br()).sib(br())
                            )
                        )
                    );
        assert_eq!(b1,c1);

    }

    #[test]
    fn strings(){
        let b1 = Bracket::from_str(r#"matt"dave""#).unwrap();
        let c1 = br().sib_lf("matt").sib_lf("dave");

        assert_eq!(b1,c1);

        let b2 = Bracket::from_str(r#""andy \"hates\" cheese""#).unwrap();
        let c2 = lf(r#"andy "hates" cheese"#);
        assert_eq!(b2,c2);
    }

    #[test]
    fn errors(){
        assert!(Bracket::from_str("peop ( er").is_err());
        assert!(Bracket::from_str(r#""poop"#).is_err());
    }

    #[test]
    fn test_head_tail(){
        
        let b1 = Bracket::from_str("hello (andy dave)").unwrap();
        match b1.head().match_str(){
            "hello"=>{},//Where the actual code might go
            _=>panic!("Head is not hello leaf"),
            
        }
    }

    #[test]
    fn many_tails(){
        let pb = br().sib_lf("matt").sib_lf("dave").sib_lf("pete").sib_lf("andy");

        let t1 = pb.tail(); //pb is parent bracket, t1 is tail
        let t4 = t1.tail_h(2).match_str();
        assert_eq!(t4,"andy");

        let th1 = pb.tail_h(3).match_str();

        assert_eq!(t4,th1);
        
    }

    #[test]
    fn test_to_string(){
        let br = Bracket::from_str("matt dave( andy steve)").unwrap();
        let bs = br.to_string();

        assert_eq!(&bs,r#""matt" "dave" ["andy" "steve"]"#);
    }
}