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#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum Pattern{
18 Arg(Box<Pattern>, String),
20
21 Str(String),
23 Range(char, char),
24 Symbol(char), Identifier,
28 Type,
29 Expr,
30 Rdl,
31
32 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 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 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#[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}