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
87
88
89
90
91
92
93
94
95
96
97
use combine::easy::{Errors, Error};
use tokenizer::Token;
use position::Pos;
pub type InternalError<'a> = Errors<Token<'a>, Token<'a>, Pos>;
#[derive(Fail, Debug)]
#[fail(display="parse error: {}", _0)]
pub struct ParseError(Errors<String, String, Pos>);
#[cfg(not(feature="fuzzy_errors"))]
impl<'a> From<InternalError<'a>> for ParseError {
fn from(e: InternalError<'a>) -> ParseError {
ParseError(e
.map_token(|t| t.value.to_string())
.map_range(|t| t.value.to_string()))
}
}
fn convert(error: Error<Token, Token>) -> Error<String, String> {
error
.map_token(|t| t.value.to_string())
.map_range(|t| t.value.to_string())
}
#[cfg(feature="fuzzy_errors")]
impl<'a> From<InternalError<'a>> for ParseError {
fn from(e: InternalError<'a>) -> ParseError {
use strsim::jaro_winkler;
use combine::easy::{Info};
let mut error_buf = Vec::new();
let mut expected_buf = Vec::new();
let mut unexpected = None;
for item in e.errors {
match item {
Error::Expected(info) => {
expected_buf.push(info);
continue;
}
Error::Unexpected(ref val) => {
unexpected = Some(val.to_string());
}
_ => {}
}
error_buf.push(convert(item));
}
if let Some(unexpected) = unexpected {
if expected_buf.len() > 3 {
let mut close = Vec::new();
for item in &expected_buf {
match item {
Info::Borrowed(item) => {
let conf = jaro_winkler(&unexpected, item);
if conf > 0.8 {
close.push((item, conf));
}
}
_ => {
}
}
}
close.sort_by_key(|&(_, ref x)| (10000. - 10000. * x) as u32);
close.truncate(3);
for (item, _) in &close {
error_buf.push(convert(Error::Expected(
Info::Borrowed(item))));
}
if close.len() < expected_buf.len() {
error_buf.push(Error::Expected(Info::Owned(format!(
"one of {} options",
expected_buf.len() - close.len(),
))));
}
} else {
for e in expected_buf {
error_buf.push(convert(Error::Expected(e)));
}
}
} else {
for e in expected_buf {
error_buf.push(convert(Error::Expected(e)));
}
}
return ParseError(Errors { position: e.position, errors: error_buf })
}
}