module Fugit::Nat::Parser

Constants

INTERVALS
INTERVAL_REX
MONTHDAY_REX
NAMED_H_REX
NAMED_M_REX

prevent “mon” from eating “monday”

NHOURS
NMINUTES
OMONTHDAYS
OMONTHDAY_REX
POINTS
POINT_REX
WEEKDAYS
WEEKDAY_REX

Public Instance Methods

_and(i) click to toggle source
# File lib/fugit/nat.rb, line 119
def _and(i); rex(nil, i, /[ \t]*and[ \t]+/i); end
_and_or_or(i) click to toggle source
# File lib/fugit/nat.rb, line 120
def _and_or_or(i); rex(nil, i, /[ \t]*(and|or)[ \t]+/i); end
_and_or_or_or_comma(i) click to toggle source
# File lib/fugit/nat.rb, line 123
def _and_or_or_or_comma(i)
  rex(nil, i, /[ \t]*(,[ \t]*)?((and|or)[ \t]+|,[ \t]*)/i); end
_at(i) click to toggle source
# File lib/fugit/nat.rb, line 115
def _at(i); rex(nil, i, /[ \t]*at[ \t]+/i); end
_day_s(i) click to toggle source
# File lib/fugit/nat.rb, line 129
def _day_s(i); rex(nil, i, /[ \t]*days?[ \t]+/i); end
_dmin(i) click to toggle source
# File lib/fugit/nat.rb, line 156
def _dmin(i)
  rex(:dmin, i, /[0-5]?[0-9]/)
end
_every(i) click to toggle source

parsers bottom to top #################################################

# File lib/fugit/nat.rb, line 113
def _every(i); rex(nil, i, /[ \t]*every[ \t]+/i); end
_from(i) click to toggle source
# File lib/fugit/nat.rb, line 114
def _from(i); rex(nil, i, /[ \t]*from[ \t]+/i); end
_in_or_on(i) click to toggle source
# File lib/fugit/nat.rb, line 121
def _in_or_on(i); rex(nil, i, /(in|on)[ \t]+/i); end
_minute(i) click to toggle source
# File lib/fugit/nat.rb, line 154
def _minute(i); rex(nil, i, /[ \t]*minute[ \t]+/i) end
_offset_unit(i) click to toggle source
# File lib/fugit/nat.rb, line 282
def _offset_unit(i)
  rex(nil, i, /(second|minute|hour|day|month)s?[ \t]+/i)
end
_on(i) click to toggle source
# File lib/fugit/nat.rb, line 116
def _on(i); rex(nil, i, /[ \t]*on[ \t]+/i); end
_point(i) click to toggle source
# File lib/fugit/nat.rb, line 245
def _point(i); rex(:point, i, POINT_REX); end
_rewrite_sub(t, key=nil) click to toggle source
# File lib/fugit/nat.rb, line 388
def _rewrite_sub(t, key=nil)
  st = t.sublookup(key)
  st ? rewrite(st) : nil
end
_rewrite_subs(t, key=nil) click to toggle source
# File lib/fugit/nat.rb, line 385
def _rewrite_subs(t, key=nil)
  t.subgather(key).collect { |ct| rewrite(ct) }
end
_sep(i) click to toggle source
# File lib/fugit/nat.rb, line 133
def _sep(i); rex(nil, i, /([ \t]+|[ \t]*,[ \t]*)/); end
_space(i) click to toggle source
# File lib/fugit/nat.rb, line 132
def _space(i); rex(nil, i, /[ \t]+/); end
_starting_at(i) click to toggle source
# File lib/fugit/nat.rb, line 279
def _starting_at(i)
  rex(nil, i, /[ \t]*(starting[ \t]+at|from)[ \t]+/i)
end
_the(i) click to toggle source
# File lib/fugit/nat.rb, line 130
def _the(i); rex(nil, i, /[ \t]*the[ \t]+/i); end
_to(i) click to toggle source
# File lib/fugit/nat.rb, line 117
def _to(i); rex(nil, i, /[ \t]*to[ \t]+/i); end
_to_or_dash(i) click to toggle source
# File lib/fugit/nat.rb, line 126
def _to_or_dash(i);
  rex(nil, i, /[ \t]*-[ \t]*|[ \t]+(to|through)[ \t]+/i); end
adjust_h(h, m, ap) click to toggle source

Try to follow en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight

# File lib/fugit/nat.rb, line 523
def adjust_h(h, m, ap)

  if ap == 'midnight' && h == 12
    24
  elsif ap == 'pm' && h < 12 # post meridian
    h + 12
  elsif ap == 'am' && h == 12 # ante meridian
    0
  else
    h
  end
end
ampm(i) click to toggle source
# File lib/fugit/nat.rb, line 210
def ampm(i)
  rex(:ampm, i, /[ \t]*(am|AM|pm|PM|[Nn]oon|[Mm]idday|[Mm]idnight)/)
end
and_dmin(i) click to toggle source
# File lib/fugit/nat.rb, line 159
def and_dmin(i)
  seq(nil, i, :_and_or_or_or_comma, :_minute, '?', :_dmin)
end
at(i) click to toggle source
# File lib/fugit/nat.rb, line 271
def at(i)
  seq(:at, i, :_at, '?', :at_objects)
end
at_object(i) click to toggle source

at five at five pm at five o'clock at 16:30 at noon at 18:00 UTC <– …tz

# File lib/fugit/nat.rb, line 264
def at_object(i)
  alt(nil, i, :named_hour, :digital_hour, :simple_hour, :at_point)
end
at_objects(i) click to toggle source
# File lib/fugit/nat.rb, line 267
def at_objects(i)
  jseq(nil, i, :at_object, :_and_or_or_or_comma)
end
at_p(i) click to toggle source
# File lib/fugit/nat.rb, line 251
def at_p(i)
  seq(:at_p, i, :_point, :counts)
end
at_point(i) click to toggle source
# File lib/fugit/nat.rb, line 254
def at_point(i)
  jseq(nil, i, :at_p, :_and_or_or)
end
city_tz(i) click to toggle source
# File lib/fugit/nat.rb, line 194
def city_tz(i)
  rex(nil, i, /[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}/)
end
count(i) click to toggle source
# File lib/fugit/nat.rb, line 135
def count(i); rex(:count, i, /\d+/); end
counts(i) click to toggle source
# File lib/fugit/nat.rb, line 247
def counts(i)
  jseq(nil, i, :count, :_and_or_or_or_comma)
end
dark(i) click to toggle source
# File lib/fugit/nat.rb, line 213
def dark(i)
  rex(:dark, i, /[ \t]*dark/i)
end
delta_tz(i) click to toggle source
# File lib/fugit/nat.rb, line 200
def delta_tz(i)
  rex(nil, i, /[-+]([01][0-9]|2[0-4])(:?(00|15|30|45))?/)
end
digital_h(i) click to toggle source
# File lib/fugit/nat.rb, line 217
def digital_h(i)
  rex(:digital_h, i, /(2[0-4]|[0-1]?[0-9]):([0-5][0-9])/i)
end
digital_hour(i) click to toggle source
# File lib/fugit/nat.rb, line 220
def digital_hour(i)
  seq(:digital_hour, i, :digital_h, :ampm, '?')
end
every(i) click to toggle source
# File lib/fugit/nat.rb, line 367
def every(i)
  seq(:every, i, :_every, :every_objects)
end
every_interval(i) click to toggle source

every day every 1 minute every minute starting at minute 10

# File lib/fugit/nat.rb, line 298
def every_interval(i)
  seq(:every_interval, i, :count, '?', :interval, :offset, '?')
end
every_named(i) click to toggle source
# File lib/fugit/nat.rb, line 353
def every_named(i)
  rex(:every_named, i, /weekday/i)
end
every_object(i) click to toggle source
# File lib/fugit/nat.rb, line 357
def every_object(i)
  alt(
    nil, i,
    :every_weekday, :every_of_the_month,
    :every_interval, :every_named, :every_single_interval)
end
every_objects(i) click to toggle source
# File lib/fugit/nat.rb, line 363
def every_objects(i)
  jseq(nil, i, :every_object, :_and_or_or)
end
every_of_the_month(i) click to toggle source

every 1st of the month every first of the month Every 2nd of the month Every second of the month every 15th of the month

# File lib/fugit/nat.rb, line 349
def every_of_the_month(i)
  seq(nil, i, :omonthdays, :otm)
end
every_single_interval(i) click to toggle source
# File lib/fugit/nat.rb, line 302
def every_single_interval(i)
  rex(:every_single_interval, i, /(1[ \t]+)?(week|year)/)
end
every_weekday(i) click to toggle source

every monday every Fri-Sun every Monday and Tuesday

# File lib/fugit/nat.rb, line 336
def every_weekday(i)
  jseq(nil, i, :weekday_range, :_and_or_or)
end
from(i) click to toggle source
# File lib/fugit/nat.rb, line 329
def from(i)
  seq(nil, i, :_from, '?', :from_objects)
end
from_object(i) click to toggle source
# File lib/fugit/nat.rb, line 323
def from_object(i)
  alt(nil, i, :to_weekday, :to_omonthday, :to_hour)
end
from_objects(i) click to toggle source
# File lib/fugit/nat.rb, line 326
def from_objects(i)
  jseq(nil, i, :from_object, :_and_or_or)
end
interval(i) click to toggle source
# File lib/fugit/nat.rb, line 275
def interval(i)
  rex(:interval, i, INTERVAL_REX)
end
monthday(i) click to toggle source
# File lib/fugit/nat.rb, line 140
def monthday(i)
  rex(:monthday, i, MONTHDAY_REX)
end
monthdays(i) click to toggle source
# File lib/fugit/nat.rb, line 148
def monthdays(i); jseq(nil, i, :monthday, :_and_or_or_or_comma); end
named_h(i) click to toggle source
# File lib/fugit/nat.rb, line 238
def named_h(i)
  rex(:named_h, i, NAMED_H_REX)
end
named_hour(i) click to toggle source
# File lib/fugit/nat.rb, line 241
def named_hour(i)
  seq(:named_hour, i, :named_h, :dark, '?', :named_min, '?', :ampm, '?')
end
named_m(i) click to toggle source
# File lib/fugit/nat.rb, line 231
def named_m(i)
  rex(:named_m, i, NAMED_M_REX)
end
named_min(i) click to toggle source
# File lib/fugit/nat.rb, line 234
def named_min(i)
  seq(nil, i, :_space, :named_m)
end
named_tz(i) click to toggle source
# File lib/fugit/nat.rb, line 197
def named_tz(i)
  rex(nil, i, /Z|UTC/)
end
nat(i) click to toggle source
# File lib/fugit/nat.rb, line 374
def nat(i)
  jseq(:nat, i, :nat_elt, :_sep)
end
nat_elt(i) click to toggle source
# File lib/fugit/nat.rb, line 371
def nat_elt(i)
  alt(nil, i, :every, :from, :at, :tzone, :on)
end
offset(i) click to toggle source

starting at minute 1 from minute 1

# File lib/fugit/nat.rb, line 291
def offset(i)
  seq(:offset, i, :_starting_at, :_offset_unit, :offset_count)
end
offset_count(i) click to toggle source
# File lib/fugit/nat.rb, line 285
def offset_count(i)
  rex(:offset_count, i, /\d+/)
end
omonthday(i) click to toggle source
# File lib/fugit/nat.rb, line 137
def omonthday(i)
  rex(:omonthday, i, OMONTHDAY_REX)
end
omonthdays(i) click to toggle source
# File lib/fugit/nat.rb, line 147
def omonthdays(i); jseq(nil, i, :omonthday, :_and_or_or_or_comma); end
on(i) click to toggle source

'every month on day 2 at 10:00' => '0 10 2 * *', 'every month on day 2 and 5 at 10:00' => '0 10 2,5 * *', 'every month on days 1,15 at 10:00' => '0 10 1,15 * *',

'every week on monday 18:23' => '23 18 * * 1',

every month on the 1st
# File lib/fugit/nat.rb, line 190
def on(i)
  seq(:on, i, :_on, :on_objects)
end
on_days(i) click to toggle source
# File lib/fugit/nat.rb, line 172
def on_days(i); seq(:on_days, i, :_day_s, :monthdays); end
on_minutes(i) click to toggle source
# File lib/fugit/nat.rb, line 163
def on_minutes(i)
  seq(:on_minutes, i, :_minute, :_dmin, :and_dmin, '*')
end
on_object(i) click to toggle source
# File lib/fugit/nat.rb, line 175
def on_object(i)
  alt(nil, i, :on_days, :on_weekdays, :on_minutes, :on_thes, :on_thex)
end
on_objects(i) click to toggle source
# File lib/fugit/nat.rb, line 178
def on_objects(i)
  jseq(nil, i, :on_object, :_and)
end
on_the(i) click to toggle source
# File lib/fugit/nat.rb, line 152
def on_the(i); seq(nil, i, :_the, :omonthdays); end
on_thes(i) click to toggle source
# File lib/fugit/nat.rb, line 171
def on_thes(i); jseq(:on_thes, i, :on_the, :_and_or_or_or_comma); end
on_thex(i) click to toggle source
# File lib/fugit/nat.rb, line 167
def on_thex(i);
  rex(:on_thex, i, /[ \t]*the[ \t]+(hour|minute)[ \t]*/i);
end
on_weekdays(i) click to toggle source
# File lib/fugit/nat.rb, line 173
def on_weekdays(i); ren(:on_weekdays, i, :weekdays); end
otm(i) click to toggle source
# File lib/fugit/nat.rb, line 340
def otm(i)
  rex(nil, i, /[ \t]+of the month/)
end
rewrite_at(t) click to toggle source
# File lib/fugit/nat.rb, line 582
def rewrite_at(t)
  _rewrite_subs(t)
end
rewrite_at_p(t) click to toggle source
# File lib/fugit/nat.rb, line 434
      def rewrite_at_p(t)

        pt = t.sublookup(:point).strinpd
        pt = pt.start_with?('mon') ? 'M' : pt[0, 1]
        pts = t.subgather(:count).collect { |e| e.string.to_i }
#p [ pt, pts ]

        case pt
        #when 'm' then slot(:m, pts)
        when 'm' then slot(:hm, '*', pts, strong: 1)
        when 's' then slot(:second, pts)
        else slot(pt.to_sym, pts)
        end
      end
rewrite_digital_hour(t) click to toggle source
# File lib/fugit/nat.rb, line 536
def rewrite_digital_hour(t)

  h, m = t.sublookup(:digital_h).strinpd.split(':').collect(&:to_i)
  ap = t.sublookup(:ampm)
  h, m = adjust_h(h, m, ap && ap.strinpd), m

  slot(:hm, h, m)
end
rewrite_dmin(t) click to toggle source
# File lib/fugit/nat.rb, line 393
def rewrite_dmin(t)
  t.strinp
end
rewrite_every(t) click to toggle source
# File lib/fugit/nat.rb, line 586
def rewrite_every(t)
  _rewrite_sub(t)
end
rewrite_every_interval(t) click to toggle source
# File lib/fugit/nat.rb, line 458
      def rewrite_every_interval(t)

#Raabro.pp(t, colours: true)
        ct = t.sublookup(:count)
        it = t.sublookup(:interval)
        ot = t.sublookup(:offset)

        c = (ct ? ct.string : '1').strip
        i = it.string.strip[0, 3]
        i = (i == 'M' || i.downcase == 'mon') ? 'M' : i[0, 1].downcase
        off = ot ? ot.sublookup(:offset_count).string.to_i : nil
        cc =
          if off then "#{off}/#{c}"
          elsif c == '1' then '*'
          else "*/#{c}"
          end

        case i
        when 'M' then slot(:month, cc)
        when 'd' then slot(:monthday, cc, :weak)
        #when 'h' then slot(:hm, cc, 0, weak: :minute)
        when 'h' then slot(:hm, cc, 0, weak: 1)
        when 'm' then slot(:hm, '*', cc, strong: 1)
        when 's' then slot(:second, cc)
        else {}
        end
      end
rewrite_every_named(t) click to toggle source
# File lib/fugit/nat.rb, line 486
def rewrite_every_named(t)

  case s = t.string
  when /weekday/i then slot(:weekday, '1-5', :weak)
  when /week/i then slot(:weekday, '0', :weak)
  else fail "cannot rewrite #{s.inspect}"
  end
end
rewrite_every_single_interval(t) click to toggle source
# File lib/fugit/nat.rb, line 449
def rewrite_every_single_interval(t)

  case t.string
  when /year/i then [ slot(:month, 1, :weak), slot(:monthday, 1, :weak) ]
  #when /week/i then xxx...
  else slot(:weekday, 0, :weak)
  end
end
rewrite_monthday(t) click to toggle source
# File lib/fugit/nat.rb, line 426
def rewrite_monthday(t)
  slot(:monthday, t.string.to_i)
end
rewrite_named_hour(t) click to toggle source
# File lib/fugit/nat.rb, line 553
def rewrite_named_hour(t)

  ht = t.sublookup(:named_h)
  mt = t.sublookup(:named_m)
  apt = t.sublookup(:ampm)

  h = ht.strinp
  m = mt ? mt.strinp : 0
  h = NHOURS[h]
  m = NMINUTES[m] || m

  h = adjust_h(h, m, apt && apt.strinpd)

  slot(:hm, h, m)
end
rewrite_nat(t) click to toggle source
# File lib/fugit/nat.rb, line 590
      def rewrite_nat(t)
#Raabro.pp(t, colours: true)
        Fugit::Nat::SlotGroup.new(_rewrite_subs(t).flatten)
      end
rewrite_omonthday(t) click to toggle source
# File lib/fugit/nat.rb, line 430
def rewrite_omonthday(t)
  slot(:monthday, OMONTHDAYS[t.string.downcase])
end
rewrite_on(t) click to toggle source
# File lib/fugit/nat.rb, line 422
def rewrite_on(t)
  _rewrite_subs(t)
end
rewrite_on_days(t) click to toggle source
# File lib/fugit/nat.rb, line 418
def rewrite_on_days(t)
  _rewrite_subs(t, :monthday)
end
rewrite_on_minutes(t) click to toggle source
# File lib/fugit/nat.rb, line 397
      def rewrite_on_minutes(t)

#Raabro.pp(t, colours: true)
        mins = t.subgather(:dmin).collect(&:strinp)
        #slot(:m, mins.join(','))
        slot(:hm, '*', mins.join(','), strong: 1)
      end
rewrite_on_thes(t) click to toggle source
# File lib/fugit/nat.rb, line 415
def rewrite_on_thes(t)
  _rewrite_subs(t, :omonthday)
end
rewrite_on_thex(t) click to toggle source
# File lib/fugit/nat.rb, line 405
def rewrite_on_thex(t)

  case s = t.string
  #when /hour/i then slot(:h, 0)
  #else slot(:m, '*')
  when /hour/i then slot(:hm, 0, '*', strong: 0)
  else slot(:hm, '*', '*', strong: 1)
  end
end
rewrite_on_weekdays(t)
Alias for: rewrite_weekdays
rewrite_simple_hour(t) click to toggle source
# File lib/fugit/nat.rb, line 545
def rewrite_simple_hour(t)

  h, ap = t.subgather(nil).collect(&:strinpd)
  h = adjust_h(h.to_i, 0, ap)

  slot(:hm, h, 0)
end
rewrite_to_hour(t) click to toggle source
# File lib/fugit/nat.rb, line 569
      def rewrite_to_hour(t)

#Raabro.pp(t, colours: true)
        ht0, ht1 = t.subgather(nil)
        h0, h1 = rewrite(ht0), rewrite(ht1)

        fail ArgumentError.new(
          "cannot deal with #{ht0.strinp} to #{ht1.strinp}, minutes diverge"
        ) if h0.data1 != h1.data1

        slot(:hm, "#{h0._data0}-#{h1._data0}", 0, strong: 0)
      end
rewrite_to_omonthday(t) click to toggle source
# File lib/fugit/nat.rb, line 516
def rewrite_to_omonthday(t)
  md0, md1 = _rewrite_subs(t, :omonthday).collect(&:_data0)
  slot(:monthday, "#{md0}-#{md1}")
end
rewrite_to_weekday(t) click to toggle source
# File lib/fugit/nat.rb, line 509
def rewrite_to_weekday(t)

  wd0, wd1 = _rewrite_subs(t, :weekday)
  #wd1 = 7 if wd1 == 0
  slot(:weekday, "#{wd0}-#{wd1}")
end
rewrite_tz(t) click to toggle source
# File lib/fugit/nat.rb, line 495
def rewrite_tz(t)
  slot(:tz, t.string)
end
rewrite_weekday(t) click to toggle source
# File lib/fugit/nat.rb, line 499
def rewrite_weekday(t)
  Fugit::Cron::Parser::WEEKDS.index(t.string[0, 3].downcase)
end
rewrite_weekdays(t) click to toggle source
# File lib/fugit/nat.rb, line 503
      def rewrite_weekdays(t)
#Raabro.pp(t, colours: true)
        slot(:weekday, _rewrite_subs(t, :weekday))
      end
Also aliased as: rewrite_on_weekdays
simple_h(i) click to toggle source
# File lib/fugit/nat.rb, line 224
def simple_h(i)
   rex(:simple_h, i, /#{(0..24).to_a.reverse.join('|')}/)
end
simple_hour(i) click to toggle source
# File lib/fugit/nat.rb, line 227
def simple_hour(i)
  seq(:simple_hour, i, :simple_h, :ampm, '?')
end
slot(key, data0, data1=nil, opts=nil) click to toggle source

rewrite parsed tree ###################################################

# File lib/fugit/nat.rb, line 381
def slot(key, data0, data1=nil, opts=nil)
  Slot.new(key, data0, data1, opts)
end
to_hour(i) click to toggle source
# File lib/fugit/nat.rb, line 319
def to_hour(i)
  seq(:to_hour, i, :at_object, :_to, :at_object)
end
to_omonthday(i) click to toggle source
# File lib/fugit/nat.rb, line 314
def to_omonthday(i)
  seq(:to_omonthday, i,
    :_the, '?', :omonthday, :_to, :_the, '?', :omonthday)
end
to_weekday(i) click to toggle source
# File lib/fugit/nat.rb, line 306
def to_weekday(i)
  seq(:to_weekday, i, :weekday, :_to_or_dash, :weekday)
end
tz(i) click to toggle source
# File lib/fugit/nat.rb, line 203
def tz(i)
  alt(:tz, i, :city_tz, :named_tz, :delta_tz)
end
tzone(i) click to toggle source
# File lib/fugit/nat.rb, line 206
def tzone(i)
  seq(nil, i, :_in_or_on, '?', :tz)
end
weekday(i) click to toggle source
# File lib/fugit/nat.rb, line 143
def weekday(i)
  rex(:weekday, i, WEEKDAY_REX)
end
weekday_range(i) click to toggle source
# File lib/fugit/nat.rb, line 310
def weekday_range(i)
  alt(nil, i, :to_weekday, :weekdays)
end
weekdays(i) click to toggle source
# File lib/fugit/nat.rb, line 150
def weekdays(i); jseq(:weekdays, i, :weekday, :_and_or_or_or_comma); end