aboutsummaryrefslogtreecommitdiff
path: root/src/fexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/fexpr')
-rw-r--r--src/fexpr/grammar.lalrpop55
-rw-r--r--src/fexpr/mod.rs6
2 files changed, 57 insertions, 4 deletions
diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop
index 45f4fde..092407e 100644
--- a/src/fexpr/grammar.lalrpop
+++ b/src/fexpr/grammar.lalrpop
@@ -4,12 +4,16 @@ use super::{
FightOutcome,
filters,
PlayerClass,
+
+ DateProducer,
+ DurationProducer,
+ CountProducer,
};
use evtclib::Boss;
use std::collections::HashSet;
use lalrpop_util::ParseError;
-use chrono::{DateTime, Local, TimeZone, Utc, Weekday};
+use chrono::{DateTime, Local, TimeZone, Utc, Weekday, Duration};
use regex::{Regex, RegexBuilder};
grammar;
@@ -48,8 +52,12 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {
"-outcome" <Comma<FightOutcome>> => filters::log::outcome(<>),
"-weekday" <Comma<Weekday>> => filters::log::weekday(<>),
- "-before" <Date> => filters::log::before(<>),
- "-after" <Date> => filters::log::after(<>),
+ "-before" <Date> => filters::values::comparison(
+ filters::values::time(), filters::values::CompOp::Less, filters::values::constant(<>)
+ ),
+ "-after" <Date> => filters::values::comparison(
+ filters::values::time(), filters::values::CompOp::Greater, filters::values::constant(<>)
+ ),
"-log-before" <Date> => filters::log::log_before(<>),
"-log-after" <Date> => filters::log::log_after(<>),
@@ -68,6 +76,10 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {
"any" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>),
"exists" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>),
+ <Comparison<DateProducer>>,
+ <Comparison<DurationProducer>>,
+ <Comparison<CountProducer>>,
+
"(" <LogFilter> ")",
}
@@ -175,6 +187,22 @@ Date: DateTime<Utc> = {
.map(|d| d.with_timezone(&Utc)),
}
+Duration: Duration = {
+ duration => Duration::from_std(humantime::parse_duration(<>).unwrap()).unwrap(),
+}
+
+CompOp: filters::values::CompOp = {
+ "<" => filters::values::CompOp::Less,
+ "<=" => filters::values::CompOp::LessEqual,
+ "=" => filters::values::CompOp::Equal,
+ ">=" => filters::values::CompOp::GreaterEqual,
+ ">" => filters::values::CompOp::Greater,
+}
+
+Comparison<T>: Box<dyn filters::log::LogFilter> = {
+ <lhs:T> <op:CompOp> <rhs:T> => filters::values::comparison(lhs, op, rhs),
+}
+
Comma<T>: HashSet<T> = {
<v:(<T> ",")*> <e:T> => {
let mut result = v.into_iter().collect::<HashSet<_>>();
@@ -183,6 +211,22 @@ Comma<T>: HashSet<T> = {
},
}
+DateProducer: Box<dyn DateProducer> = {
+ <Date> => filters::values::constant(<>),
+ "-time" => filters::values::time(),
+}
+
+DurationProducer: Box<dyn DurationProducer> = {
+ <Duration> => filters::values::constant(<>),
+ "-duration" => filters::values::duration(),
+}
+
+CountProducer: Box<dyn CountProducer> = {
+ <integer> => filters::values::constant(<>.parse().unwrap()),
+ "count" "(" "player" ":" <PlayerFilter> ")" => filters::values::player_count(<>),
+ "count" "(" "player" ")" => filters::values::player_count(filters::constant(true)),
+}
+
match {
"player" => "player",
"not" => "not",
@@ -191,10 +235,13 @@ match {
"any" => "any",
"all" => "all",
"exists" => "exists",
+ "count" => "count",
r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d" => datetime,
r"\d\d\d\d-\d\d-\d\d" => date,
- r"[\w]+" => word,
+ r"((\d+m ?)?\d+s)|(\d+m)" => duration,
+ r"\d+" => integer,
+ r"[[:alpha:]][\w]*" => word,
r#""[^"]*""# => string,
_
diff --git a/src/fexpr/mod.rs b/src/fexpr/mod.rs
index c6a3a39..5d12051 100644
--- a/src/fexpr/mod.rs
+++ b/src/fexpr/mod.rs
@@ -11,6 +11,12 @@ use itertools::Itertools;
use lalrpop_util::{lalrpop_mod, lexer::Token, ParseError};
use thiserror::Error;
+// Lalrpop chokes on the associated type specification (it doesn't expect the =), so we need to
+// define those aliases here in Rust and then import and use them in the grammar.
+trait DateProducer = filters::values::Producer<Output = chrono::DateTime<chrono::Utc>>;
+trait DurationProducer = filters::values::Producer<Output = chrono::Duration>;
+trait CountProducer = filters::values::Producer<Output = u8>;
+
lalrpop_mod!(#[allow(clippy::all)] pub grammar, "/fexpr/grammar.rs");
#[derive(Debug)]