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


use parsers::{Parser, ParserCombinator, ParseResult};
use regex::{Captures, Regex};
use std::rc::Rc;

pub type StringParser<T> = Parser<I=str, O=T>;
    
/// A string Parser that attempts to consume the given regex
#[derive(Clone)]
pub struct RegexLiteralParser<T: Clone> {
  pub regex: Regex,
  literal: T,
}

impl<T: Clone> Parser for RegexLiteralParser<T> {
  type I = str;
  type O = T;

  fn parse<'a>(&self, data: &'a str) -> ParseResult<&'a str, Self::O>{
    self.regex.find(data).map(|(_, e)| (self.literal.clone(), &data[e..])).ok_or(format!("regex literal match fail"))
  }
}

impl<T: Clone> ParserCombinator for RegexLiteralParser<T> {}


pub struct RegexCapturesParser<T, F: Fn(Captures) -> T> {
  pub regex: Regex,
  f: Rc<Box<F>>
}

impl<T, F: Fn(Captures) -> T> Parser for RegexCapturesParser<T, F> {

  type I = str;
  type O = T;

  fn parse<'a>(&self, data: &'a str) -> ParseResult<&'a str, T> {
    match self.regex.captures(data) {
      Some(caps) => match caps.pos(0) {
        Some((_, e)) => Ok(((self.f)(caps), &data[e..])),
        None => Err(format!("No Match"))
      },
      None => Err(format!("No Match"))
    }
  }
}

impl<T: Clone, F: Fn(Captures) -> T> ParserCombinator for RegexCapturesParser<T, F> {}

impl<T: Clone, F: Fn(Captures) -> T> Clone for RegexCapturesParser<T, F> {

  fn clone(&self) -> Self {
    RegexCapturesParser{regex: self.regex.clone(), f: self.f.clone()}
  }
}


pub fn rlit<T: Clone>(r: Regex, l: T) -> RegexLiteralParser<T> {
  RegexLiteralParser{regex: r, literal: l}
}
pub fn str_lit<T: Clone>(s: &str, l: T) -> RegexLiteralParser<T> {
  let r = format!("^{}", s);
  let regex = Regex::new(&r).unwrap();
  RegexLiteralParser{regex: regex, literal: l}
}

pub fn capture<T, F: 'static + Fn(Captures) -> T>(reg: &str, f: F) -> RegexCapturesParser<T, F> {
  let regex = Regex::new(reg).unwrap();

  RegexCapturesParser{regex: regex, f: Rc::new(Box::new(f))}
}