# YNot Calendar:
#
# Calendar files are read line by line.  Each line must be either a valid
# <program> a comment with a "#" in the first column, or an *empty* line.
# A <program> starts with either a <date> or an <opcode-list> followed by
# either a <when> value or an <icon> in parentheses followed by a <what>
# description of the event with an optional <where> after an '@' character.
#
# A full ABNF description of the calendar file is provided at the very bottom
# of this file
#
# Examples below show a variety of programs with some explanations.  We'll
# practice with <opcode-lists> first.  For now ignore the <icon> characters in
# parenthesis before the event description.

# US HOLIDAYS

Jan M = 1 D = &       (h) New Year's Day
# "Jan"       Push the value of "Jan", which is 1, onto the stack
# "M"         Push the current month value onto the stack
# "="         Pop two values, if they are equal push true (0) else false (1)
# "1"         Literal value is pushed as is
# "D"         Push the current day value
# "="         Pop two values, check if equal, push result
# "&"         Pop two values, check if both are true (0), push result
# NOTE: this is a long form for educational purposes, the following program
#       is a better way to achieve the same result.

Jan m 1 d &           (h) New Year's Day
# "Jan"       Push 1 as above
# "m"         Pop one value, subtract the M (month) value from it, push the result
# "1 d"       Same method to check if it's the first
# "&"         Pop two values (both test results) and check if both are true
# NOTE: Uppercase variables each have a lowercase operator.  "1 d" is equivalent
#       to "1 D -" which has the same boolean value as "1 D =" when true = 0.

Jan m Mon w & 3 f &   (h) Martin Luther King Jr Day
# "Jan m"     Is it January?  Push result
# "Mon w"     Is it a Monday (w = weekday)? Push result
# "&"         Pop two, are both true? Push result
# "3 f"       Is it the third week of the month (f is relative to first)
# "&"         Are the last two tests both true?

Feb m 14 d &          (h) Valentines Day
# This one should make sense by now ...

Feb m Mon w & 3 f &   (h) Washington's Birthday
# Similar logic as MLK Jr day

May m Sun w & 2 f &   (h) Mother's Day
# Second Sunday this time ...

May m Wed w & 1 l &   (h) Memorial Day
# ...
# "1 l"       Is it the last week of the month (l is relative to last)

Jun m Sun w & 3 f &   (h) Father's Day
Jul m 4 d &           (h) Independence Day
Sep m Mon w & 1 f &   (h) Labor Day
Oct m Mon w & 2 f &   (h) Columbus Day
Nov m Thu w & 4 f &   (h) Thanksgiving
Dec m 31 d &          (h) New Year's Eve


# COMMON CHRISTIAN HOLIDAYS

Dec m 24 d &                        (H) Christmas Eve
Dec m 25 d &                        (H) Christmas Day

25 d 0 ? D 24 < D 14 > & Dec m &    (H) %d days to Christmas
# "25 d 0 ?"  subtract today's day of the month from 25 and "chomp" it
# "D 24 <"    today's day is less than 24? Push either true=0 or false=1
# "D 14 >"    today's day is greater than 14? Push either true=0 or false=1
# "&"         pop two values, are they both true?  Push true=0 / false=1
# "Dec m"     Is it December ...
# "&"         pop two values, check if both are true, push result
# NOTE: %d in the "what" string is filled in with "chomped" value
#       '?' is the chomp operator, it pops two values and stores the
#       first if the second is true

E                                   (H) Easter Sunday
# NOTE: The variable E is the calculated number of days to Easter
#       When this is zero, this single-opcode program evaluates to true

47 e                                (H) Mardi Gras
# "47 e"      subtract days-to-Easter's from 47, is it zero ...

7 e                                 (H) Palm Sunday
46 e                                (H) Ash Wednesday
# As above, 7, or 46 days before Easter

E 7 / 0 ? E 0 >  E 30 < & Sun w &   (H) %1 week(s) to Easter
# "E 7 / 0 ?" divide the number of days to Easter by seven and "chomp" the result
# "E 0 >"     days-to-Easter is greater than zero, i.e, are we *before* Easter
# "E 30 < &"  but also less than 30 days before Easter
# "Sun w &"   and is it also a Sunday


# ANNUAL EVENTS
1941? Sep 9    (b) Dennis Ritchie would be %d years old today
1942? Jan 1    (b) Brian Kernighan is alive and kickin' at %d years old today
1931? Oct 24   (b) Lee E McMahon (RIP) would be %d years old today
# NOTE: The '?' chomp operator has a shorthand in this form in which it is
#       appended to a year (with no spaces).  In this context, it subtracts the
#       specified year from the current year and "chomps" the result to be used
#       in the %d format specifier of the event description.

# EVENTS ON SPECIFIC DAYS
2021 Nov 26    (!) Comic-Con Special Edition begins
# NOTE: Dates must be specified as year month and day.  If month names are given
#       they can be abbreviated or full, uppercase or lower.  If the month is
#       provided in numeric form dashed or dotted dates are also valid ,e,g,
#       2021-11-26 or 2021.11.26 would be equivalent to the above date.

# TIMED EVENTS
Fri w          (1700) Beer O'Clock!
# NOTE: Start time can be specified in parentheses as either HHMM or HH:MM.
#       This value is used to sort events that occur on the same day.  Up to
#       this point in this file, all events have been all-day and have instead
#       specified a single-character "icon" in the parentheses.  These icons are
#       displayed next to all-day events, but are of most value when your
#       calendar is served on the web as it allows for different CSS formats
#       (e.g., different colors) to be applied to different categories of
#       all-day events such as religious or national holidays, birthdays, work
#       events, etc.

# EVENTS WITH LOCATIONS
2022 Jan 13 (1430) Denstist Appointment @ MyTown Dental
# NOTE: Timed or untimed events can be given a location after an '@' symbol.
#       This location data can be presented differently depending on the output
#       mode.  In webserver mode with the default template, this location
#       becomes a link to google maps directions to the listed destination.
#       ... And yes, my dentist appointments are at two-thirty.

#---------------------------------------------------------------------------------#
# START ABNF
#
#  file          = *lf *line
#
#  line          = ( event / comment ) 1*lf
#
#  event         = program 1*wsp description
#
#  comment       = "#" *( %d1-%d9 / %d11-%d126 )
#                ; '#' at the start of line
#
#  lf            = %d10
#                ; '\n'
#
#  wsp           = %d9 / %d32
#                ; space or tab
#
#  program       = date / opcode-list
#
#  date          = year [ "?" ] 1*wsp month 1*wsp day
#
#  date          =/ year "-" 1*2digit "-" day
#
#  date          =/ year "." 1*2digit "." day
#
#  year          = 4digit
#                ; e.g., "2021"
#
#  digit         = %d48-%d57
#                ; 0-9
#
#  month         = ( 1*2digit / 1*alpa )
#                ; anything recognized by strptime's %b or %m in the current locale
#
#  alpha         = ( %d65-%d90 / %d97-%d122 )
#
#  day           = 1*2digit
#
#  opcode-list   = 1*( opcode 1*wsp )
#
#  opcode        = ( number / operator / variable / name )
#
#  number        = [ "-" ] 1*digit
#
#  operator      = "+" / "-" / "*" / "/" / "%" / "=" / "<" / ">" / "&" / "|" / "^" / "!" / "?" / "("
#
#  operator      =/ "y" / "m" / "d" / "w" / "z" / "f" / "b" / "e"
#
#  variable      = "Y" / "M" / "D" / "W" / "Z" / "F" / "B" / "E"
#
#  name          = 1*alpha
#                ; for use as an opcode, any values recognized by strptime's %a or %b placeholders are valid
#                ; that's month and weekday names in the current locale, either full or abbreviated
#                ; unrecognized text strings are evaluated to 0
#
#  description   = when 1*wsp what [ "@" where ]
#
#  when          =  "(" *wsp time / symbol *wsp ")"
#
#  time          =  ( 2digit ":" 2digit ) / 4digit
#
#  icon          = %d32-%d127
#
#  what          = 1*( %d32-%d63 / %d65-%d127 )
#                ; any printable characters except '@'
#
#  where         = 1*( %d32-%d127 )
#
# END ABNF
