Get rid of nom
This commit is contained in:
parent
afa708960c
commit
2ef7fd0f5e
4 changed files with 0 additions and 219 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
|
@ -27,29 +27,6 @@ version = "0.2.106"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
|
@ -85,15 +62,8 @@ name = "today"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
|
|
|
|||
|
|
@ -5,4 +5,3 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
chrono = "0.4.19"
|
||||
nom = "7.1.0"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
mod commands;
|
||||
mod parse;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
|
|
|||
187
src/parse.rs
187
src/parse.rs
|
|
@ -1,187 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use chrono::{Duration, NaiveDate, NaiveTime};
|
||||
use nom::branch::Alt;
|
||||
use nom::bytes::complete::{take_while1, take_while_m_n};
|
||||
use nom::character::complete::{char, digit1, newline};
|
||||
use nom::combinator::{eof, fail, map_opt, map_res, opt, value};
|
||||
use nom::sequence::terminated;
|
||||
use nom::{IResult, Parser};
|
||||
|
||||
use crate::commands::Delta;
|
||||
|
||||
fn line_ending(i: &str) -> IResult<&str, ()> {
|
||||
(newline.map(|_| ()), eof.map(|_| ())).choice(i)
|
||||
}
|
||||
|
||||
fn title(i: &str) -> IResult<&str, &str> {
|
||||
terminated(take_while1(|c| c != '\n'), line_ending)(i)
|
||||
}
|
||||
|
||||
fn number<N: FromStr>(i: &str) -> IResult<&str, N> {
|
||||
map_res(digit1, str::parse)(i)
|
||||
}
|
||||
|
||||
fn fixed_width_number<N: FromStr, const W: usize>(i: &str) -> IResult<&str, N> {
|
||||
map_res(
|
||||
take_while_m_n(W, W, |c: char| c.is_ascii_digit()),
|
||||
str::parse,
|
||||
)(i)
|
||||
}
|
||||
|
||||
fn date(i: &str) -> IResult<&str, NaiveDate> {
|
||||
let (i, year) = number::<i32>(i)?;
|
||||
let (i, _) = char('-')(i)?;
|
||||
let (i, month) = fixed_width_number::<u32, 2>(i)?;
|
||||
let (i, _) = char('-')(i)?;
|
||||
let (i, day) = fixed_width_number::<u32, 2>(i)?;
|
||||
match NaiveDate::from_ymd_opt(year, month, day) {
|
||||
Some(date) => Ok((i, date)),
|
||||
None => fail(i),
|
||||
}
|
||||
}
|
||||
|
||||
fn time(i: &str) -> IResult<&str, NaiveTime> {
|
||||
let (i, hour) = fixed_width_number::<u32, 2>(i)?;
|
||||
let (i, _) = char(':')(i)?;
|
||||
let (i, min) = fixed_width_number::<u32, 2>(i)?;
|
||||
if hour < 24 && min < 60 {
|
||||
Ok((i, NaiveTime::from_hms(hour, min, 0)))
|
||||
} else {
|
||||
fail(i)
|
||||
}
|
||||
}
|
||||
|
||||
fn single_delta<const C: char>(i: &str) -> IResult<&str, i32> {
|
||||
let (i, sign) = (value(1, char('+')), value(-1, char('-'))).choice(i)?;
|
||||
let (i, amount) = opt(number::<i32>)(i)?;
|
||||
let amount = amount.unwrap_or(1);
|
||||
Ok((i, sign * amount))
|
||||
}
|
||||
|
||||
fn opt_single_delta<const C: char>(i: &str) -> IResult<&str, i32> {
|
||||
let (i, delta) = opt(single_delta::<C>)(i)?;
|
||||
let delta = delta.unwrap_or(0);
|
||||
Ok((i, delta))
|
||||
}
|
||||
|
||||
fn delta(i: &str) -> IResult<&str, Delta> {
|
||||
// TODO Require at least one field?
|
||||
let (i, years) = opt_single_delta::<'y'>(i)?;
|
||||
let (i, months) = opt_single_delta::<'m'>(i)?;
|
||||
let (i, weeks) = opt_single_delta::<'w'>(i)?;
|
||||
let (i, days) = opt_single_delta::<'d'>(i)?;
|
||||
let (i, hours) = opt_single_delta::<'h'>(i)?;
|
||||
let (i, minutes) = opt_single_delta::<'m'>(i)?;
|
||||
Ok((
|
||||
i,
|
||||
Delta {
|
||||
years,
|
||||
months,
|
||||
weeks,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_line_ending() {
|
||||
assert_eq!(line_ending("\n"), Ok(("", ())));
|
||||
assert_eq!(line_ending("\nbla"), Ok(("bla", ())));
|
||||
assert_eq!(line_ending("\n\n"), Ok(("\n", ())));
|
||||
assert_eq!(line_ending(""), Ok(("", ())));
|
||||
|
||||
assert!(line_ending("bla").is_err());
|
||||
assert!(line_ending("\r").is_err());
|
||||
assert!(line_ending("\r\n").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_title() {
|
||||
assert_eq!(title("foo bar\nbaz"), Ok(("baz", "foo bar")));
|
||||
assert_eq!(title("foo bar\n"), Ok(("", "foo bar")));
|
||||
assert_eq!(title("foo bar"), Ok(("", "foo bar")));
|
||||
assert_eq!(title(" \nbla"), Ok(("bla", " ")));
|
||||
assert_eq!(
|
||||
title("!\"§$%&/()'<>[]{}_:;.,-=\nbla"),
|
||||
Ok(("bla", "!\"§$%&/()'<>[]{}_:;.,-="))
|
||||
);
|
||||
|
||||
assert!(title("\nxyz").is_err());
|
||||
assert!(title("").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_number() {
|
||||
assert_eq!(number::<u32>("012345abc"), Ok(("abc", 12345)));
|
||||
assert_eq!(number::<u8>("255"), Ok(("", 255)));
|
||||
assert_eq!(number::<i64>("0x3f"), Ok(("x3f", 0)));
|
||||
|
||||
assert!(number::<u8>("256").is_err());
|
||||
assert!(number::<i32>("xyz").is_err());
|
||||
assert!(number::<i8>("").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fixed_width_number() {
|
||||
assert_eq!(
|
||||
fixed_width_number::<u32, 2>("012345abc"),
|
||||
Ok(("2345abc", 1))
|
||||
);
|
||||
assert_eq!(
|
||||
fixed_width_number::<u32, 3>("012345abc"),
|
||||
Ok(("345abc", 12))
|
||||
);
|
||||
assert_eq!(
|
||||
fixed_width_number::<u32, 6>("012345abc"),
|
||||
Ok(("abc", 12345))
|
||||
);
|
||||
|
||||
assert!(fixed_width_number::<u8, 0>("012345abc").is_err());
|
||||
assert!(fixed_width_number::<u8, 6>("012345abc").is_err());
|
||||
assert!(fixed_width_number::<u8, 3>("14x").is_err());
|
||||
assert!(fixed_width_number::<i8, 4>("").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date() {
|
||||
assert_eq!(
|
||||
date("2021-11-06"),
|
||||
Ok(("", NaiveDate::from_ymd(2021, 11, 6)))
|
||||
);
|
||||
assert_eq!(
|
||||
date("2021-11-0678"),
|
||||
Ok(("78", NaiveDate::from_ymd(2021, 11, 6)))
|
||||
);
|
||||
assert_eq!(date("0-01-01"), Ok(("", NaiveDate::from_ymd(0, 1, 1))));
|
||||
assert_eq!(
|
||||
date("2020-02-29"),
|
||||
Ok(("", NaiveDate::from_ymd(2020, 2, 29)))
|
||||
);
|
||||
|
||||
assert!(date("2021-11-6").is_err());
|
||||
assert!(date("0000-00-00").is_err());
|
||||
assert!(date("2021-02-29").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_time() {
|
||||
assert_eq!(time("12:34"), Ok(("", NaiveTime::from_hms(12, 34, 0))));
|
||||
assert_eq!(time("00:00"), Ok(("", NaiveTime::from_hms(0, 0, 0))));
|
||||
assert_eq!(time("23:59"), Ok(("", NaiveTime::from_hms(23, 59, 0))));
|
||||
assert_eq!(time("02:04:06"), Ok((":06", NaiveTime::from_hms(2, 4, 0))));
|
||||
|
||||
assert!(time("abc").is_err());
|
||||
assert!(time("24:23").is_err());
|
||||
assert!(time("12:60").is_err());
|
||||
assert!(time("12-34").is_err());
|
||||
assert!(time("2:34").is_err());
|
||||
assert!(time("12:3").is_err());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue