summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-10-27 20:37:43 +0200
committerMatthias Beyer <mail@beyermatthias.de>2017-10-28 18:04:54 +0200
commitac01c4a224f9b2db08248c45170bea202e08ada9 (patch)
tree932e58efb9cf91eee7e6493fb362c91eddb8bed6
parent1ac1641dc5a0e54e0362081c2113427f2e35a8cc (diff)
Initial bootstrapping of nom-based parser
-rw-r--r--Cargo.toml7
-rw-r--r--build.rs6
-rw-r--r--src/grammar.rustpeg2
-rw-r--r--src/lib.rs3
-rw-r--r--src/parser.rs177
5 files changed, 175 insertions, 20 deletions
diff --git a/Cargo.toml b/Cargo.toml
index bc8f016..c0a4c1a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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;
-
diff --git a/src/lib.rs b/src/lib.rs
index 8f7fed9..d39493a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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>);
+