lib/schedulability/parser.rb in schedulability-0.1.0 vs lib/schedulability/parser.rb in schedulability-0.2.0

- old
+ new

@@ -54,19 +54,47 @@ ############### module_function ############### + ### Normalize an array of parsed periods into a human readable string. + def stringify( periods ) + strings = [] + periods.each do |period| + period_string = [] + period.sort_by{|k, v| k}.each do |scale, ranges| + range_string = "" + range_string << "%s { " % [ scale.to_s ] + + range_strings = ranges.each_with_object( [] ).each do |range, acc| + if range.min == range.max + acc << range.min + elsif range.exclude_end? + acc << "%d-%d" % [ range.min, range.max + 1 ] + else + acc << "%d-%d" % [ range.min, range.max ] + end + end + + range_string << range_strings.join( ' ' ) << " }" + period_string << range_string + end + strings << period_string.join( ' ' ) + end + + return strings.join( ', ' ) + end + + ### Scan +expression+ for periods and return them in an Array. def extract_periods( expression ) positive_periods = [] negative_periods = [] expression.strip.downcase.split( /\s*,\s*/ ).each do |subexpr| hash, negative = self.extract_period( subexpr ) if negative - self.log.debug "Adding %p to the negative " negative_periods << hash else positive_periods << hash end end @@ -79,11 +107,10 @@ def extract_period( expression ) hash = {} scanner = StringScanner.new( expression ) negative = scanner.skip( /\s*(!|not |except )\s*/ ) - self.log.debug "Period %p is %snegative!" % [ expression, negative ? "" : "not " ] while scanner.scan( PERIOD_PATTERN ) ranges = scanner[:ranges].strip scale = scanner[:scale] @@ -185,19 +212,19 @@ end ### Return an Array of Integer minute Ranges for the specified +ranges+ expression. def extract_minute_ranges( ranges ) - return self.extract_ranges( :minute, ranges, 0, 59 ) do |val| + return self.extract_ranges( :minute, ranges, 0, 60 ) do |val| Integer( strip_leading_zeros(val) ) end end ### Return an Array of Integer second Ranges for the specified +ranges+ expression. def extract_second_ranges( ranges ) - return self.extract_ranges( :second, ranges, 0, 59 ) do |val| + return self.extract_ranges( :second, ranges, 0, 60 ) do |val| Integer( strip_leading_zeros(val) ) end end @@ -231,24 +258,21 @@ exclude_end = EXCLUSIVE_RANGED_SCALES.include?( scale ) valid_range = Range.new( minval, maxval, exclude_end ) ints = ranges.split( /(?<!-)\s+(?!-)/ ).flat_map do |range| min, max = range.split( /\s*-\s*/, 2 ) - self.log.debug "Min = %p, max = %p" % [ min, max ] min = yield( min ) raise Schedulability::ParseError, "invalid %s value: %p" % [ scale, min ] unless valid_range.cover?( min ) next [ min ] unless max max = yield( max ) raise Schedulability::ParseError, "invalid %s value: %p" % [ scale, max ] unless valid_range.cover?( max ) - self.log.debug "Parsed min = %p, max = %p" % [ min, max ] if min > max - self.log.debug "wrapped: %d-%d and %d-%d" % [ minval, max, min, maxval ] Range.new( minval, max, exclude_end ).to_a + Range.new( min, maxval, false ).to_a else Range.new( min, max, exclude_end ).to_a end @@ -259,12 +283,10 @@ ### Coalese an Array of non-contiguous Range objects from the specified +ints+ for +scale+. def coalesce_ranges( ints, scale ) exclude_end = EXCLUSIVE_RANGED_SCALES.include?( scale ) - self.log.debug "Coalescing %d ints to Ranges (%p, %s)" % - [ ints.size, ints, exclude_end ? "exclusive" : "inclusive" ] ints.flatten! return [] if ints.empty? prev = ints[0] range_ints = ints.sort.slice_before do |v| @@ -274,12 +296,10 @@ return range_ints.map do |values| last_val = values.last last_val += 1 if exclude_end Range.new( values.first, last_val, exclude_end ) - end.tap do |ranges| - self.log.debug "Coalesced range integers to Ranges: %p" % [ ranges ] end end ### Map a +value+ from a period's range to an Integer, using the specified +index_arrays+ @@ -300,10 +320,12 @@ return index end ### Return a copy of the specified +val+ with any leading zeros stripped. + ### If the resulting string is empty, return "0". def strip_leading_zeros( val ) - return val.sub( /\A0+/, '' ) + return val.sub( /\A0+(?!$)/, '' ) end end # module Schedulability::Parser +