aboutsummaryrefslogtreecommitdiff
path: root/src/fexpr/grammar.lalrpop
diff options
context:
space:
mode:
authorDaniel <kingdread@gmx.de>2020-06-12 00:48:18 +0200
committerDaniel <kingdread@gmx.de>2020-06-12 00:48:18 +0200
commitd4a24eef7fd410c147de201d776089e0601317d5 (patch)
tree8311b261c20d6d5f2d817f63e2cf4a3b213cdd34 /src/fexpr/grammar.lalrpop
parent1fb3d3259d23410f8bf9879f64de880a11e4f876 (diff)
downloadraidgrep-d4a24eef7fd410c147de201d776089e0601317d5.tar.gz
raidgrep-d4a24eef7fd410c147de201d776089e0601317d5.tar.bz2
raidgrep-d4a24eef7fd410c147de201d776089e0601317d5.zip
initial work on comparison based filters
This enables filters such as -time > 2020-01-01 -time < 2020-02-03 ... for time and duration, and later possibly also for more things (such as a COUNT(...) construct). This work tries to integrate them into the existing filter system as seamless as possible, by providing a Comparator which implements LogFilter. The "type checking" is done at parse time, so nonsensical comparisons like -time > 12s flat out give a parse error. This however might be changed to a more dynamic system with run-time type checking, in which case we could do away with the type parameter on Producer and simply work with a generic Value. The comparator would then return an error if two non-identical types would be compared. Note that the system does not support arithmetic expressions, only simple comparisons to constant values.
Diffstat (limited to 'src/fexpr/grammar.lalrpop')
-rw-r--r--src/fexpr/grammar.lalrpop37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop
index 45f4fde..c2df097 100644
--- a/src/fexpr/grammar.lalrpop
+++ b/src/fexpr/grammar.lalrpop
@@ -4,12 +4,15 @@ use super::{
FightOutcome,
filters,
PlayerClass,
+
+ DateProducer,
+ DurationProducer,
};
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;
@@ -68,6 +71,9 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {
"any" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>),
"exists" "(" "player" ":" <PlayerFilter> ")" => filters::player::any(<>),
+ <Comparison<DateProducer>>,
+ <Comparison<DurationProducer>>,
+
"(" <LogFilter> ")",
}
@@ -175,6 +181,22 @@ Date: DateTime<Utc> = {
.map(|d| d.with_timezone(&Utc)),
}
+Duration: Duration = {
+ duration => Duration::seconds(<>[..<>.len() - 1].parse().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 +205,16 @@ 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(),
+}
+
match {
"player" => "player",
"not" => "not",
@@ -194,7 +226,8 @@ match {
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+s" => duration,
+ r"[[:alpha:]][\w]*" => word,
r#""[^"]*""# => string,
_