1
#![allow(non_camel_case_types, non_snake_case)]
2
#![allow(dead_code)]
3

            
4
use merc_pest_consume::match_nodes;
5

            
6
// Define a simple matcher based on an enum. Each variant of the enum gives a node name, and the
7
// corresponding matcher function extracts the contained value. The contructed node type stores the
8
// enum variant and an optional tag.
9
macro_rules! simple_matcher {
10
    (
11
        #[matcher=$matcher:ident]
12
        #[node=$node:ident]
13
        #[names=$name:ident]
14
        enum $kind:ident { $($variant:ident($ty:ty),)* }
15
    ) => {
16
        #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
17
        enum $name {
18
            $($variant,)*
19
        }
20

            
21
        #[derive(Debug, PartialEq, Eq)]
22
        enum $kind {
23
            $($variant($ty),)*
24
        }
25

            
26
        #[derive(Debug, PartialEq, Eq)]
27
        struct $node {
28
            kind: $kind,
29
            tag: Option<String>,
30
        }
31

            
32
        impl $kind {
33
36
            fn no_tag(self) -> $node {
34
36
                $node { kind: self, tag: None }
35
36
            }
36
10
            fn with_tag(self, tag: impl ToString) -> $node {
37
10
                $node { kind: self, tag: Some(tag.to_string()) }
38
10
            }
39
75
            fn name(&self) -> $name {
40
75
                match self {
41
18
                    $($kind::$variant(_) => $name::$variant,)*
42
                }
43
75
            }
44
        }
45

            
46
        impl $node {
47
75
            fn name(&self) -> $name {
48
75
                self.kind.name()
49
75
            }
50
        }
51

            
52
        impl From<$kind> for $node {
53
            fn from(kind: $kind) -> $node {
54
                kind.no_tag()
55
            }
56
        }
57

            
58
        struct $matcher;
59

            
60
        impl merc_pest_consume::NodeMatcher for $matcher {
61
            type NodeName = $name;
62
        }
63

            
64
        impl $matcher {
65
            $(
66
27
                fn $variant(n: $node) -> Result<$ty, ()> {
67
27
                    match n.kind {
68
27
                        $kind::$variant(x) => Ok(x),
69
                        _ => Err(()),
70
                    }
71
27
                }
72

            
73
            )*
74
        }
75

            
76
        impl merc_pest_consume::NodeList<$matcher> for Vec<$node> {
77
            type Node = $node;
78
            type NodeNamer = Namer;
79

            
80
27
            fn consume(self) -> (Vec<Self::Node>, Namer) {
81
27
                (self, Namer)
82
27
            }
83
        }
84

            
85
        struct Namer;
86
        impl merc_pest_consume::NodeNamer<$matcher> for Namer {
87
            type Node = $node;
88
            type Error = ();
89

            
90
75
            fn node_name(&self, n: &Self::Node) -> $name {
91
75
                n.name()
92
75
            }
93
21
            fn tag<'a>(&self, n: &'a Self::Node) -> Option<&'a str>{
94
21
                n.tag.as_deref()
95
21
            }
96
9
            fn error(self, _message: String) -> Self::Error {
97

            
98
9
            }
99
        }
100
    };
101
}
102

            
103
use NodeKind::*;
104
simple_matcher! {
105
    #[matcher=TestMatcher]
106
    #[node=Node]
107
    #[names=NodeName]
108
    enum NodeKind {
109
        boolean(bool),
110
        string(String),
111
        number(u32),
112
    }
113
}
114

            
115
19
fn notag(input: Vec<NodeKind>) -> Vec<Node> {
116
35
    input.into_iter().map(|kind| kind.no_tag()).collect()
117
19
}
118

            
119
#[test]
120
1
fn single_number() {
121
4
    let single_number = |input: Vec<NodeKind>| {
122
4
        Ok(match_nodes!(<TestMatcher>; notag(input);
123
1
            [number(x)] => x,
124
        ))
125
4
    };
126
1
    assert!(single_number(vec![]).is_err());
127
1
    assert!(single_number(vec![string(String::new())]).is_err());
128
1
    assert_eq!(single_number(vec![number(42)]), Ok(42));
129
1
    assert!(single_number(vec![number(42), number(0)]).is_err());
130
1
}
131

            
132
#[test]
133
1
fn multi_number() {
134
3
    let multi_number = |input: Vec<NodeKind>| {
135
3
        Ok(match_nodes!(<TestMatcher>; notag(input);
136
3
            [number(x)..] => x.collect::<Vec<_>>(),
137
        ))
138
3
    };
139
1
    assert_eq!(multi_number(vec![]), Ok(vec![]));
140
1
    assert_eq!(multi_number(vec![number(42)]), Ok(vec![42]));
141
1
    assert_eq!(multi_number(vec![number(42), number(12)]), Ok(vec![42, 12]));
142
1
}
143

            
144
#[test]
145
1
fn multi_number_skip() {
146
4
    let multi_number_skip = |input: Vec<NodeKind>| {
147
4
        Ok(match_nodes!(<TestMatcher>; notag(input);
148
3
            [_, number(x).., _] => x.collect::<Vec<_>>(),
149
        ))
150
4
    };
151
1
    assert!(multi_number_skip(vec![]).is_err());
152
1
    assert_eq!(multi_number_skip(vec![number(0), number(0)]), Ok(vec![]));
153
1
    assert_eq!(
154
1
        multi_number_skip(vec![number(0), number(41), number(42), number(0)]),
155
1
        Ok(vec![41, 42])
156
    );
157
1
    assert_eq!(
158
1
        multi_number_skip(vec![boolean(true), number(41), number(42), boolean(false)]),
159
1
        Ok(vec![41, 42])
160
    );
161
1
}
162

            
163
#[test]
164
1
fn multi_multi() {
165
6
    let multi_multi = |input: Vec<NodeKind>| {
166
6
        Ok(match_nodes!(<TestMatcher>; notag(input);
167
5
            [number(x).., boolean(y).., _] => (x.sum(), y.clone().all(|b| b)),
168
        ))
169
6
    };
170
1
    assert!(multi_multi(vec![]).is_err());
171
1
    assert_eq!(multi_multi(vec![number(1), number(2)]), Ok((1, true)));
172
1
    assert_eq!(multi_multi(vec![number(1), number(2), number(4)]), Ok((3, true)));
173
1
    assert_eq!(multi_multi(vec![number(1), boolean(true), number(4)]), Ok((1, true)));
174
1
    assert_eq!(
175
1
        multi_multi(vec![boolean(false), boolean(true), number(4)]),
176
        Ok((0, false))
177
    );
178
1
    assert_eq!(
179
1
        multi_multi(vec![boolean(true), boolean(true), boolean(false)]),
180
        Ok((0, true))
181
    );
182
1
}
183

            
184
#[test]
185
1
fn single_tag() {
186
4
    let single_tag = |input: Vec<Node>| {
187
4
        Ok(match_nodes!(<TestMatcher>; input;
188
1
            [tag1 # number(x)] => x,
189
        ))
190
4
    };
191
1
    assert!(single_tag(vec![]).is_err());
192
1
    assert!(single_tag(vec![number(0).no_tag()]).is_err());
193
1
    assert!(single_tag(vec![number(0).with_tag("tag2")]).is_err());
194
1
    assert_eq!(single_tag(vec![number(0).with_tag("tag1")]), Ok(0));
195
1
}
196

            
197
#[test]
198
1
fn multi_multi_tag() {
199
4
    let multi_multi_tag = |input: Vec<Node>| {
200
4
        Ok(match_nodes!(<TestMatcher>; input;
201
3
            [tag1 # number(x).., tag2 # number(y)..] => (x.sum(), y.sum()),
202
        ))
203
4
    };
204
1
    assert_eq!(multi_multi_tag(vec![number(1).with_tag("tag1")]), Ok((1, 0)));
205
1
    assert_eq!(multi_multi_tag(vec![number(1).with_tag("tag2")]), Ok((0, 1)));
206
1
    assert_eq!(
207
1
        multi_multi_tag(vec![
208
1
            number(1).with_tag("tag1"),
209
1
            number(1).with_tag("tag2"),
210
1
            number(1).with_tag("tag1"),
211
1
        ]),
212
        Err(())
213
    );
214
1
    assert_eq!(
215
1
        multi_multi_tag(vec![
216
1
            number(1).with_tag("tag1"),
217
1
            number(2).with_tag("tag1"),
218
1
            number(4).with_tag("tag2"),
219
1
        ]),
220
        Ok((3, 4))
221
    );
222
1
}
223

            
224
#[test]
225
1
fn or_pattern() {
226
2
    let or_pattern = |input: Vec<NodeKind>| {
227
2
        Ok(match_nodes!(<TestMatcher>; notag(input);
228
1
            [number(x), boolean(b)] | [boolean(b), number(x)] => (x, b),
229
        ))
230
2
    };
231
1
    assert_eq!(or_pattern(vec![number(42), boolean(true)]), Ok((42, true)));
232
1
    assert_eq!(or_pattern(vec![boolean(true), number(42)]), Ok((42, true)));
233
1
}