diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2017-10-27 20:37:43 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2017-10-28 18:04:54 +0200 |
commit | ac01c4a224f9b2db08248c45170bea202e08ada9 (patch) | |
tree | 932e58efb9cf91eee7e6493fb362c91eddb8bed6 | |
parent | 1ac1641dc5a0e54e0362081c2113427f2e35a8cc (diff) |
Initial bootstrapping of nom-based parser
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | build.rs | 6 | ||||
-rw-r--r-- | src/grammar.rustpeg | 2 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/parser.rs | 177 |
5 files changed, 175 insertions, 20 deletions
@@ -12,17 +12,14 @@ license = "MPL-2.0" repository = "https://github.com/matthiasbeyer/kairos" -build = "build.rs" - [dependencies] chrono = "0.4" error-chain = "0.10" +nom = "3.2" +iso8601 = { git = "https://github.com/matthiasbeyer/iso8601", branch = "update-nom" } filters = { version = "0.1.1", optional = true } -[build-dependencies] -peg = { version = "0.5" } - [dev-dependencies] env_logger = "0.4" log = "0.3" diff --git a/build.rs b/build.rs deleted file mode 100644 index af09e85..0000000 --- a/build.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern crate peg; - -fn main() { - peg::cargo_build("src/grammar.rustpeg"); -} - diff --git a/src/grammar.rustpeg b/src/grammar.rustpeg deleted file mode 100644 index 36a3fa0..0000000 --- a/src/grammar.rustpeg +++ /dev/null @@ -1,2 +0,0 @@ -use timetype::TimeType; - @@ -3,7 +3,8 @@ extern crate error_chain; extern crate chrono; #[macro_use] -extern crate peg; +extern crate nom; +extern crate iso8601; #[cfg(feature = "with-filters")] extern crate filters; diff --git a/src/parser.rs b/src/parser.rs index 4820668..d50cbec 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -29,13 +29,178 @@ //! //! ## User-facing syntax nodes //! -//! AmountExp = <Amount> (<Operator> <AmountExp>)? -//! ExactDate = "today" | "yesterday" | "tomorrow" | <Iso8601> -//! Date = <ExactDate> (<Operator> <AmountExp>)? -//! Iterator = <Date> <Iterspec> ("until" <ExactDate> | <number> "times")? +//! AmountExpr = <Amount> (<Operator> <AmountExpr>)? +//! ExactDate = "today" | "yesterday" | "tomorrow" | <Iso8601> +//! Date = <ExactDate> (<Operator> <AmountExpr>)? +//! Iterator = <Date> <Iterspec> ("until" <ExactDate> | <number> "times")? //! -mod grammar { - include!(concat!(env!("OUT_DIR"), "/grammar.rs")); +use nom::{IResult, space, alpha, alphanumeric, digit}; +use std::str; +use std::str::FromStr; + +named!(integer<i64>, alt!( + map_res!( + map_res!( + ws!(digit), + str::from_utf8 + ), + FromStr::from_str + ) +)); + +named!(unit_parser<Unit>, alt!( + tag!("second") => { |_| Unit::Second } | + tag!("seconds") => { |_| Unit::Second } | + tag!("sec") => { |_| Unit::Second } | + tag!("secs") => { |_| Unit::Second } | + tag!("s") => { |_| Unit::Second } | + tag!("minute") => { |_| Unit::Minute } | + tag!("minutes") => { |_| Unit::Minute } | + tag!("min") => { |_| Unit::Minute } | + tag!("mins") => { |_| Unit::Minute } | + tag!("hour") => { |_| Unit::Hour } | + tag!("hours") => { |_| Unit::Hour } | + tag!("hr") => { |_| Unit::Hour } | + tag!("hrs") => { |_| Unit::Hour } | + tag!("day") => { |_| Unit::Day } | + tag!("days") => { |_| Unit::Day } | + tag!("d") => { |_| Unit::Day } | + tag!("week") => { |_| Unit::Week } | + tag!("weeks") => { |_| Unit::Week } | + tag!("w") => { |_| Unit::Week } | + tag!("month") => { |_| Unit::Month } | + tag!("months") => { |_| Unit::Month } | + tag!("year") => { |_| Unit::Year } | + tag!("years") => { |_| Unit::Year } | + tag!("yrs") => { |_| Unit::Year } +)); + +pub enum Unit { + Second, + Minute, + Hour, + Day, + Week, + Month, + Year, +} + +named!(operator_parser<Operator>, alt!( + tag!("+") => { |_| Operator::Plus } | + tag!("-") => { |_| Operator::Minus } +)); + +pub enum Operator { + Plus, + Minus, +} + +named!(amount_parser<Amount>, do_parse!( + number: integer >> + unit : unit_parser >> + (Amount(number, unit)) +)); + +pub struct Amount(i64, Unit); + +named!(iter_spec<Iterspec>, alt!( + tag!("secondly") => { |_| Iterspec::Secondly } | + tag!("minutely") => { |_| Iterspec::Minutely } | + tag!("hourly") => { |_| Iterspec::Hourly } | + tag!("daily") => { |_| Iterspec::Daily } | + tag!("weekly") => { |_| Iterspec::Weekly } | + tag!("monthly") => { |_| Iterspec::Monthly } | + tag!("yearly") => { |_| Iterspec::Yearly } | + do_parse!( + tag!("every") >> + number:integer >> + unit:unit_parser >> + (Iterspec::Every(number, unit)) + ) +)); + +pub enum Iterspec { + Secondly, + Minutely, + Hourly, + Daily, + Weekly, + Monthly, + Yearly, + Every(i64, Unit), +} + +named!(amount_expr<AmountExpr>, do_parse!( + amount:amount_parser >> + o: opt!(do_parse!(op:operator_parser >> amexp:amount_expr >> ((op, Box::new(amexp))))) >> + (AmountExpr { amount: amount, next: o, }) +)); + +pub struct AmountExpr { + amount: Amount, + next: Option<(Operator, Box<AmountExpr>)>, +} + +impl AmountExpr { + fn new(amount: Amount, next: Option<(Operator, Box<AmountExpr>)>) -> AmountExpr { + AmountExpr { + amount: amount, + next: next + } + } } +use iso8601::parsers::parse_date; +use iso8601::parsers::parse_datetime; +named!(exact_date_parser<ExactDate>, alt!( + tag!("today") => { |_| ExactDate::Today } | + tag!("yesterday") => { |_| ExactDate::Yesterday } | + tag!("tomorrow") => { |_| ExactDate::Tomorrow } | + do_parse!(d: parse_date >> (ExactDate::Iso8601Date(d))) | + do_parse!(d: parse_datetime >> (ExactDate::Iso8601DateTime(d))) +)); + +pub enum ExactDate { + Today, + Yesterday, + Tomorrow, + Iso8601Date(::iso8601::Date), + Iso8601DateTime(::iso8601::DateTime) +} + +named!(date<Date>, do_parse!( + exact:exact_date_parser >> + o: opt!(do_parse!(op:operator_parser >> a:amount_expr >> (op, a))) >> + (Date(exact, o)) +)); + +pub struct Date(ExactDate, Option<(Operator, AmountExpr)>); + +named!(until_spec<UntilSpec>, alt!( + do_parse!( + tag!("until") >> + exact: exact_date_parser >> + (UntilSpec::Exact(exact)) + ) | + do_parse!( + num: integer >> + tag!("times") >> + (UntilSpec::Times(num)) + ) +)); + +pub enum UntilSpec { + Exact(ExactDate), + Times(i64) +} + +named!(iterator<Iterator>, do_parse!( + d: date >> + spec: iter_spec >> + until: opt!(until_spec) >> + (Iterator(d, spec, until)) +)); + +pub struct Iterator(Date, Iterspec, Option<UntilSpec>); + |