use std::str;
use nom::IResult;
use errors::{Error, ErrorKind};
#[derive(Debug, PartialEq)]
pub enum Exp<'a> {
Func { name: &'a str },
Literal(&'a str),
}
named!(literal<&[u8], Exp>,
map!(
map_res!(
is_not!("%{"),
str::from_utf8
),
Exp::Literal
)
);
named!(func<&[u8], Exp>,
do_parse!(
tag!("%{") >>
name: map_res!(take_until!("}"), str::from_utf8) >>
tag!("}") >>
(Exp::Func {
name: name,
})
)
);
named!(pub exps<&[u8], Vec<Exp>>,
many0!(
alt!(func | literal)
)
);
pub fn parse(input: &str) -> Result<Vec<Exp>, Error> {
match exps(input.as_bytes()) {
IResult::Done(_, exps) => Ok(exps),
_ => Err(ErrorKind::Parse.into()),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_literal() {
assert_eq!(
literal(b"testing"),
IResult::Done(&b""[..], Exp::Literal("testing"))
);
}
#[test]
fn parse_func() {
assert_eq!(
func(b"%{test}"),
IResult::Done(&b""[..], Exp::Func { name: "test" })
);
}
#[test]
fn parse_exps() {
assert_eq!(
exps(b"%{test}literal%{test2}haha"),
IResult::Done(
&b""[..],
vec![
Exp::Func { name: "test" },
Exp::Literal("literal"),
Exp::Func { name: "test2" },
Exp::Literal("haha"),
],
)
);
assert_eq!(
exps(b"haha%{test}%{test2}lala"),
IResult::Done(
&b""[..],
vec![
Exp::Literal("haha"),
Exp::Func { name: "test" },
Exp::Func { name: "test2" },
Exp::Literal("lala"),
],
)
);
}
}