Skip to content

Commit

Permalink
Editorial: Use early errors to simplify time-only grammar
Browse files Browse the repository at this point in the history
Previously the grammar relied on bizarre one-off productions such as
TimeSpecWithOptionalOffsetNotAmbiguous and DateMonthWithThirtyOneDays, to
prevent time strings such as 0119 (01:19 but ambiguous with 19th January)
or 1524-08 (15:24 at -08:00 from UTC, but ambiguous with August of 1524)
from parsing correctly without a time designator.

By using early errors, these confusing productions are no longer necessary
to achieve the desired result.

Closes: #1984
  • Loading branch information
ptomato committed Jun 13, 2024
1 parent 9e9a7f7 commit c30c407
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 23 deletions.
21 changes: 12 additions & 9 deletions polyfill/test/validStrings.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,6 @@ const timeSpec = seq(
timeHour,
choice([':', timeMinute, [':', timeSecond, [timeFraction]]], seq(timeMinute, [timeSecond, [timeFraction]]))
);
const timeSpecWithOptionalOffsetNotAmbiguous = withSyntaxConstraints(seq(timeSpec, [dateTimeUTCOffset]), (result) => {
if (/^(?:(?!02-?30)(?:0[1-9]|1[012])-?(?:0[1-9]|[12][0-9]|30)|(?:0[13578]|10|12)-?31)$/.test(result)) {
throw new SyntaxError('valid PlainMonthDay');
}
if (/^(?![-]000000)(?:[0-9]{4}|[+-][0-9]{6})-?(?:0[1-9]|1[012])$/.test(result)) {
throw new SyntaxError('valid PlainYearMonth');
}
});

function validateDayOfMonth(result, { year, month, day }) {
if (day > ES.ISODaysInMonth(year, month)) throw SyntaxError('retry if bad day of month');
Expand All @@ -306,7 +298,18 @@ const date = withSyntaxConstraints(
const dateTime = seq(date, [dateTimeSeparator, timeSpec, [dateTimeUTCOffset]]);
const annotatedTime = choice(
seq(timeDesignator, timeSpec, [dateTimeUTCOffset], [timeZoneAnnotation], [annotations]),
seq(timeSpecWithOptionalOffsetNotAmbiguous, [timeZoneAnnotation], [annotations])
seq(
withSyntaxConstraints(seq(timeSpec, [dateTimeUTCOffset]), (result) => {
if (/^(?:(?!02-?30)(?:0[1-9]|1[012])-?(?:0[1-9]|[12][0-9]|30)|(?:0[13578]|10|12)-?31)$/.test(result)) {
throw new SyntaxError('valid PlainMonthDay');
}
if (/^(?![-]000000)(?:[0-9]{4}|[+-][0-9]{6})-?(?:0[1-9]|1[012])$/.test(result)) {
throw new SyntaxError('valid PlainYearMonth');
}
}),
[timeZoneAnnotation],
[annotations]
)
);
const annotatedDateTime = seq(dateTime, [timeZoneAnnotation], [annotations]);
const annotatedDateTimeTimeRequired = seq(
Expand Down
27 changes: 13 additions & 14 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -1239,9 +1239,6 @@ <h1>ISO 8601 grammar</h1>
`11`
`12`

DateMonthWithThirtyOneDays ::: one of
`01` `03` `05` `07` `08` `10` `12`

DateDay :::
`0` NonZeroDigit
`1` DecimalDigit
Expand All @@ -1256,13 +1253,6 @@ <h1>ISO 8601 grammar</h1>
`--` DateMonth `-`? DateDay
DateMonth `-`? DateDay

ValidMonthDay :::
DateMonth `-`? `0` NonZeroDigit
DateMonth `-`? `1` DecimalDigit
DateMonth `-`? `2` DecimalDigit
DateMonth `-`? `30` but not one of `0230` or `02-30`
DateMonthWithThirtyOneDays `-`? `31`

Date :::
DateYear `-` DateMonth `-` DateDay
DateYear DateMonth DateDay
Expand Down Expand Up @@ -1363,16 +1353,13 @@ <h1>ISO 8601 grammar</h1>
TimeHour `:` TimeMinute `:` TimeSecond TimeFraction?
TimeHour TimeMinute TimeSecond TimeFraction?

TimeSpecWithOptionalOffsetNotAmbiguous :::
TimeSpec DateTimeUTCOffset? but not one of ValidMonthDay or DateSpecYearMonth

DateTime :::
Date
Date DateTimeSeparator TimeSpec DateTimeUTCOffset?

AnnotatedTime :::
TimeDesignator TimeSpec DateTimeUTCOffset? TimeZoneAnnotation? Annotations?
TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotation? Annotations?
TimeSpec DateTimeUTCOffset? TimeZoneAnnotation? Annotations?

AnnotatedDateTime[Zoned] :::
[~Zoned] DateTime TimeZoneAnnotation? Annotations?
Expand Down Expand Up @@ -1518,6 +1505,18 @@ <h1>Static Semantics: IsValidDate ( ): a Boolean</h1>

<emu-clause id="sec-temporal-iso8601grammar-static-semantics-early-errors">
<h1>Static Semantics: Early Errors</h1>
<emu-grammar>
AnnotatedTime :::
TimeSpec DateTimeUTCOffset? TimeZoneAnnotation? Annotations?
</emu-grammar>
<ul>
<li>
It is a Syntax Error if IsValidMonthDay of ParseText(|TimeSpec| |DateTimeUTCOffset|, |DateSpecMonthDay|) is *true*.
</li>
<li>
It is a Syntax Error if ParseText(|TimeSpec| |DateTimeUTCOffset|, |DateSpecYearMonth|) is a Parse Node.
</li>
</ul>
<emu-grammar>
Date :::
DateYear `-` DateMonth `-` DateDay
Expand Down

0 comments on commit c30c407

Please sign in to comment.