ryna/
patterns.rs

1use std::{cell::RefCell, collections::{ HashMap, HashSet }};
2
3use nom::{
4    branch::alt, bytes::complete::{tag, take_while1}, character::complete::{one_of, satisfy}, combinator::{cut, map, opt, value}, error::{VerboseError, VerboseErrorKind}, multi::separated_list1, sequence::{delimited, separated_pair, tuple}
5};
6use serde::{Serialize, Deserialize};
7
8use crate::{context::RynaContext, macros::RynaMacroType, parser::{empty0, empty1, identifier_parser, string_parser, verbose_error, PCache, PResult, Span}};
9
10/*
11                                                  ╒══════════════════╕
12    ============================================= │  IMPLEMENTATION  │ =============================================
13                                                  ╘══════════════════╛
14*/
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum Pattern{
18    // Markers
19    Arg(Box<Pattern>, String),
20
21    // Tail patterns
22    Str(String),
23    Range(char, char),
24    Symbol(char), // Digit (d), Letter (l/L), Alphabetic (a), Alphanumeric (A), Space (s)
25
26    // High level patterns
27    Identifier,
28    Type,
29    Expr,
30    Rdl,
31
32    // Combination patterns
33    Or(Vec<Pattern>),
34    And(Vec<Pattern>),
35    Optional(Box<Pattern>),
36    Repeat(Box<Pattern>, Option<usize>, Option<usize>)
37}
38
39impl Pattern {
40    pub fn get_markers(&self) -> HashSet<String> {
41        return match self {
42            Pattern::Arg(_, n) => vec!(n.clone()).into_iter().collect(),
43            Pattern::Or(p) |
44            Pattern::And(p) => p.iter().flat_map(Pattern::get_markers).collect(),
45            Pattern::Repeat(p, _, _) |
46            Pattern::Optional(p) => p.get_markers(),
47            _ => HashSet::new()
48        };
49    }
50
51    pub fn extract<'a>(&'a self, text: Span<'a>, ctx: &'a RynaContext, cache: &PCache<'a>) -> PResult<'a, HashMap<String, Vec<String>>> {
52        fn merge(a: &mut HashMap<String, Vec<String>>, b: HashMap<String, Vec<String>>) {
53            for (k, v) in b.into_iter() {
54                a.entry(k).or_default().extend(v);
55            }
56        }
57
58        return match self {
59            Pattern::Symbol('d') => value(HashMap::new(), satisfy(|c| c.is_ascii_digit()))(text),
60            Pattern::Symbol('l') => value(HashMap::new(), satisfy(|c| c.is_lowercase()))(text),
61            Pattern::Symbol('L') => value(HashMap::new(), satisfy(|c| c.is_uppercase()))(text),
62            Pattern::Symbol('a') => value(HashMap::new(), satisfy(|c| c.is_alphabetic()))(text),
63            Pattern::Symbol('A') => value(HashMap::new(), satisfy(|c| c.is_alphanumeric()))(text),
64            Pattern::Symbol('s') => value(HashMap::new(), empty1)(text),
65            Pattern::Symbol(_) => unreachable!(),
66
67            Pattern::Range(a, b) => value(HashMap::new(), satisfy(|c| c >= *a && c <= *b))(text),
68
69            Pattern::Identifier => value(HashMap::new(), identifier_parser)(text),
70            Pattern::Type => value(HashMap::new(), |input| ctx.type_parser(input))(text),
71            Pattern::Expr => value(HashMap::new(), |input| ctx.ryna_expr_parser(input, cache))(text),
72            Pattern::Rdl => value(HashMap::new(), |input| parse_rdl_pattern(input, true, true, ctx))(text),
73
74            Pattern::Str(s) => value(HashMap::new(), tag(s.as_str()))(text),
75
76            Pattern::And(patterns) => {
77                let mut res = HashMap::new();
78                let mut input = text;
79
80                for p in patterns {
81                    if let Ok((i, o)) = p.extract(input, ctx, cache) {
82                        input = i;
83                        merge(&mut res, o);
84
85                    } else {
86                        return Err(verbose_error(text, "Unable to parse"))
87                    }
88                }
89                
90                Ok((input, res))
91            },
92
93            Pattern::Or(patterns) => {
94                for p in patterns {
95                    if let Ok((i, o)) = p.extract(text, ctx, cache) {
96                        return Ok((i, o));
97                    }
98                }
99                
100                Err(verbose_error(text, "Unable to parse"))
101            },
102            
103            Pattern::Repeat(p, from, to) => {
104                let mut res = HashMap::new();
105                let mut input = text;
106
107                // Minimum
108                if let Some(f) = from {
109                    for _ in 0..*f {
110                        if let Ok((i, o)) = p.extract(input, ctx, cache) {
111                            input = i;
112                            merge(&mut res, o);
113    
114                        } else {
115                            return Err(verbose_error(text, "Unable to parse"))
116                        }
117                    }
118                }
119
120                // Maximum
121                if let Some(t) = to {
122                    for _ in 0..(t - from.unwrap_or(0)) {
123                        if let Ok((i, o)) = p.extract(input, ctx, cache) {
124                            input = i;
125                            merge(&mut res, o);
126    
127                        } else {
128                            break;
129                        }
130                    }
131
132                } else {
133                    while let Ok((i, o)) = p.extract(input, ctx, cache) {
134                        input = i;
135                        merge(&mut res, o);
136                    }
137                }
138
139                Ok((input, res))
140            }
141
142            Pattern::Optional(p) => map(opt(|i| p.extract(i, ctx, cache)), Option::unwrap_or_default)(text),
143            Pattern::Arg(p, k) => {
144                let (i, mut o) = p.extract(text, ctx, cache)?;
145
146                o.entry(k.clone()).or_default().push(text[..(text.len() - i.len())].into());
147
148                Ok((i, o))
149            }
150        };
151    }
152}
153
154fn parse_and<'a>(text: Span<'a>, and: bool, ctx: &'a RynaContext) -> PResult<'a, Pattern> {
155    return if and {
156        map(
157            separated_list1(empty1, |i| parse_rdl_pattern(i, false, false, ctx)), 
158            |v| if v.len() > 1 { Pattern::And(v) } else { v[0].clone() }
159        )(text)
160        
161    } else {
162        Err(verbose_error(text, "Unable to parse"))
163    }
164}
165
166fn parse_or<'a>(text: Span<'a>, or: bool, ctx: &'a RynaContext) -> PResult<'a, Pattern> {
167    return if or {
168        return map(
169            separated_list1(tuple((empty0, tag("|"), empty0)), |i| parse_rdl_pattern(i, false, true, ctx)), 
170            |v| if v.len() > 1 { Pattern::Or(v) } else { v[0].clone() }
171        )(text)
172        
173    } else {
174        Err(verbose_error(text, "Unable to parse"))
175    }
176}
177
178fn custom_rdl_pattern_parser<'a>(ctx: &'a RynaContext, mut input: Span<'a>, cache: &PCache<'a>) -> PResult<'a, Pattern> {
179    let prev_input = input;
180
181    for m in ctx.macros.iter().filter(|i| i.m_type == RynaMacroType::Rdl) {            
182        if let Ok((new_input, args)) = m.pattern.extract(input, ctx, cache) {
183            input = new_input;
184
185            match m.generator.expand(&args, ctx) {
186                Ok(code) => {                    
187                    let parsed_code = cut(
188                        |input| parse_rdl_pattern(input, true, true, ctx)
189                    )(Span::new(&code));
190
191                    match parsed_code {
192                        Ok((rest, pattern)) if rest.trim().is_empty() => {
193                            return match m.m_type {
194                                RynaMacroType::Rdl => Ok((input, pattern)),
195                                _ => unreachable!(),
196                            }
197                        },
198
199                        Ok(_) |
200                        Err(nom::Err::Error(_)) |
201                        Err(nom::Err::Failure(_)) => {                                
202                            return Err(nom::Err::Failure(VerboseError { errors: vec!((
203                                prev_input, 
204                                VerboseErrorKind::Context("Error while parsing expanded code")
205                            )) }));
206                        }
207
208                        _ => unreachable!()
209                    }
210                }
211
212                Err(_) => {
213                    return Err(verbose_error(prev_input, "Unable to parse"))
214                }
215            }
216        }
217    }
218
219    return Err(verbose_error(prev_input, "Unable to parse"))
220}
221
222pub fn parse_rdl_pattern<'a>(text: Span<'a>, or: bool, and: bool, ctx: &'a RynaContext) -> PResult<'a, Pattern> {
223    return alt((
224        |input| custom_rdl_pattern_parser(ctx, input, &RefCell::default()),
225        |i| parse_or(i, or, ctx),
226        |i| parse_and(i, and, ctx),
227        map(delimited(tag("["), separated_pair(satisfy(|c| c != '\"'), tag("-"), satisfy(|c| c != '\"')), tag("]")), |(a, b)| Pattern::Range(a, b)),
228        map(string_parser, |s: String| Pattern::Str(s.to_string())),
229        map(delimited(
230            tuple((tag("Arg("), empty0)),
231            separated_pair(|i| parse_rdl_pattern(i, true, true, ctx), tuple((empty0, tag(","), empty0)), take_while1(|c| c != ')')),
232            tuple((empty0, tag(")")))
233        ), |(p, n)| Pattern::Arg(Box::new(p), n.to_string())),
234        map(tuple((
235            opt(map(take_while1(|c: char| c.is_ascii_digit()), |s: Span<'a>| s.parse::<usize>().unwrap())),
236            delimited(tuple((tag("{"), empty0)), |i| parse_rdl_pattern(i, true, true, ctx), tuple((empty0, tag("}")))),
237            opt(map(take_while1(|c: char| c.is_ascii_digit()), |s: Span<'a>| s.parse::<usize>().unwrap()))
238        )), |(f, p, t)| Pattern::Repeat(Box::new(p), f, t)),
239        map(delimited(tuple((tag("["), empty0)), |i| parse_rdl_pattern(i, true, true, ctx), tuple((empty0, tag("]")))), |p| Pattern::Optional(Box::new(p))),
240        delimited(tuple((tag("("), empty0)), |i| parse_rdl_pattern(i, true, true, ctx), tuple((empty0, tag(")")))),
241        map(one_of("dlLaAsq"), Pattern::Symbol),
242        value(Pattern::Identifier, tag("<ident>")),
243        value(Pattern::Type, tag("<type>")),
244        value(Pattern::Expr, tag("<expr>")),
245        value(Pattern::Rdl, tag("<rdl>"))
246    ))(text);
247}
248
249/*
250                                                  ╒═════════╕
251    ============================================= │  TESTS  │ =============================================
252                                                  ╘═════════╛
253*/
254
255#[cfg(test)]
256mod tests {
257    use std::cell::RefCell;
258    use std::collections::HashMap;
259    use std::iter::FromIterator;
260    
261    use crate::context::{standard_ctx, RynaContext};
262    use crate::parser::{Span, PResult};
263    use crate::patterns::Pattern;
264
265    use super::parse_rdl_pattern;
266
267    fn ok_result<T>(res: PResult<'_, T>) -> bool {
268        res.is_ok() && res.unwrap().0.is_empty()
269    }
270
271    fn parse_pattern(str: &str, ctx: &RynaContext) -> Result<Pattern, ()> {
272        parse_rdl_pattern(Span::new(str), true, true, ctx).map(|i| i.1).map_err(|_| ())
273    }
274
275    #[test]
276    fn basic_patterns() {
277        let ctx = standard_ctx();
278
279        let u_pattern = Pattern::Str("test".into());
280
281        assert!(u_pattern.extract(Span::new("utest"), &ctx, &RefCell::default()).is_err());
282        assert!(ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
283
284        let u_pattern = Pattern::And(vec!(
285            Pattern::Str("test".into()),
286            Pattern::Str("1".into())
287        ));
288
289        assert!(u_pattern.extract(Span::new("utest"), &ctx, &RefCell::default()).is_err());
290        assert!(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default()).is_err());
291        assert!(ok_result(u_pattern.extract(Span::new("test1"), &ctx, &RefCell::default())));
292
293        let u_pattern = Pattern::And(vec!(
294            Pattern::Str("*".into()),
295            Pattern::Str("test".into()),
296            Pattern::Str("1".into())
297        ));
298
299        assert!(u_pattern.extract(Span::new("utest"), &ctx, &RefCell::default()).is_err());
300        assert!(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default()).is_err());
301        assert!(u_pattern.extract(Span::new("test1"), &ctx, &RefCell::default()).is_err());
302        assert!(ok_result(u_pattern.extract(Span::new("*test1"), &ctx, &RefCell::default())));
303
304        let u_pattern = Pattern::Or(vec!(
305            Pattern::Str("1".into()),
306            Pattern::Str("2".into())
307        ));
308
309        assert!(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default()).is_err());
310        assert!(u_pattern.extract(Span::new("*"), &ctx, &RefCell::default()).is_err());
311        assert!(ok_result(u_pattern.extract(Span::new("1"), &ctx, &RefCell::default())));
312        assert!(ok_result(u_pattern.extract(Span::new("2"), &ctx, &RefCell::default())));
313
314        let u_pattern = Pattern::Or(vec!(
315            Pattern::Str("*".into()),
316            Pattern::Str("1".into()),
317            Pattern::Str("2".into())
318        ));
319
320        assert!(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default()).is_err());
321        assert!(ok_result(u_pattern.extract(Span::new("*"), &ctx, &RefCell::default())));
322        assert!(ok_result(u_pattern.extract(Span::new("1"), &ctx, &RefCell::default())));
323        assert!(ok_result(u_pattern.extract(Span::new("2"), &ctx, &RefCell::default())));
324
325        let u_pattern = Pattern::And(vec!(
326            Pattern::Or(vec!(
327                Pattern::Str(".".into()),
328                Pattern::Str("#".into())
329            )),
330            Pattern::Str("test".into()),
331            Pattern::Or(vec!(
332                Pattern::Str("1".into()),
333                Pattern::Str("2".into())
334            ))
335        ));
336        
337        assert!(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default()).is_err());
338        assert!(u_pattern.extract(Span::new(".test"), &ctx, &RefCell::default()).is_err());
339        assert!(u_pattern.extract(Span::new("#test"), &ctx, &RefCell::default()).is_err());
340        assert!(u_pattern.extract(Span::new("test1"), &ctx, &RefCell::default()).is_err());
341        assert!(u_pattern.extract(Span::new("test2"), &ctx, &RefCell::default()).is_err());
342        assert!(ok_result(u_pattern.extract(Span::new("#test1"), &ctx, &RefCell::default())));
343        assert!(ok_result(u_pattern.extract(Span::new("#test2"), &ctx, &RefCell::default())));
344        assert!(ok_result(u_pattern.extract(Span::new(".test1"), &ctx, &RefCell::default())));
345        assert!(ok_result(u_pattern.extract(Span::new(".test2"), &ctx, &RefCell::default())));
346
347        let u_pattern = Pattern::Repeat(
348            Box::new(Pattern::Str("test".into())),
349            Some(1),
350            Some(3)
351        );
352        
353        assert!(u_pattern.extract(Span::new("utest"), &ctx, &RefCell::default()).is_err());
354        assert!(u_pattern.extract(Span::new(""), &ctx, &RefCell::default()).is_err());
355        assert!(ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
356        assert!(ok_result(u_pattern.extract(Span::new("testtest"), &ctx, &RefCell::default())));
357        assert!(ok_result(u_pattern.extract(Span::new("testtesttest"), &ctx, &RefCell::default())));
358        assert!(!ok_result(u_pattern.extract(Span::new("testtesttesttest"), &ctx, &RefCell::default())));
359
360        let u_pattern = Pattern::Repeat(
361            Box::new(Pattern::Str("a".into())),
362            None,
363            Some(2)
364        );
365        
366        assert!(!ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
367        assert!(ok_result(u_pattern.extract(Span::new(""), &ctx, &RefCell::default())));
368        assert!(ok_result(u_pattern.extract(Span::new("a"), &ctx, &RefCell::default())));
369        assert!(ok_result(u_pattern.extract(Span::new("aa"), &ctx, &RefCell::default())));
370        assert!(!ok_result(u_pattern.extract(Span::new("aaa"), &ctx, &RefCell::default())));
371
372        let u_pattern = Pattern::Repeat(
373            Box::new(Pattern::Str("a".into())),
374            Some(2),
375            None
376        );
377        
378        assert!(!ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
379        assert!(!ok_result(u_pattern.extract(Span::new(""), &ctx, &RefCell::default())));
380        assert!(!ok_result(u_pattern.extract(Span::new("a"), &ctx, &RefCell::default())));
381        assert!(ok_result(u_pattern.extract(Span::new("aa"), &ctx, &RefCell::default())));
382        assert!(ok_result(u_pattern.extract(Span::new("aaa"), &ctx, &RefCell::default())));
383        assert!(ok_result(u_pattern.extract(Span::new("aaaa"), &ctx, &RefCell::default())));
384        assert!(ok_result(u_pattern.extract(Span::new("aaaaa"), &ctx, &RefCell::default())));
385        assert!(ok_result(u_pattern.extract(Span::new("aaaaaa"), &ctx, &RefCell::default())));
386
387        let u_pattern = Pattern::Repeat(
388            Box::new(Pattern::Str("a".into())),
389            None,
390            None
391        );
392        
393        assert!(!ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
394        assert!(ok_result(u_pattern.extract(Span::new(""), &ctx, &RefCell::default())));
395        assert!(ok_result(u_pattern.extract(Span::new("a"), &ctx, &RefCell::default())));
396        assert!(ok_result(u_pattern.extract(Span::new("aa"), &ctx, &RefCell::default())));
397        assert!(ok_result(u_pattern.extract(Span::new("aaa"), &ctx, &RefCell::default())));
398        assert!(ok_result(u_pattern.extract(Span::new("aaaa"), &ctx, &RefCell::default())));
399        assert!(ok_result(u_pattern.extract(Span::new("aaaaa"), &ctx, &RefCell::default())));
400        assert!(ok_result(u_pattern.extract(Span::new("aaaaaa"), &ctx, &RefCell::default())));
401
402        let u_pattern = Pattern::And(vec!(
403            Pattern::Str("test".into()),
404            Pattern::Optional(
405                Box::new(Pattern::Str("?".into()))
406            )
407        ));
408        
409        assert!(!ok_result(u_pattern.extract(Span::new("utest"), &ctx, &RefCell::default())));
410        assert!(ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
411        assert!(ok_result(u_pattern.extract(Span::new("test?"), &ctx, &RefCell::default())));
412    }
413
414    #[test]
415    fn basic_parsing() {
416        let ctx = standard_ctx();
417
418        let pattern: Pattern = parse_pattern("\"hello\"", &ctx).expect("Error while parsing pattern");
419        
420        assert_eq!(pattern, Pattern::Str("hello".into()));
421
422        let pattern: Pattern = parse_pattern("[a-z]", &ctx).expect("Error while parsing pattern");
423        
424        assert_eq!(pattern, Pattern::Range('a', 'z'));
425
426        let pattern: Pattern = parse_pattern("[\"Test\"]", &ctx).expect("Error while parsing pattern");
427
428        assert_eq!(pattern, Pattern::Optional(Box::new(Pattern::Str("Test".into()))));
429
430        let pattern: Pattern = parse_pattern("[a-z] | [0-9]", &ctx).expect("Error while parsing pattern");
431        
432        assert_eq!(pattern, Pattern::Or(vec!(Pattern::Range('a', 'z'), Pattern::Range('0', '9'))));
433
434        let pattern: Pattern = parse_pattern("[a-z] [0-9]", &ctx).expect("Error while parsing pattern");
435        
436        assert_eq!(pattern, Pattern::And(vec!(Pattern::Range('a', 'z'), Pattern::Range('0', '9'))));
437
438        let pattern: Pattern = parse_pattern("Arg([a-z], l)", &ctx).expect("Error while parsing pattern");
439        
440        assert_eq!(pattern, Pattern::Arg(Box::new(Pattern::Range('a', 'z')), "l".into()));
441    }
442
443    #[test]
444    fn arg_markers(){
445        let ctx = standard_ctx();
446
447        let u_pattern = Pattern::And(vec!(
448            Pattern::Arg(
449                Box::new(Pattern::Optional(
450                    Box::new(Pattern::Str("-".into()))
451                )),
452                "Sign".into()
453            ),
454            Pattern::Arg(
455                Box::new(
456                    Pattern::Repeat(
457                        Box::new(Pattern::Symbol('d')),
458                        Some(1),
459                        None
460                    ),
461                ),
462                "Int".into()
463            ),
464            Pattern::Optional(Box::new(
465                Pattern::And(vec!(
466                    Pattern::Str(".".into()),
467                    Pattern::Arg(
468                        Box::new(Pattern::Repeat(
469                            Box::new(Pattern::Symbol('d')),
470                            Some(1),
471                            None
472                        )),
473                        "Dec".into()
474                    )
475                ))
476            ))
477        ));
478
479        assert_eq!(u_pattern.extract("125".into(), &ctx, &RefCell::default()).unwrap().1, HashMap::from_iter(vec!(
480            ("Sign".into(), vec!("".into())),
481            ("Int".into(), vec!("125".into())),
482        )));
483
484        assert_eq!(u_pattern.extract("0.056".into(), &ctx, &RefCell::default()).unwrap().1, HashMap::from_iter(vec!(
485            ("Sign".into(), vec!("".into())),
486            ("Int".into(), vec!("0".into())),
487            ("Dec".into(), vec!("056".into())),
488        )));
489
490        assert_eq!(u_pattern.extract("-13.26".into(), &ctx, &RefCell::default()).unwrap().1, HashMap::from_iter(vec!(
491            ("Sign".into(), vec!("-".into())),
492            ("Int".into(), vec!("13".into())),
493            ("Dec".into(), vec!("26".into())),
494        )));
495
496        assert!(!ok_result(u_pattern.extract(Span::new("+100"), &ctx, &RefCell::default())));
497        assert!(!ok_result(u_pattern.extract(Span::new("123."), &ctx, &RefCell::default())));
498        assert!(!ok_result(u_pattern.extract(Span::new("test"), &ctx, &RefCell::default())));
499    }
500
501    #[test]
502    fn high_level_pattern_parsing() {
503        let ctx = standard_ctx();
504
505        let pattern: Pattern = parse_pattern("<ident>", &ctx).expect("Error while parsing pattern");
506        
507        assert_eq!(pattern, Pattern::Identifier);
508
509        let pattern: Pattern = parse_pattern("<type>", &ctx).expect("Error while parsing pattern");
510        
511        assert_eq!(pattern, Pattern::Type);
512
513        let pattern: Pattern = parse_pattern("<expr>", &ctx).expect("Error while parsing pattern");
514        
515        assert_eq!(pattern, Pattern::Expr);
516
517        let pattern: Pattern = parse_pattern("<rdl>", &ctx).expect("Error while parsing pattern");
518        
519        assert_eq!(pattern, Pattern::Rdl);
520    }
521
522    #[test]
523    fn high_level_patterns() {
524        let ctx = standard_ctx();
525
526        let pattern: Pattern = parse_pattern("<ident>", &ctx).expect("Error while parsing pattern");
527        
528        assert!(ok_result(pattern.extract("test".into(), &ctx, &RefCell::default())));
529        assert!(ok_result(pattern.extract("test2".into(), &ctx, &RefCell::default())));
530        assert!(ok_result(pattern.extract("test_3".into(), &ctx, &RefCell::default())));
531        assert!(pattern.extract("3test".into(), &ctx, &RefCell::default()).is_err());
532
533        let pattern: Pattern = parse_pattern("<type>", &ctx).expect("Error while parsing pattern");
534        
535        assert!(ok_result(pattern.extract("Int".into(), &ctx, &RefCell::default())));
536        assert!(ok_result(pattern.extract("'Template".into(), &ctx, &RefCell::default())));
537        assert!(ok_result(pattern.extract("@Bool".into(), &ctx, &RefCell::default())));
538        assert!(ok_result(pattern.extract("(Bool, &String)".into(), &ctx, &RefCell::default())));
539        assert!(ok_result(pattern.extract("(Bool, Int) => String".into(), &ctx, &RefCell::default())));
540        assert!(ok_result(pattern.extract("Array<Int, 'T>".into(), &ctx, &RefCell::default())));
541        assert!(pattern.extract("Test".into(), &ctx, &RefCell::default()).is_err());
542        assert!(pattern.extract("+++".into(), &ctx, &RefCell::default()).is_err());
543
544        let pattern: Pattern = parse_pattern("<expr>", &ctx).expect("Error while parsing pattern");
545        
546        assert_eq!(pattern, Pattern::Expr);
547
548        assert!(ok_result(pattern.extract("5".into(), &ctx, &RefCell::default())));
549        assert!(ok_result(pattern.extract("true".into(), &ctx, &RefCell::default())));
550        assert!(ok_result(pattern.extract("6 + 2".into(), &ctx, &RefCell::default())));
551        assert!(ok_result(pattern.extract("(6 + 2, true, false + \"Test\")".into(), &ctx, &RefCell::default())));
552        assert!(ok_result(pattern.extract("a * 6 + 5 - \"Test\"".into(), &ctx, &RefCell::default())));
553        assert!(pattern.extract("5 ++ true".into(), &ctx, &RefCell::default()).unwrap().0.len() != 0);
554        assert!(pattern.extract("+8u76tt".into(), &ctx, &RefCell::default()).is_err());
555    }
556
557    #[test]
558    fn number_pattern() {
559        let ctx = standard_ctx();
560
561        let str_pattern = parse_pattern("Arg([\"-\"], Sign) Arg(1{d}, Int) [\".\" Arg(1{d}, Dec)]", &ctx).unwrap();
562
563        let u_pattern = Pattern::And(vec!(
564            Pattern::Arg(
565                Box::new(Pattern::Optional(
566                    Box::new(Pattern::Str("-".into()))
567                )),
568                "Sign".into()
569            ),
570            Pattern::Arg(
571                Box::new(
572                    Pattern::Repeat(
573                        Box::new(Pattern::Symbol('d')),
574                        Some(1),
575                        None
576                    ),
577                ),
578                "Int".into()
579            ),
580            Pattern::Optional(Box::new(
581                Pattern::And(vec!(
582                    Pattern::Str(".".into()),
583                    Pattern::Arg(
584                        Box::new(Pattern::Repeat(
585                            Box::new(Pattern::Symbol('d')),
586                            Some(1),
587                            None
588                        )),
589                        "Dec".into()
590                    )
591                ))
592            ))
593        ));
594
595        assert_eq!(u_pattern, str_pattern);
596
597        assert!(ok_result(u_pattern.extract("13".into(), &ctx, &RefCell::default())));
598        assert!(ok_result(u_pattern.extract("-156".into(), &ctx, &RefCell::default())));
599        assert!(ok_result(u_pattern.extract("0156".into(), &ctx, &RefCell::default())));
600        assert!(ok_result(u_pattern.extract("15.56".into(), &ctx, &RefCell::default())));
601        assert!(!ok_result(u_pattern.extract("15.".into(), &ctx, &RefCell::default())));
602        assert!(ok_result(u_pattern.extract("-56.176".into(), &ctx, &RefCell::default())));
603    }
604
605    #[test]
606    fn nested_patterns() {
607        let ctx = standard_ctx();
608
609        let pattern_nonest = Pattern::And(vec!(
610            Pattern::Str("[".into()),
611            Pattern::Repeat(Box::new(Pattern::Symbol('d')), Some(1), None),
612            Pattern::Repeat(Box::new(Pattern::And(vec!(
613                Pattern::Str(", ".into()),
614                Pattern::Repeat(Box::new(Pattern::Symbol('d')), Some(1), None)
615            ))), None, None),
616            Pattern::Str("]".into())
617        ));
618
619        assert!(ok_result(pattern_nonest.extract("[1, 2, 3]".into(), &ctx, &RefCell::default())));
620
621        let pattern_nested = Pattern::And(vec!(
622            Pattern::Str("[".into()),
623            Pattern::And(vec!(
624                Pattern::Repeat(Box::new(Pattern::Symbol('d')), Some(1), None),
625                Pattern::Repeat(Box::new(Pattern::And(vec!(
626                    Pattern::Str(", ".into()),
627                    Pattern::Repeat(Box::new(Pattern::Symbol('d')), Some(1), None)
628                ))), None, None)    
629            )),
630            Pattern::Str("]".into())
631        ));
632
633        assert!(ok_result(pattern_nested.extract("[1, 2, 3]".into(), &ctx, &RefCell::default())));
634    }
635
636    #[test]
637    fn pattern_grouping() {
638        let ctx = standard_ctx();
639
640        let str_pattern = parse_pattern("(l d) | (d d)", &ctx).unwrap();
641
642        let u_pattern = Pattern::Or(vec!(
643            Pattern::And(vec!(
644                Pattern::Symbol('l'),
645                Pattern::Symbol('d')
646            )),
647
648            Pattern::And(vec!(
649                Pattern::Symbol('d'),
650                Pattern::Symbol('d')
651            ))
652        ));
653
654        assert_eq!(u_pattern, str_pattern);
655
656        assert!(ok_result(u_pattern.extract("k1".into(), &ctx, &RefCell::default())));
657        assert!(ok_result(u_pattern.extract("90".into(), &ctx, &RefCell::default())));
658        assert!(ok_result(u_pattern.extract("b2".into(), &ctx, &RefCell::default())));
659        assert!(!ok_result(u_pattern.extract("yy".into(), &ctx, &RefCell::default())));
660    }
661}