############################################################################ # # File: indices.icn # # Subject: Procedure to produce indices # # Author: Ralph E. Griswold # # Date: June 2, 1998 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # indices(spec, last) # produces a list of the integers given by the # specification spec, which is a common separated list # of either positive integers or integer spans, as in # # "1,3-10, ..." # # If last is specified, it it used for a span of # the form "10-". # # In an integer span, the low and high values need not # be in order. For example, "1-10" and "10-1" # are equivalent. Similarly, indices need not be # in order, as in "3-10, 1, ..." # # And empty value, as in "10,,12" is ignored. # # indices() fails if the specification is syntactically # erroneous or if it contains a value less than 1. # ############################################################################ procedure indices(spec, last) #: generate indices local item, hi, lo, result if \last then last := (0 < integer(last)) | fail result := set() spec ? { while item := tab(upto(',') | 0) do { if item := integer(item) then ((insert(result, 0 < item)) | fail) else if *item = 0 then { move(1) | break next } else item ? { (lo := (0 < integer(tab(upto('-')))) | fail) move(1) hi := (if pos(0) then last else ((0 < integer(tab(0)) | fail))) /hi := lo if lo > hi then lo :=: hi every insert(result, lo to hi) } move(1) | break } } return sort(result) end