A range like `1-5` names every value between two endpoints. Today you teach a single list-part to expand a hyphenated range into the full run of values it covers, still bounds-checked.
Compile a hyphenated range into the set of every value from its low to its high endpoint.
A range is a compact way to name a contiguous run of values: 1-5 in the
minute field means minutes 1, 2, 3, 4, and 5. It is just another kind of list
part, so it slots into the comma-splitting you built for lists - each part is
parsed on its own and unioned into the field’s set. That is why 1-3,5 works the
moment ranges do: the first part expands to a run, the second is a plain number,
and the union is {1, 2, 3, 5}.
Enforce two things while expanding. Both endpoints must sit inside the field’s
bounds, so 1-70 fails in the minute field. And the low endpoint must not exceed
the high one - a backwards range like 5-2 is meaningless, so reject it rather
than silently producing an empty set. Pinning the backwards-range error now keeps
the field grammar honest as steps arrive next.
// inside the per-part parser, before the single-number path:if i := strings.Index(part, "-"); i >= 0 {lo := atoi(part[:i]); hi := atoi(part[i+1:])// error if lo > hi, or either endpoint is out of the field bounds,// then add every value lo..hi to the set}