Verified Cedar Extension Parsers in Lean 4

2.3. Parser🔗

Duration.parse returns some d when the input string is valid, and none otherwise. It first splits off an optional leading '-' with isNegativeDuration, then hands the remaining body to parseDuration? (shown here directly from its source in Cedar.Spec.Ext.Datetime):

public def Duration.parse (str : String) : Option Duration := let (isNegative, restStr) := isNegativeDuration str parseDuration? isNegative restStr

parseDuration? consumes each unit suffix in largest-to-smallest order (d, h, m, s, ms are peeled from the right), accumulates the signed millisecond total, and requires that the body be fully consumed. Because the units are matched in a fixed order, out-of-order strings like 1h30m1d are rejected:

def parseDuration? (isNegative : Bool) (str : String) : Option Duration := do if str.isEmpty then failure let (milliseconds, restStr) parseUnit? isNegative str "ms" let (seconds, restStr) parseUnit? isNegative restStr "s" let (minutes, restStr) parseUnit? isNegative restStr "m" let (hours, restStr) parseUnit? isNegative restStr "h" let (days, restStr) parseUnit? isNegative restStr "d" if restStr.isEmpty then duration? (days + hours + minutes + seconds + milliseconds) else none

For example:

some "1d2h30m0s0ms"#eval (Duration.parse "1d2h30m").map Duration.toString -- valid
some "1d2h30m0s0ms"
some "-0d1h30m0s0ms"#eval (Duration.parse "-1h30m").map Duration.toString -- negative
some "-0d1h30m0s0ms"
none#eval Duration.parse "1h30m1d" -- out of order
none
none#eval Duration.parse "" -- empty
none