summaryrefslogtreecommitdiffstats
path: root/src/parser/mod.rs
blob: c6483b4c3d166aa7790e3d74464f20e6dc9821f1 (plain)
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
//! The definition of the "kairos" syntax, for parsing user input into TimeType objects
//!
//! The syntax itself is described in the grammar.rustpeg file.
//! Here goes a documentation on the syntax
//!
//! # Syntax
//!
//! ## Units
//!
//! UnitSec   = "second" | "seconds" | "sec" | "secs" | "s"
//! UnitMin   = "minute" | "minutes" | "min" | "mins"
//! UnitHr    = "hour"   | "hours"   | "hr" | "hrs"
//! UnitDay   = "day"    | "days"    | "d"
//! UnitWeek  = "week"   | "weeks"   | "w"
//! UnitMonth = "month"  | "months"  |
//! UnitYear  = "year"   | "years"   | "yrs"
//! Unit      = UnitSec | UnitMin | UnitHr | UnitDay | UnitWeek | UnitMonth | UnitYear
//!
//! ## Operators
//!
//! Operator  = "+" | "-"
//!
//! ## Intermediate syntax nodes
//!
//! Amount    = "<Number><Unit>"
//!
//! TextIterSpec = "secondly" | "minutely" | "hourly" | "daily" | "weekly" | "monthly" | "yearly"
//! Iterspec     = TextIterSpec | "every" <Number><Unit>
//!
//! ## User-facing syntax nodes
//!
//! AmountExpr = <Amount> (<Operator> <AmountExpr>)?
//! ExactDate  = "today" | "yesterday" | "tomorrow" | <Iso8601>
//! Date       = <ExactDate> (<Operator> <AmountExpr>)?
//! Iterator   = <Date> <Iterspec> ("until" <ExactDate> | <number> "times")?
//!
//! # Warning
//!
//! This module is not intended for public use... it is still public, so you can use it, but you
//! should know that these interfaces are considered private and I will not follow semver and
//! update the minor or major semver numbers of the interface of this module changes.
//!
//! Be warned!
//!

use nom::Needed;
use nom::IResult;

mod timetype;
mod iterator;

use failure::Fallible as Result;
use error::ErrorKind as KEK;
use iter::Iter;
use timetype::IntoTimeType;
use parser::timetype::timetype;
use parser::iterator::iterator;

pub enum Parsed {
    Iterator(Result<::parser::iterator::UserIterator<Iter>>),
    TimeType(::timetype::TimeType)
}

named!(do_parse<Result<Parsed>>, alt_complete!(
    do_parse!(it: iterator >> (Ok(Parsed::Iterator(it.into_user_iterator())))) |
    do_parse!(tt: timetype >> (tt.into_timetype().map(Parsed::TimeType)))
));

pub fn parse(s: &str) -> Result<Parsed> {
    match do_parse(s.as_bytes()) {
        IResult::Done(_, Ok(o))              => Ok(o),
        IResult::Done(_, Err(e))             => Err(e),
        IResult::Error(e)                    => Err(e).map_err(From::from),
        IResult::Incomplete(Needed::Unknown) => Err(KEK::UnknownParserError.into()),
        IResult::Incomplete(Needed::Size(_)) => Err(KEK::UnknownParserError.into()),

    }
}