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
#[warn(clippy::pedantic)]
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Header {
pub info: Vec<Elem>,
pub players: Option<(PlayerAndPoint, PlayerAndPoint)>,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct PlayerAndPoint {
pub player_name: String,
pub point: i64,
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub enum Elem {
Value(String),
KeyedValue(String, String),
}
use nom::combinator::opt;
use nom::error::{Error, ErrorKind};
use nom::multi::many0;
use nom::multi::many_m_n;
use nom::Err;
use nom::IResult;
fn elem_parser(s: &str) -> IResult<&str, Elem> {
let (no_used, in_string) = super::parse_braced_string(s, '{', '}')?;
Ok((no_used, {
let mut splitter = in_string.splitn(2, ':');
let first = splitter.next().unwrap();
let second = splitter.next();
match (first, second) {
("", Some(val)) | (val, None) => Elem::Value(val.to_owned()),
(key, Some(value)) => Elem::KeyedValue(key.to_owned(), value.to_owned()),
}
}))
}
use super::skip_spaces_and_newlines;
fn player_and_point_parser(s: &str) -> IResult<&str, (String, Option<i64>)> {
let (no_used, player_name) = super::parse_braced_string(s, '[', ']')?;
let (no_used, _) = skip_spaces_and_newlines(no_used)?;
let (no_used, opt_num) = opt(super::parse_numeral)(no_used)?;
let (no_used, _) = skip_spaces_and_newlines(no_used)?;
Ok((no_used, (player_name.to_owned(), opt_num)))
}
pub fn parse(input: &str) -> IResult<&str, Header> {
let (no_used, _) = skip_spaces_and_newlines(input)?;
let (no_used, info) = many0(elem_parser)(no_used)?;
let (no_used, vec2) = many_m_n(0, 2, player_and_point_parser)(no_used)?;
let players = match vec2.as_slice() {
[] => None,
[q, r] => {
let (n1, p1) = q.clone();
let (n2, p2) = r.clone();
let (p1, p2) = match (p1, p2) {
(Some(b), Some(d)) => (b, d),
(Some(b), None) => (b, 40 - b),
(None, Some(d)) => (40 - d, d),
(None, None) => (20, 20),
};
Some((
PlayerAndPoint {
player_name: n1,
point: p1,
},
PlayerAndPoint {
player_name: n2,
point: p2,
},
))
}
_ => return Err(Err::Error(Error::new(no_used, ErrorKind::Verify))),
};
Ok((no_used, Header { info, players }))
}
#[cfg(test)]
mod tests_;