eol = _{ NEWLINE | EOI } WHITESPACE = _{ !eol ~ WHITE_SPACE } rest_some = { (!eol ~ ANY)+ } rest_any = { (!eol ~ ANY)* } title = { WHITESPACE ~ rest_some ~ eol } year = @{ ASCII_DIGIT{4} } month = @{ ASCII_DIGIT{2} } day = @{ ASCII_DIGIT{2} } datum = ${ year ~ "-" ~ month ~ "-" ~ day } bdatum = ${ (year | "?") ~ "-" ~ month ~ "-" ~ day } hour = @{ ASCII_DIGIT{2} } minute = @{ ASCII_DIGIT{2} } time = ${ hour ~ ":" ~ minute } weekday = { "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun" } amount_sign = { ("+" | "-")? } amount_value = { ASCII_DIGIT{0,9} } // Fits in an i32 amount = { amount_sign ~ amount_value } delta_weekdays = { amount ~ weekday } delta_minutes = { amount ~ "min" } delta_years = { amount ~ "y" } delta_months = { amount ~ "m" } delta_months_reverse = { amount ~ "M" } delta_days = { amount ~ "d" } delta_weeks = { amount ~ "w" } delta_hours = { amount ~ "h" } delta = { ( delta_weekdays | delta_minutes | delta_years | delta_months | delta_months_reverse | delta_days | delta_weeks | delta_hours )+ } paren_expr = { "(" ~ expr ~ ")" } number = @{ ASCII_DIGIT{1,9} } // Fits in an i32 boolean = { "true" | "false" } variable = { "j" | "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 } op = { "+" | "-" | "*" | "/" | "%" | "=" | "!=" | "<=" | "<" | ">=" | ">" | "&" | "|" | "^" } expr = { term ~ (op ~ term)* } date_fixed_start = { datum ~ delta? ~ time? } date_fixed_end = { datum ~ delta? ~ time? | delta ~ time? | time } date_fixed_repeat = { delta } date_fixed = { date_fixed_start ~ ("--" ~ date_fixed_end)? ~ (";" ~ date_fixed_repeat)? } wildcard_expr = { "*" } date_expr_start = { (wildcard_expr | paren_expr) ~ delta? ~ time? } date_expr_end = { delta ~ time? | time } date_expr = { date_expr_start ~ ("--" ~ date_expr_end)? } date_weekday_start = { weekday ~ delta? ~ time? } date_weekday_end = { weekday ~ delta? ~ time? | delta ~ time? | time } date_weekday = { date_weekday_start ~ ("--" ~ date_weekday_end)? } date = !{ "DATE" ~ (date_fixed | date_expr | date_weekday) ~ eol } bdate = !{ "BDATE" ~ bdatum ~ eol } from = !{ "FROM" ~ datum ~ eol } until = !{ "UNTIL" ~ datum ~ eol } except = !{ "EXCEPT" ~ datum ~ eol } donedate = { "(" ~ datum ~ time ~ ")" } done = !{ "DONE" ~ datum? ~ donedate? ~ eol } desc_line = { "#" ~ (" " ~ rest_any)? ~ eol } description = { desc_line* } task_options = { (date | from | until | except | done)* } task = { "TASK" ~ title ~ task_options ~ description } note_options = { (date | from | until | except)* } note = { "NOTE" ~ title ~ note_options ~ description } birthday = { "BIRTHDAY" ~ title ~ bdate ~ description } empty_line = _{ WHITESPACE* ~ NEWLINE } command = { task | note | birthday } file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI }