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


/// Calls a sequence of parsers, failing completely if one returns `Err`.
///
/// ## Example 
/// ```
/// just!( fn left_number { "123" } );
/// just!( fn right_number { "456" } );
/// just!( fn plus { "+" } );
///
/// and!( fn addition { 
///
///     left_number();
///     plus(); 
///     right_number(); 
///
/// });
///
/// assert!( addition(String::from("123+456"), 0).is_ok() );
/// ```
///
#[macro_export]
macro_rules! and {
    
    ($visibility:vis fn $name:ident { $($function:ident() ;)* } ) => {
    
        $visibility fn $name (string: &str, index: usize) -> $crate::core::Result {

            use std::rc::Rc;
            use $crate::core::Done;
            use $crate::core::Result;
            use $crate::core::Progress;

            let name: &'static str = stringify!($name);

            let sequence: Vec<fn(&str, usize) -> $crate::core::Result> = vec![$($function),*];

            let mut offset: usize = 0;
            
            let mut children: Vec<Rc<Done>> = vec![];

            for parser in sequence {
                
                let progress_maybe = parser(string, index + offset);

                match progress_maybe {
                    
                    Ok(progress) => {

                        offset += progress.offset();

                        children.push(Rc::from(progress.done().unwrap()));

                    }

                    Err(done) => return Err( Done::Fail { 
                        
                        name,
                        done: Some(Box::from(done)) 
                    
                    })

                }

            }

            Ok( Progress::Nonempty {

                offset,
                
                done: Done::Nonterminal {

                    name,

                    children
                    
                }
            
            })
 
        }

    }
}