build-a-cron-parser / lesson-06.md
Lesson 06 · Field syntax

Ranges

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.

The goal

Compile a hyphenated range into the set of every value from its low to its high endpoint.

Start here - the target
TO DO
Scenario: A range expands to every value between its endpoints
Giventhe minute field
WhenparseField compiles '1-5'
Thenthe set is {1, 2, 3, 4, 5}
AndparseField compiles '1-3,5' to {1, 2, 3, 5}, and '5-2' (low above high) returns an error
Background

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.

Make it work
// 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
}
CheckpointDONE
A hyphenated range expands to the run of values it covers. Commit and stop here.