lib/fugit/nat.rb in fugit-1.3.5 vs lib/fugit/nat.rb in fugit-1.3.6
- old
+ new
@@ -14,20 +14,11 @@
return nil unless s.is_a?(String)
#p s; Raabro.pp(Parser.parse(s, debug: 3), colours: true)
#(p s; Raabro.pp(Parser.parse(s, debug: 1), colours: true)) rescue nil
- a = Parser.parse(s)
-
- return nil unless a
-
- return parse_crons(s, a, opts) \
- if a.include?([ :flag, 'every' ])
- return parse_crons(s, a, opts) \
- if a.include?([ :flag, 'from' ]) && a.find { |e| e[0] == :day_range }
-
- nil
+ parse_crons(s, Parser.parse(s), opts)
end
def do_parse(s, opts={})
parse(s, opts) ||
@@ -36,21 +27,42 @@
protected
def parse_crons(s, a, opts)
- hms, aa = a
- .partition { |e| e[0] == :point && e[1][0] == :hour }
- ms = hms
- .inject({}) { |h, e| (h[e[1][1]] ||= []) << e[1][2]; h }
- .values
+#p a
+ return nil unless a
+
+ h = a
+ .reverse
+ .inject({}) { |r, e| send("parse_#{e[0]}_elt", e, opts, r); r }
+ #
+ # the reverse ensure that in "every day at five", the
+ # "at five" is placed before the "every day" so that
+ # parse_x_elt calls have the right sequence
+#p h
+
+ if f = h[:_fail]
+ #fail ArgumentError.new(f)
+ return nil
+ end
+
+ hms = h[:hms]
+
+ hours = (hms || [])
.uniq
- crons =
- ms.size > 1 ?
- hms.collect { |e| parse_cron([ e ] + aa, opts) } :
- [ parse_cron(a, opts) ]
+ .inject({}) { |r, hm| (r[hm[1]] ||= []) << hm[0]; r }
+ .inject({}) { |r, (m, hs)| (r[hs.sort] ||= []) << m; r }
+ .to_a
+ .sort_by { |hs, ms| -hs.size }
+ if hours.empty?
+ hours << (h[:dom] ? [ [ '0' ], [ '0' ] ] : [ [ '*' ], [ '*' ] ])
+ end
+ crons = hours
+ .collect { |hm| assemble_cron(h.merge(hms: hm)) }
+
fail ArgumentError.new(
"multiple crons in #{s.inspect} " +
"(#{crons.collect(&:original).join(' | ')})"
) if opts[:multi] == :fail && crons.size > 1
@@ -59,302 +71,454 @@
else
crons.first
end
end
- def parse_cron(a, opts)
+ def assemble_cron(h)
- h = { min: nil, hou: nil, dom: nil, mon: nil, dow: nil }
- hkeys = h.keys
+#puts "ac: " + h.inspect
+ s = []
+ s << h[:sec] if h[:sec]
+ s << h[:hms][1].join(',')
+ s << h[:hms][0].join(',')
+ s << (h[:dom] || '*') << (h[:mon] || '*') << (h[:dow] || '*')
+ s << h[:tz] if h[:tz]
- i0s, es = a.partition { |e| e[0] == :interval0 }
- a = es + i0s
- # interval0s are fallback
+ Fugit::Cron.parse(s.join(' '))
+ end
- a.each do |key, val|
- case key
- when :biz_day
- (h[:dow] ||= []) << '1-5'
- when :name_day
- (h[:dow] ||= []) << val
- when :day_range
- (h[:dow] ||= []) << val.collect { |v| v.to_s[0, 3] }.join('-')
- when :tz
- h[:tz] = val
- when :point
- process_point(h, *val)
- when :interval1
- process_interval1(h, *val[0].to_h.first)
- when :interval0
- process_interval0(h, val)
- end
- end
+ def eone(e); e1 = e[1]; e1 == 1 ? '*' : "*/#{e1}"; end
- return nil if h[:fail]
+ def parse_interval_elt(e, opts, h)
- h[:min] = (h[:min] || [ 0 ]).uniq
- h[:hou] = (h[:hou] || []).uniq.sort
- h[:dow].sort! if h[:dow]
+ e1 = e[1]
- a = hkeys
- .collect { |k|
- v = h[k]
- (v && v.any?) ? v.collect(&:to_s).join(',') : '*' }
- a.insert(0, h[:sec]) if h[:sec]
- a << h[:tz].first if h[:tz]
+ case e[2]
+ when 's', 'sec', 'second', 'seconds'
+ h[:sec] = eone(e)
+ when 'm', 'min', 'mins', 'minute', 'minutes'
+ #(h[:hms] ||= []) << [ '*', eone(e) ]
+ h[:hms] ||= [ [ '*', eone(e) ] ]
+ when 'h', 'hour', 'hours'
+ h[:hms] ||= [ [ eone(e), 0 ] ]
+ when 'd', 'day', 'days'
+ h[:dom] = "*/#{e1}" if e1 > 1
+ h[:hms] ||= [ [ 0, 0 ] ]
+ when 'w', 'week', 'weeks'
+ h[:_fail] = "cannot have crons for \"every #{e1} weeks\"" if e1 > 1
+ h[:hms] ||= [ [ 0, 0 ] ]
+ h[:dow] ||= 0
+ when 'M', 'month', 'months'
+ h[:_fail] = "cannot have crons for \"every #{e1} months\"" if e1 > 12
+ h[:hms] ||= [ [ 0, 0 ] ]
+ h[:dom] = 1
+ h[:mon] = eone(e)
+ when 'Y', 'y', 'year', 'years'
+ h[:_fail] = "cannot have crons for \"every #{e1} years\"" if e1 > 1
+ h[:hms] ||= [ [ 0, 0 ] ]
+ h[:dom] = 1
+ h[:mon] = 1
+ end
+ end
- s = a.join(' ')
+ def parse_dow_list_elt(e, opts, h)
- Fugit::Cron.parse(s)
+ h[:hms] ||= [ [ 0, 0 ] ]
+ h[:dow] = e[1..-1].collect(&:to_s).sort.join(',')
end
- def process_point(h, key, *value)
+ def parse_dow_range_elt(e, opts, h)
- case key
- when :hour
- v0, v1 = value
- v0 = v0.to_i if v0.is_a?(String) && v0.match(/^\d+$/)
- (h[:hou] ||= []) << v0
- (h[:min] ||= []) << v1.to_i if v1
- when :sec, :min
- (h[key] ||= []) << value[0]
- end
+ h[:hms] ||= [ [ 0, 0 ] ]
+ h[:dow] = e[1] == e[2] ? e[1] : "#{e[1]}-#{e[2]}"
end
- def process_interval0(h, value)
+ def parse_day_of_month_elt(e, opts, h)
- case value
- when 'sec', 'second'
- h[:min] = [ '*' ]
- h[:sec] = [ '*' ]
- when 'min', 'minute'
- h[:min] = [ '*' ]
- when 'hour'
- unless h[:min] || h[:hou]
- h[:min] = [ 0 ]
- h[:hou] = [ '*' ]
- end
- when 'day'
- unless h[:min] || h[:hou]
- h[:min] = [ 0 ]
- h[:hou] = [ 0 ]
- end
- when 'week'
- unless h[:min] || h[:hou] || h[:dow]
- h[:min] = [ 0 ]
- h[:hou] = [ 0 ]
- h[:dow] = [ 0 ]
- end
- when 'month'
- unless h[:min] || h[:hou]
- h[:min] = [ 0 ]
- h[:hou] = [ 0 ]
- end
- (h[:dom] ||= []) << 1
- when 'year'
- unless h[:min] || h[:hou]
- h[:min] = [ 0 ]
- h[:hou] = [ 0 ]
- end
- (h[:dom] ||= []) << 1
- (h[:mon] ||= []) << 1
- end
+ h[:dom] = e[1..-1].join(',')
end
- def process_interval1(h, interval, value)
+ def parse_at_elt(e, opts, h)
- if value != 1 && [ :yea, :wee ].include?(interval)
- int = interval == :year ? 'years' : 'weeks'
- h[:fail] = "cannot cron for \"every #{value} #{int}\""
- return
- end
+ (h[:hms] ||= []).concat(e[1])
- case interval
- when :yea
- h[:hou] = [ 0 ]
- h[:mon] = [ 1 ]
- h[:dom] = [ 1 ]
- when :mon
- h[:hou] = [ 0 ]
- h[:dom] = [ 1 ]
- h[:mon] = [ value == 1 ? '*' : "*/#{value}" ]
- when :wee
- h[:hou] = [ 0 ]
- h[:dow] = [ 0 ] # Sunday
- when :day
- h[:hou] = [ 0 ]
- h[:dom] = [ value == 1 ? '*' : "*/#{value}" ]
- when :hou
- h[:hou] = [ value == 1 ? '*' : "*/#{value}" ]
- when :min
- h[:hou] = [ '*' ]
- h[:min] = [ value == 1 ? '*' : "*/#{value}" ]
- when :sec
- h[:hou] = [ '*' ]
- h[:min] = [ '*' ]
- h[:sec] = [ value == 1 ? '*' : "*/#{value}" ]
- end
+ l = h[:hms].last
+ h[:sec] = l.pop if l.size > 2
end
+
+ def parse_on_elt(e, opts, h)
+
+ e1 = e[1]
+ h[:dow] = e1[0]
+ h[:hms] = [ e1[1] ]
+
+ l = h[:hms].last
+ h[:sec] = l.pop if l.size > 2
+ end
+
+ def parse_tz_elt(e, opts, h)
+
+ h[:tz] = e[1]
+ end
end
module Parser include Raabro
NUMS = %w[
- zero
- one two three four five six seven eight nine
- ten eleven twelve ]
+ zero one two three four five six seven eight nine ten eleven twelve ]
WEEKDAYS =
Fugit::Cron::Parser::WEEKDS + Fugit::Cron::Parser::WEEKDAYS
- NHOURS =
- { 'noon' => [ 12, 0 ], 'midnight' => [ 0, 0 ] }
+ NHOURS = {
+ 'noon' => [ 12, 0 ],
+ 'midnight' => [ 0, 0 ], 'oh' => [ 0, 0 ] }
+ NMINUTES = {
+ "o'clock" => 0, 'five' => 5,
+ 'ten' => 10, 'fifteen' => 15,
+ 'twenty' => 20, 'twenty-five' => 25,
+ 'thirty' => 30, 'thirty-five' => 35,
+ 'fourty' => 40, 'fourty-five' => 45,
+ 'fifty' => 50, 'fifty-five' => 55 }
+ oh = {
+ '1st' => 1, '2nd' => 2, '3rd' => 3, '21st' => 21, '22nd' => 22,
+ '23rd' => 23, '31st' => 31 }
+ %w[ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 24 25 26 27 28 29 30 ]
+ .each { |i| oh["#{i}th"] = i.to_i }
+ %w[
+ first second third fourth fifth sixth seventh eighth ninth tenth
+ eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth
+ eighteenth nineteenth twentieth twenty-first twenty-second twenty-third
+ twenty-fourth twenty-fifth twenty-fifth twenty-sixth twenty-seventh
+ twenty-eighth twenty-ninth thirtieth thirty-first ]
+ .each_with_index { |e, i| oh[e] = i + 1 }
+ ORDINALS = oh
+
# piece parsers bottom to top
- def interval0(i)
- rex(:interval0, i,
- /(year|month|week|day|hour|min(ute)?|sec(ond)?)(?![a-z])/i)
+ def _from(i); rex(nil, i, /\s*from\s+/i); end
+ def _every(i); rex(nil, i, /\s*(every)\s+/i); end
+ def _at(i); rex(nil, i, /\s*at\s+/i); end
+ def _in(i); rex(nil, i, /\s*(in|on)\s+/i); end
+ def _to(i); rex(nil, i, /\s*to\s+/i); end
+ def _dash(i); rex(nil, i, /-\s*/i); end
+ def _and(i); rex(nil, i, /\s*and\s+/i); end
+ def _on(i); rex(nil, i, /\s*on\s+/i); end
+
+ def _and_or_comma(i)
+ rex(nil, i, /\s*(,?\s*and\s|,?\s*or\s|,)\s*/i)
end
+ def _at_comma(i)
+ rex(nil, i, /\s*(at\s|,|)\s*/i)
+ end
+ def _to_through(i)
+ rex(nil, i, /\s*(to|through)\s+/i)
+ end
+ def integer(i); rex(:int, i, /\d+\s*/); end
+
+ def tz_name(i)
+ rex(nil, i,
+ /\s*[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}(\s+|$)/)
+ end
+ def tz_delta(i)
+ rex(nil, i,
+ /\s*[-+]([01][0-9]|2[0-4]):?(00|15|30|45)(\s+|$)/)
+ end
+ def tzone(i)
+ alt(:tzone, i, :tz_delta, :tz_name)
+ end
+
+ def and_named_digits(i)
+rex(:xxx, i, 'TODO')
+ end
+
+ def dname(i)
+ rex(:dname, i, /(s(ec(onds?)?)?|m(in(utes?)?)?)\s+/i)
+ end
+ def named_digit(i)
+ seq(:named_digit, i, :dname, :integer)
+ end
+ def named_digits(i)
+ seq(nil, i, :named_digit, '+', :and_named_digits, '*')
+ end
+
def am_pm(i)
- rex(:am_pm, i, / *(am|pm)/i)
+ rex(:am_pm, i, /\s*(am|pm|dark)\s*/i)
end
+ def nminute(i)
+ rex(:nminute, i, /(#{NMINUTES.keys.join('|')})\s*/i)
+ end
+ def nhour(i)
+ rex(:nhour, i, /(#{NUMS.join('|')})\s*/i)
+ end
+ def numeral_hour(i)
+ seq(:numeral_hour, i, :nhour, :am_pm, '?', :nminute, '?')
+ end
+
+ def named_hour(i)
+ rex(:named_hour, i, /(#{NHOURS.keys.join('|')})/i)
+ end
+
+ def shour(i)
+ rex(:shour, i, /(2[0-4]|[01]?[0-9])/)
+ end
+ def simple_hour(i)
+ seq(:simple_hour, i, :shour, :am_pm, '?')
+ end
+
def digital_hour(i)
rex(:digital_hour, i, /(2[0-4]|[01][0-9]):?[0-5]\d/)
end
- def _simple_hour(i)
- rex(:sh, i, /(2[0-4]|[01]?[0-9])/)
+ def at_point(i)
+ alt(nil, i,
+ :digital_hour, :simple_hour, :named_hour, :numeral_hour,
+ :named_digits)
end
- def simple_hour(i)
- seq(:simple_hour, i, :_simple_hour, :am_pm, '?')
+
+ def weekday(i)
+ rex(:weekday, i, /(#{WEEKDAYS.reverse.join('|')})\s*/i)
end
- def _numeral_hour(i)
- rex(:nh, i, /(#{NUMS.join('|')})/i)
+ def and_at(i)
+ seq(nil, i, :_and_or_comma, :at_point)
end
- def numeral_hour(i)
- seq(:numeral_hour, i, :_numeral_hour, :am_pm, '?')
+
+ def _intervals(i)
+ rex(:intervals, i,
+ /(
+ y(ears?)?|months?|w(eeks?)?|d(ays?)?|
+ h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?
+ )(\s+|$)/ix)
end
- def name_hour(i)
- rex(:name_hour, i, /(#{NHOURS.keys.join('|')})/i)
+ def sinterval(i)
+ rex(:sinterval, i,
+ /(year|month|week|day|hour|min(ute)?|sec(ond)?)(\s+|$)/i)
end
+ def ninterval(i)
+ seq(:ninterval, i, :integer, :_intervals)
+ end
- def biz_day(i); rex(:biz_day, i, /(biz|business|week) *day/i); end
- def name_day(i); rex(:name_day, i, /#{WEEKDAYS.reverse.join('|')}/i); end
+ def ordinal(i)
+ rex(:ordinal, i, /\s*(#{ORDINALS.keys.join('|')})\s*/)
+ end
- def range_sep(i); rex(nil, i, / *- *| +(to|through) +/); end
+ def _mod(i); rex(nil, i, /\s*month\s+on\s+days?\s+/i); end
+ def _oftm(i); rex(nil, i, /\s*(day\s)?\s*of\s+the\s+month\s*/i); end
- def day_range(i)
- seq(:day_range, i, :name_day, :range_sep, :name_day)
+ def dom(i)
+ rex(:int, i, /([12][0-9]|3[01]|[0-9])/)
end
+ def and_or_dom(i)
+ seq(nil, i, :_and_or_comma, :dom)
+ end
+ def dom_list(i)
+ seq(:dom_list, i, :dom, :and_or_dom, '*')
+ end
- def _tz_name(i)
- rex(nil, i, /[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}/)
+ def dom_mod(i) # every month on day
+ seq(:dom, i, :_mod, :dom_list)
end
- def _tz_delta(i)
- rex(nil, i, /[-+]([01][0-9]|2[0-4]):?(00|15|30|45)/)
+ def dom_noftm(i) # every nth of month
+ seq(:dom, i, :ordinal, :_oftm)
end
- def _tz(i); alt(:tz, i, :_tz_delta, :_tz_name); end
+ def day_of_month(i)
+ alt(nil, i, :dom_noftm, :dom_mod)
+ end
- def interval1(i)
- rex(:interval1, i,
- /
- \d+
- \s?
- (y(ears?)?|months?|w(eeks?)?|d(ays?)?|
- h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?)
- /ix)
+ def dow_class(i)
+ rex(:dow_class, i, /(weekday)(\s+|$)/i)
end
- def min_or_sec(i)
- rex(:min_or_sec, i, /(min(ute)?|sec(ond)?)\s+\d+/i)
+ def dow(i)
+ seq(:dow, i, :weekday)
end
+ def and_or_dow(i)
+ seq(nil, i, :_and_or_comma, :dow)
+ end
+ def dow_list(i)
+ seq(:dow_list, i, :dow, :and_or_dow, '*')
+ end
- def point(i)
- alt(:point, i,
- :min_or_sec,
- :name_hour, :numeral_hour, :digital_hour, :simple_hour)
+ def to_dow_range(i)
+ seq(:dow_range, i, :weekday, :_to_through, :weekday)
end
+ def dash_dow_range(i)
+ seq(:dow_range, i, :weekday, :_dash, :weekday)
+ end
+ def dow_range(i)
+ alt(nil, i, :to_dow_range, :dash_dow_range)
+ end
- def flag(i); rex(:flag, i, /(every|from|at|after|on|in)/i); end
+ def day_of_week(i)
+ alt(nil, i, :dow_range, :dow_list, :dow_class)
+ end
- def datum(i)
- alt(nil, i,
- :flag,
- :interval1,
- :point,
- :interval0,
- :day_range, :biz_day, :name_day,
- :_tz)
+ def interval(i)
+ alt(nil, i, :sinterval, :ninterval)
end
- def sugar(i); rex(nil, i, /(and|or|[, \t]+)/i); end
+ def every_object(i)
+ alt(nil, i, :day_of_month, :interval, :day_of_week)
+ end
+ def from_object(i)
+ alt(nil, i, :interval, :to_dow_range)
+ end
- def elt(i); alt(nil, i, :sugar, :datum); end
- def nat(i); rep(:nat, i, :elt, 1); end
+ def tz(i)
+ seq(nil, i, :_in, '?', :tzone)
+ end
+ def on(i)
+ seq(:on, i, :_on, :weekday, :at_point, :and_at, '*')
+ end
+ def at(i)
+ seq(:at, i, :_at_comma, :at_point, :and_at, '*')
+ end
+ def from(i)
+ seq(:from, i, :_from, :from_object)
+ end
+ def every(i)
+ seq(:every, i, :_every, :every_object)
+ end
+ def at_from(i)
+ seq(nil, i, :at, :from, :tz, '?')
+ end
+ def at_every(i)
+ seq(nil, i, :at, :every, :tz, '?')
+ end
+
+ def from_at(i)
+ seq(nil, i, :from, :at, '?', :tz, '?')
+ end
+
+ def every_(i)
+ seq(nil, i, :every, :tz, '?')
+ end
+ def every_on(i)
+ seq(nil, i, :every, :on, :tz, '?')
+ end
+ def every_at(i)
+ seq(nil, i, :every, :at, :tz, '?')
+ end
+
+ def nat(i)
+ alt(:nat, i,
+ :every_at, :every_on, :every_,
+ :from_at,
+ :at_every, :at_from)
+ end
+
# rewrite parsed tree
- def _rewrite(t)
- [ t.name, t.string.downcase ]
+ #def _rewrite_single(t)
+ # [ t.name, rewrite(t.sublookup(nil)) ]
+ #end
+ def _rewrite_children(t)
+ t.subgather(nil).collect { |tt| rewrite(tt) }
end
- alias rewrite_flag _rewrite
- alias rewrite_interval0 _rewrite
- alias rewrite_biz_day _rewrite
+ def _rewrite_multiple(t)
+ [ t.name, _rewrite_children(t) ]
+ end
+ def _rewrite_child(t)
+ rewrite(t.sublookup(nil))
+ end
- def rewrite_name_day(t)
- [ :name_day, WEEKDAYS.index(t.string.downcase[0, 3]) ]
+ def rewrite_int(t); t.string.to_i; end
+
+ def rewrite_tzone(t)
+
+ [ :tz, t.strim ]
end
- def rewrite_day_range(t)
- [ :day_range, t.subgather(nil).collect { |st| st.string.downcase } ]
+ def rewrite_sinterval(t)
+
+ [ :interval, 1, t.strim ]
end
- def rewrite_name_hour(t)
- [ :hour, *NHOURS[t.string.strip.downcase] ]
+ def rewrite_ninterval(t)
+
+ [ :interval,
+ t.sublookup(:int).string.to_i,
+ t.sublookup(:intervals).strim ]
end
+
+ def rewrite_named_digit(t)
+
+ i = t.sublookup(:int).string.to_i
+
+ case n = t.sublookup(:dname).strim
+ when /^s/ then [ '*', '*', i ]
+ when /^m/ then [ '*', i ]
+ end
+ end
+
+ def rewrite_named_hour(t)
+ NHOURS[t.strim.downcase]
+ end
def rewrite_numeral_hour(t)
- vs = t.subgather(nil).collect { |st| st.string.downcase.strip }
+ vs = t.subgather(nil).collect { |st| st.strim.downcase }
v = NUMS.index(vs[0])
v += 12 if vs[1] == 'pm'
- [ :hour, v, 0 ]
+ m = NMINUTES[vs[2]] || 0
+ [ v, m ]
end
def rewrite_simple_hour(t)
- vs = t.subgather(nil).collect { |st| st.string.downcase.strip }
+ vs = t.subgather(nil).collect { |st| st.strim.downcase }
v = vs[0].to_i
v += 12 if vs[1] == 'pm'
- [ :hour, v, 0 ]
+ [ v, 0 ]
end
def rewrite_digital_hour(t)
- v = t.string.gsub(/:/, '')
- [ :hour, v[0, 2], v[2, 2] ]
+ m = t.string.match(/(\d\d?):?(\d\d)/)
+ [ m[1].to_i, m[2].to_i ]
end
- def rewrite_min_or_sec(t)
- unit, num = t.string.split(/\s+/)
- [ unit[0, 3].to_sym, num.to_i ]
+ def rewrite_weekday(t)
+
+ WEEKDAYS.index(t.strim.downcase[0, 3])
end
- def rewrite_point(t)
- [ :point, rewrite(t.sublookup) ]
+ def rewrite_ordinal(t); ORDINALS[t.strim]; end
+
+ def rewrite_dom(t)
+
+#Raabro.pp(t, colours: true)
+ [ :day_of_month,
+ *_rewrite_children(t).flatten.select { |e| e.is_a?(Integer) } ]
end
- def rewrite_tz(t)
- [ :tz, [ t.string.strip, EtOrbi.get_tzone(t.string.strip) ] ]
+ alias rewrite_dow _rewrite_child
+
+ def rewrite_dom_list(t); [ :dom_list, *_rewrite_children(t) ]; end
+ def rewrite_dow_list(t); [ :dow_list, *_rewrite_children(t) ]; end
+
+ def rewrite_dow_class(t)
+
+ [ :dow_range, 1, 5 ] # only "weekday" for now
end
- def rewrite_interval1(t)
- [ t.name, [ Fugit::Duration.parse(t.string.strip) ] ]
+ def rewrite_dow_range(t)
+
+ tts = t.subgather(nil)
+
+ [ :dow_range, rewrite(tts[0]), rewrite(tts[1]) ]
end
+ alias rewrite_on _rewrite_multiple
+ alias rewrite_at _rewrite_multiple
+
+ alias rewrite_from _rewrite_child
+ alias rewrite_every _rewrite_child
+
def rewrite_nat(t)
-#Raabro.pp(t, colours: true)
t.subgather(nil).collect { |tt| rewrite(tt) }
+#.tap { |x| pp x }
end
end
end
end