module Timing

grammar NaturalTimeLanguage

  rule expression
    space* moment:moment space* zone_info:zone_info? space* <Expression>
  end

  rule zone_info
    zone_offset /
    zone_name
  end

  rule moment
    timestamp /
    time_ago /
    moment_at_time /
    before_from_moment /
    date_moment
  end

  rule date_moment
    named_moment / 
    last_next_day_name / 
    day_month_name_year / 
    year_month_day /
    beginning_end_interval
  end

  rule named_moment
    now / today / tomorrow / yesterday
  end

  rule last_next_day_name
    direction:last_next space* day_name:day_name space* including_today:'including today'? <LastNextDayName>
  end

  rule day_month_name_year
    day:integer space* month:month_name space* year:integer? space* <DayMonthNameYear>
  end

  rule year_month_day
    year:integer '-' month:integer '-' day:integer <YearMonthDay>
  end

  rule beginning_end_interval
    direction:beginning_end space* interval_type:interval <BeginningEndInterval>
  end

  rule time_ago
    number:integer space* interval_type:interval space* 'ago' <TimeAgo>
  end

  rule moment_at_time
    moment:date_moment space* 'at' space* time:hour_minute_second <MomentAtTime>
  end

  rule before_from_moment
    number:integer space* interval_type:interval space* direction:before_from space* moment:moment <BeforeFromMoment>
  end

  rule timestamp
    [\d]4..4 '-' [\d]2..2 '-' [\d]2..2 space* 't'? space* [\d]2..2 ':' [\d]2..2 ':' [\d]2..2 <Timestamp>
  end

  rule now
    'now' <Now>
  end

  rule today
    'today' <Today>
  end

  rule tomorrow
    'tomorrow' <Tomorrow>
  end

  rule yesterday
    'yesterday' <Yesterday>
  end

  rule last_next
    last / next
  end

  rule last
    'last' <LastNext>
  end

  rule next
    'next' <LastNext>
  end

  rule beginning_end
    beginning_of / end_of
  end

  rule beginning_of
    direction:'beginning' space* 'of' <BeginningEnd>
  end

  rule end_of
    direction:'end' space* 'of' <BeginningEnd>
  end

  rule before_from
    before / from
  end

  rule before
    'before' <BeforeFrom>
  end

  rule from
    'from' <BeforeFrom>
  end

  rule interval
    second_interval / 
    minute_interval / 
    hour_interval / 
    day_interval / 
    week_interval / 
    month_interval / 
    year_interval
  end

  rule second_interval
    'second' 's'? <SecondInterval>
  end

  rule minute_interval
    'minute' 's'? <MinuteInterval>
  end

  rule hour_interval
    'hour' 's'? <HourInterval>
  end

  rule day_interval
    'day' 's'? <DayInterval>
  end

  rule week_interval
    'week' 's'?  <WeekInterval>
  end

  rule month_interval
    'month' 's'?  <MonthInterval>
  end

  rule year_interval
    'year' 's'?  <YearInterval>
  end

  rule day_name
    long_day_name / short_day_name
  end

  rule long_day_name
    'sunday'    <DayName> /
    'monday'    <DayName> /
    'tuesday'   <DayName> /
    'wednesday' <DayName> /
    'thursday'  <DayName> /
    'friday'    <DayName> /
    'saturday'  <DayName>
  end

  rule short_day_name
    'sun' <DayName> /
    'mon' <DayName> /
    'tue' <DayName> /
    'wed' <DayName> /
    'thu' <DayName> /
    'fri' <DayName> /
    'sat' <DayName>
  end

  rule month_name
    long_month_name / short_month_name
  end

  rule long_month_name
    'january'   <MonthName> /
    'february'  <MonthName> /
    'march'     <MonthName> /
    'april'     <MonthName> /
    'may'       <MonthName> /
    'june'      <MonthName> /
    'july'      <MonthName> /
    'august'    <MonthName> /
    'september' <MonthName> /
    'october'   <MonthName> /
    'november'  <MonthName> /
    'december'  <MonthName>
  end

  rule short_month_name
    'jan' <MonthName> /
    'feb' <MonthName> /
    'mar' <MonthName> /
    'apr' <MonthName> /
    'may' <MonthName> /
    'jun' <MonthName> /
    'jul' <MonthName> /
    'aug' <MonthName> /
    'sep' <MonthName> /
    'oct' <MonthName> /
    'nov' <MonthName> /
    'dec' <MonthName>
  end

  rule zone_offset
    [+-] [\d]2..2 ':'? [\d]2..2 <ZoneOffset>
  end

  rule zone_name
    'utc' <ZoneName>
  end

  rule hour_minute_second
    [\d]2..2 ':' [\d]2..2 (':' [\d]2..2)? <HourMinuteSecond> /
    'beginning' <HourMinuteSecond> /
    'end' <HourMinuteSecond>
  end

  rule integer
    [\d]+ <Int>
  end

  rule space
    [\s\t\n]
  end

end

end