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
74
75
76
77
78
79
80
81
82
83
84
85
86
use nom::{Err as NomErr, ErrorKind, IResult, Needed};
use std::error::Error;
use std::fmt;
use std::str::{from_utf8_unchecked};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParseError {
kind: ErrorKind,
info: String
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "error ({:?}): {}", self.kind, self.info)
}
}
impl Error for ParseError {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ParseResult<T> {
Ok(T),
Err(ParseError),
Incomplete(Needed)
}
pub fn parse<P, T>(source: &[u8], parser: P) -> ParseResult<T>
where P: FnOnce(&[u8]) -> IResult<&[u8], T> {
match parser(source) {
IResult::Done(i, x) => {
if i.is_empty() {
ParseResult::Ok(x)
} else {
let kind = ErrorKind::Custom(0);
let msg = unsafe { from_utf8_unchecked(i).to_owned() };
let info = msg.lines().next().unwrap_or("").to_owned();
ParseResult::Err(ParseError { kind, info })
}
},
IResult::Error(err) => match err {
NomErr::Code(k) => ParseResult::Err(ParseError { kind: k, info: String::new() }),
NomErr::Node(kind, trace) => {
let info = format!("{:#?}", trace);
ParseResult::Err(ParseError { kind, info })
},
NomErr::Position(kind, p) => {
let msg = unsafe { from_utf8_unchecked(p).to_owned() };
let info = msg.lines().next().unwrap_or("").to_owned();
ParseResult::Err(ParseError { kind, info })
},
NomErr::NodePosition(kind, p, trace) => {
let p_msg = unsafe { from_utf8_unchecked(p) };
let info = format!("{}: {:#?}", p_msg, trace);
ParseResult::Err(ParseError { kind, info })
}
},
IResult::Incomplete(n) => ParseResult::Incomplete(n)
}
}
pub fn parse_str<'a, I, P, T>(source: I, parser: P) -> ParseResult<T>
where I: Into<&'a str>,
P: FnOnce(&[u8]) -> IResult<&[u8], T> {
parse(source.into().as_bytes(), parser)
}