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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
pub use crate::core::complete::*;
pub use crate::core::*;
pub fn read_line(s: &str) -> IResult<&str, &str> {
use nom::combinator::recognize;
recognize(pair(take_until("\n"), tag("\n")))(s)
}
#[test]
fn test_read_line() {
let txt = "first line\nsecond line\r\nthird line\n";
let (rest, line) = read_line(txt).unwrap();
assert_eq!(line, "first line\n");
let (rest, line) = read_line(rest).unwrap();
assert_eq!(line, "second line\r\n");
let (rest, line) = read_line(rest).unwrap();
assert_eq!(line, "third line\n");
assert_eq!(rest, "");
}
pub fn read_until_eol(s: &str) -> IResult<&str, &str> {
use nom::character::complete::line_ending;
use nom::character::complete::not_line_ending;
nom::sequence::terminated(not_line_ending, line_ending)(s)
}
pub fn eol(s: &str) -> IResult<&str, &str> {
use nom::character::complete::line_ending;
nom::sequence::terminated(space0, line_ending)(s)
}
pub fn not_space(s: &str) -> IResult<&str, &str> {
is_not(" \t\r\n")(s)
}
pub fn unsigned_digit(s: &str) -> IResult<&str, usize> {
map(digit1, |s: &str| s.parse().unwrap())(s)
}
pub fn signed_digit(s: &str) -> IResult<&str, isize> {
use nom::combinator::recognize;
let sign = opt(alt((tag("-"), tag("+"))));
map_res(recognize(pair(sign, digit1)), |x: &str| x.parse::<isize>())(s)
}
#[test]
fn test_signed_digit() {
let (_, x) = signed_digit("-123").expect("signed digit, minus");
assert_eq!(x, -123);
let (_, x) = signed_digit("123").expect("signed digit, normal");
assert_eq!(x, 123);
let (_, x) = signed_digit("+123").expect("signed digit, plus");
assert_eq!(x, 123);
}
pub fn read_usize(s: &str) -> IResult<&str, usize> {
use nom::character::complete::line_ending;
let p = nom::sequence::delimited(space0, unsigned_digit, space0);
nom::sequence::terminated(p, line_ending)(s)
}
#[test]
fn test_numbers() {
let s = "12x";
let (r, n) = unsigned_digit(s).unwrap();
assert_eq!(n, 12);
assert_eq!(r, "x");
let (r, n) = read_usize(" 12 \n").unwrap();
assert_eq!(n, 12);
assert_eq!(r, "");
}
pub fn xyz_array(s: &str) -> IResult<&str, [f64; 3]> {
let (r, (x, _, y, _, z)) = tuple((double, space1, double, space1, double))(s)?;
Ok((r, [x, y, z]))
}
pub fn jump_to<'a>(token: &'a str) -> impl Fn(&'a str) -> IResult<&str, ()> {
map(pair(take_until(token), tag(token)), |_| ())
}
#[test]
fn test_take() {
let x = "xxbcc aa cc";
let (r, _) = jump_to("aa")(x).unwrap();
assert_eq!(r, " cc");
}
pub fn take_s<'a>(n: usize) -> impl Fn(&'a str) -> IResult<&'a str, &'a str> {
take(n)
}