Start parsing expressions

This commit is contained in:
Joscha 2021-11-19 20:31:46 +01:00
parent 991df5e026
commit 04417ea0f9
3 changed files with 55 additions and 52 deletions

View file

@ -1,4 +1,4 @@
use chrono::{NaiveDate, NaiveDateTime};
use chrono::NaiveDate;
#[derive(Debug)]
pub struct Time {
@ -76,7 +76,7 @@ pub struct WeekdaySpec {
}
#[derive(Debug)]
pub enum IntVar {
pub enum Var {
/// `j`, see <https://en.wikipedia.org/wiki/Julian_day>
JulianDay,
/// `y`
@ -141,24 +141,6 @@ pub enum IntVar {
Saturday,
/// `sun`, always 7
Sunday,
}
#[derive(Debug)]
pub enum IntExpr {
Lit(i64),
Var(IntVar),
Paren(Box<IntVar>),
Neg(Box<IntExpr>),
Add(Box<IntExpr>, Box<IntExpr>),
Sub(Box<IntExpr>, Box<IntExpr>),
Mul(Box<IntExpr>, Box<IntExpr>),
Div(Box<IntExpr>, Box<IntExpr>),
Mod(Box<IntExpr>, Box<IntExpr>),
Ternary(Box<BoolExpr>, Box<IntExpr>, Box<IntExpr>),
}
#[derive(Debug)]
pub enum BoolVar {
/// `isWeekday`, whether the current day is one of mon-fri
IsWeekday,
/// `isWeekend`, whether the current day is one of sat-sun
@ -168,27 +150,34 @@ pub enum BoolVar {
}
#[derive(Debug)]
pub enum BoolExpr {
Lit(bool),
Var(BoolVar),
Paren(Box<BoolVar>),
Eq(Box<IntExpr>, Box<IntExpr>),
Neq(Box<IntExpr>, Box<IntExpr>),
Lt(Box<IntExpr>, Box<IntExpr>),
Lte(Box<IntExpr>, Box<IntExpr>),
Gt(Box<IntExpr>, Box<IntExpr>),
Gte(Box<IntExpr>, Box<IntExpr>),
Not(Box<BoolExpr>),
And(Box<BoolExpr>, Box<BoolExpr>),
Or(Box<BoolExpr>, Box<BoolExpr>),
Xor(Box<BoolExpr>, Box<BoolExpr>),
BEq(Box<BoolExpr>, Box<BoolExpr>),
BNeq(Box<BoolExpr>, Box<BoolExpr>),
pub enum Expr {
Lit(i64),
Var(Var),
Paren(Box<Expr>),
// Integer-y operations
Neg(Box<Expr>),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Mod(Box<Expr>, Box<Expr>),
// Comparisons
Eq(Box<Expr>, Box<Expr>),
Neq(Box<Expr>, Box<Expr>),
Lt(Box<Expr>, Box<Expr>),
Lte(Box<Expr>, Box<Expr>),
Gt(Box<Expr>, Box<Expr>),
Gte(Box<Expr>, Box<Expr>),
// Boolean-y operations
Not(Box<Expr>),
And(Box<Expr>, Box<Expr>),
Or(Box<Expr>, Box<Expr>),
Xor(Box<Expr>, Box<Expr>),
}
#[derive(Debug)]
pub struct FormulaSpec {
pub start: Option<BoolExpr>, // None: *
pub start: Option<Expr>, // None: *
pub start_delta: Option<Delta>,
pub start_time: Option<Time>,
pub end: Option<Delta>,

View file

@ -4,11 +4,12 @@ use std::result;
use chrono::NaiveDate;
use pest::error::{Error, ErrorVariant};
use pest::iterators::Pair;
use pest::prec_climber::PrecClimber;
use pest::{Parser, Span};
use crate::commands::{
Birthday, BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, FormulaSpec, Note, Spec,
Task, Time, Weekday, WeekdaySpec,
Birthday, BirthdaySpec, Command, DateSpec, Delta, DeltaStep, Done, Expr, FormulaSpec, Note,
Spec, Task, Time, Weekday, WeekdaySpec,
};
#[derive(pest_derive::Parser)]
@ -30,11 +31,6 @@ fn fail<S: Into<String>, T>(span: Span, message: S) -> Result<T> {
Err(error(span, message))
}
fn parse_number(p: Pair<Rule>) -> Result<i32> {
assert_eq!(p.as_rule(), Rule::number);
Ok(p.as_str().parse().unwrap())
}
fn parse_title(p: Pair<Rule>) -> Result<String> {
assert_eq!(p.as_rule(), Rule::title);
let p = p.into_inner().next().unwrap();
@ -116,7 +112,7 @@ fn parse_amount(p: Pair<Rule>) -> Result<Amount> {
_ => unreachable!(),
})
}
Rule::number => value = parse_number(p)?,
Rule::amount_value => value = p.as_str().parse().unwrap(),
_ => unreachable!(),
}
}
@ -274,6 +270,25 @@ fn parse_date_fixed(p: Pair<Rule>) -> Result<DateSpec> {
Ok(spec)
}
fn parse_number(p: Pair<Rule>) -> Result<i32> {
assert_eq!(p.as_rule(), Rule::number);
Ok(p.as_str().parse().unwrap())
}
fn parse_term(p: Pair<Rule>) -> Expr {
todo!()
}
fn parse_op(l: Expr, p: Pair<Rule>, r: Expr) -> Expr {
todo!()
}
fn parse_expr(p: Pair<Rule>) -> Result<Expr> {
assert_eq!(p.as_rule(), Rule::expr);
let climber = PrecClimber::new(vec![todo!()]);
Ok(climber.climb(p.into_inner(), parse_term, parse_op))
}
fn parse_date_expr(p: Pair<Rule>) -> Result<FormulaSpec> {
assert_eq!(p.as_rule(), Rule::date_expr);
dbg!(p);

View file

@ -3,8 +3,6 @@ WHITESPACE = _{ !eol ~ WHITE_SPACE }
rest_some = { (!eol ~ ANY)+ }
rest_any = { (!eol ~ ANY)* }
number = @{ ASCII_DIGIT{1,9} } // Fits into an i32
title = { WHITESPACE ~ rest_some ~ eol }
year = @{ ASCII_DIGIT{4} }
@ -20,7 +18,8 @@ time = ${ hour ~ ":" ~ minute }
weekday = { "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun" }
amount_sign = { "+" | "-" }
amount = { amount_sign? ~ number? }
amount_value = @{ ASCII_DIGIT{1,9} } // Fits into an i32
amount = { amount_sign? ~ amount_value? }
delta_weekdays = { amount ~ weekday }
delta_minutes = { amount ~ "min" }
delta_years = { amount ~ "y" }
@ -42,20 +41,20 @@ delta = {
)+
}
number = @{ ("+" | "-")? ~ ASCII_DIGIT{1,9} } // Fits into an i32
paren_expr = { "(" ~ expr ~ ")" }
boolean = { "true" | "false" }
variable = {
"j"
| "yl" | "yd" | "Yd" | "yw" | "Yw" | "y"
| "ml" | "md" | "Md" | "mw" | "Mw" | "m"
| "yl" | "yd" | "yD" | "yw" | "yW" | "y"
| "ml" | "md" | "mD" | "mw" | "mW" | "m"
| "d" | "D"
| "iy" | "iyl"
| "wd"
| "e"
| "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"
| "isWeekday" | "isWeekend" | "isLeapYear"
}
term = { paren_expr | number | boolean | variable }
term = { paren_expr | number | boolean | weekday | variable }
op = {
"+" | "-" | "*" | "/" | "%"
| "=" | "!="