diff --git a/src/syntax/timestamp.rs b/src/syntax/timestamp.rs
index 63c673a..7626153 100644
--- a/src/syntax/timestamp.rs
+++ b/src/syntax/timestamp.rs
@@ -1,7 +1,7 @@
use nom::{
- bytes::complete::{take, take_till, take_while},
+ bytes::complete::{take_till, take_while1, take_while_m_n},
character::complete::{space0, space1},
- combinator::{map, opt, verify},
+ combinator::{map, opt},
sequence::tuple,
IResult,
};
@@ -44,48 +44,47 @@ pub fn timestamp_diary_node(input: Input) -> IResult {
crate::lossless_parser!(parser, input)
}
-fn is_digit_str(s: &Input) -> bool {
- s.as_str().bytes().all(|u| u.is_ascii_digit())
-}
-
-fn date(i: Input) -> IResult {
+fn date(i: Input) -> IResult {
map(
tuple((
- verify(take(4usize), is_digit_str),
+ take_while_m_n(4, 4, |c: char| c.is_ascii_digit()),
minus_token,
- verify(take(2usize), is_digit_str),
+ take_while_m_n(2, 2, |c: char| c.is_ascii_digit()),
minus_token,
- verify(take(2usize), is_digit_str),
- space1,
- take_while(|c: char| {
- !c.is_ascii_whitespace()
- && !c.is_ascii_digit()
- && c != '+'
- && c != '-'
- && c != ']'
- && c != '>'
- }),
+ take_while_m_n(2, 2, |c: char| c.is_ascii_digit()),
)),
- |(year, minus, month, minus_, day, ws, dayname)| {
+ |(year, minus, month, minus_, day)| {
[
year.token(TIMESTAMP_YEAR),
minus,
month.token(TIMESTAMP_MONTH),
minus_,
day.token(TIMESTAMP_DAY),
- ws.ws_token(),
- dayname.token(TIMESTAMP_DAYNAME),
]
},
)(i)
}
+fn dayname(i: Input) -> IResult {
+ map(
+ take_while1(|c: char| {
+ !c.is_ascii_whitespace()
+ && !c.is_ascii_digit()
+ && c != '+'
+ && c != '-'
+ && c != ']'
+ && c != '>'
+ }),
+ |i: Input| i.token(TIMESTAMP_DAYNAME),
+ )(i)
+}
+
fn time(i: Input) -> IResult {
map(
tuple((
- verify(take(2usize), is_digit_str),
+ take_while_m_n(2, 2, |c: char| c.is_ascii_digit()),
colon_token,
- verify(take(2usize), is_digit_str),
+ take_while_m_n(2, 2, |c: char| c.is_ascii_digit()),
)),
|(hour, colon, minute)| {
[
@@ -97,15 +96,25 @@ fn time(i: Input) -> IResult {
)(i)
}
-fn timestamp_active_node_base(input: Input) -> IResult {
- let (input, l_angle) = l_angle_token(input)?;
+fn timestamp_node_base(
+ input: Input,
+ l_parser: impl Fn(Input) -> IResult,
+ r_parser: impl Fn(Input) -> IResult,
+) -> IResult, ()> {
+ let (input, l_angle) = l_parser(input)?;
let (input, start_date) = date(input)?;
+ let (input, start_dayname) = opt(tuple((space1, dayname)))(input)?;
let (input, start_time) = opt(tuple((space1, time)))(input)?;
let mut b = NodeBuilder::new();
b.push(l_angle);
b.children.extend(start_date);
+ if let Some((ws, dayname)) = start_dayname {
+ b.push(ws.ws_token());
+ b.push(dayname);
+ }
+
if input.as_str().starts_with('-') {
let (ws, start_time) = match start_time {
Some(start_time) => start_time,
@@ -116,7 +125,7 @@ fn timestamp_active_node_base(input: Input) -> IResult
let (input, end_time) = time(input)?;
let (input, space) = space0(input)?;
// TODO: delay-or-repeater
- let (input, r_angle) = r_angle_token(input)?;
+ let (input, r_angle) = r_parser(input)?;
b.ws(ws);
b.children.extend(start_time);
@@ -125,11 +134,11 @@ fn timestamp_active_node_base(input: Input) -> IResult
b.ws(space);
b.push(r_angle);
- return Ok((input, b.finish(TIMESTAMP_ACTIVE)));
+ return Ok((input, b.children));
}
let (input, space) = space0(input)?;
- let (input, r_angle) = r_angle_token(input)?;
+ let (input, r_angle) = r_parser(input)?;
if let Some((ws, start_time)) = start_time {
b.ws(ws);
@@ -139,18 +148,22 @@ fn timestamp_active_node_base(input: Input) -> IResult
b.ws(space);
b.push(r_angle);
- if input.as_str().starts_with("--<") {
+ if input.as_str().starts_with("--") {
let (input, minus2) = minus2_token(input)?;
- let (input, l_angle) = l_angle_token(input)?;
+ let (input, l_angle) = l_parser(input)?;
let (input, end_date) = date(input)?;
+ let (input, end_dayname) = opt(tuple((space1, dayname)))(input)?;
let (input, end_time) = opt(tuple((space1, time)))(input)?;
let (input, space_) = space0(input)?;
// TODO: delay-or-repeater
- let (input, r_angle) = r_angle_token(input)?;
+ let (input, r_angle) = r_parser(input)?;
b.children.extend([minus2, l_angle]);
b.children.extend(end_date);
-
+ if let Some((ws, dayname)) = end_dayname {
+ b.push(ws.ws_token());
+ b.push(dayname);
+ }
if let Some((ws, end_time)) = end_time {
b.ws(ws);
b.children.extend(end_time);
@@ -159,88 +172,28 @@ fn timestamp_active_node_base(input: Input) -> IResult
b.ws(space_);
b.push(r_angle);
- Ok((input, b.finish(TIMESTAMP_ACTIVE)))
+ Ok((input, b.children))
} else {
- Ok((input, b.finish(TIMESTAMP_ACTIVE)))
- }
-}
-
-fn timestamp_inactive_node_base(input: Input) -> IResult {
- let (input, l_bracket) = l_bracket_token(input)?;
- let (input, start_date) = date(input)?;
- let (input, start_time) = opt(tuple((space1, time)))(input)?;
-
- let mut b = NodeBuilder::new();
- b.push(l_bracket);
- b.children.extend(start_date);
-
- if input.s.starts_with('-') {
- let (ws, start_time) = match start_time {
- Some(start_time) => start_time,
- None => return Err(nom::Err::Error(())),
- };
-
- let (input, minus) = minus_token(input)?;
- let (input, end_time) = time(input)?;
- let (input, space) = space0(input)?;
- // TODO: delay-or-repeater
- let (input, r_bracket) = r_bracket_token(input)?;
-
- b.ws(ws);
- b.children.extend(start_time);
- b.push(minus);
- b.children.extend(end_time);
- b.ws(space);
- b.push(r_bracket);
-
- return Ok((input, b.finish(TIMESTAMP_INACTIVE)));
- }
-
- let (input, space) = space0(input)?;
- let (input, r_bracket) = r_bracket_token(input)?;
-
- if let Some((ws, start_time)) = start_time {
- b.ws(ws);
- b.children.extend(start_time);
- }
-
- b.ws(space);
- b.push(r_bracket);
-
- if input.s.starts_with("--[") {
- let (input, minus2) = minus2_token(input)?;
- let (input, l_bracket) = l_bracket_token(input)?;
- let (input, end_date) = date(input)?;
- let (input, end_time) = opt(tuple((space1, time)))(input)?;
- let (input, space_) = space0(input)?;
- // TODO: delay-or-repeater
- let (input, r_bracket) = r_bracket_token(input)?;
-
- b.children.extend([minus2, l_bracket]);
- b.children.extend(end_date);
-
- if let Some((ws, end_time)) = end_time {
- b.ws(ws);
- b.children.extend(end_time);
- }
-
- b.ws(space_);
- b.push(r_bracket);
-
- Ok((input, b.finish(TIMESTAMP_INACTIVE)))
- } else {
- Ok((input, b.finish(TIMESTAMP_INACTIVE)))
+ Ok((input, b.children))
}
}
#[tracing::instrument(level = "debug", skip(input), fields(input = input.s))]
pub fn timestamp_active_node(input: Input) -> IResult {
- crate::lossless_parser!(timestamp_active_node_base, input)
+ fn parser(input: Input) -> IResult {
+ let (input, children) = timestamp_node_base(input, l_angle_token, r_angle_token)?;
+ Ok((input, node(TIMESTAMP_ACTIVE, children)))
+ }
+ crate::lossless_parser!(parser, input)
}
#[tracing::instrument(level = "debug", skip(input), fields(input = input.s))]
pub fn timestamp_inactive_node(input: Input) -> IResult {
- crate::lossless_parser!(timestamp_inactive_node_base, input)
+ fn parser(input: Input) -> IResult {
+ let (input, children) = timestamp_node_base(input, l_bracket_token, r_bracket_token)?;
+ Ok((input, node(TIMESTAMP_INACTIVE, children)))
+ }
+ crate::lossless_parser!(parser, input)
}
#[test]
@@ -249,6 +202,18 @@ fn parse() {
let to_timestamp = to_ast::(timestamp_inactive_node);
+ to_timestamp("[2003-09-16]");
+ to_timestamp("[2003-09-16 09:09]");
+ to_timestamp("[2003-09-16 Tue]");
+ to_timestamp("[2003-09-16 Tue 09:09]");
+ to_timestamp("[2003-09-16]--[2003-09-16]");
+ to_timestamp("[2003-09-16 09:09]--[2003-09-16 09:09]");
+ to_timestamp("[2003-09-16]--[2003-09-16 09:09]");
+ to_timestamp("[2003-09-16 Tue]--[2003-09-16 Tue]");
+ to_timestamp("[2003-09-16 Tue 09:09]--[2003-09-16 Tue 09:09]");
+ to_timestamp("[2003-09-16 Tue 09:09-09:09]");
+ to_timestamp("[2003-09-16 09:09-09:09]");
+
let ts = to_timestamp("[2003-09-16 Tue]");
assert!(!ts.is_range());
insta::assert_debug_snapshot!(