Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editorial: Collapse nonterminals only used for disambiguation #2767

Merged
merged 1 commit into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 73 additions & 58 deletions polyfill/test/validStrings.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -225,26 +225,11 @@ const dateYear = withCode(
const dateMonth = withCode(zeroPaddedInclusive(1, 12, 2), (data, result) => (data.month = +result));
const dateDay = withCode(zeroPaddedInclusive(1, 31, 2), (data, result) => (data.day = +result));

function saveHour(data, result) {
data.hour = +result;
}
function saveMinute(data, result) {
data.minute = +result;
}
function saveSecond(data, result) {
data.second = +result;
if (data.second === 60) data.second = 59;
}
const timeHour = withCode(hour, saveHour);
const timeMinute = withCode(minuteSecond, saveMinute);
const timeSecond = withCode(choice(minuteSecond, '60'), saveSecond);
const timeFraction = withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const fraction = result.padEnd(9, '0');
data.millisecond = +fraction.slice(0, 3);
data.microsecond = +fraction.slice(3, 6);
data.nanosecond = +fraction.slice(6, 9);
});

function saveOffset(data, result) {
data.offset = ES.ParseDateTimeUTCOffset(result);
Expand All @@ -266,10 +251,9 @@ const utcOffset = (subMinutePrecision) =>
]);
const dateTimeUTCOffset = (z) =>
z ? choice(utcDesignator, withCode(utcOffset(true), saveOffset)) : withCode(utcOffset(true), saveOffset);
const timeZoneUTCOffsetName = utcOffset(false);
const timeZoneIANAName = choice(...timezoneNames);
const timeZoneIdentifier = withCode(
choice(timeZoneUTCOffsetName, timeZoneIANAName),
choice(utcOffset(false), timeZoneIANAName),
(data, result) => (data.tzAnnotation = result)
);
const timeZoneAnnotation = seq('[', [annotationCriticalFlag], timeZoneIdentifier, ']');
Expand All @@ -291,7 +275,26 @@ const annotations = withSyntaxConstraints(oneOrMore(choice(calendarAnnotation, a
}
});
const timeSpec = (extended) =>
seq(timeHour, [timeSeparator(extended), timeMinute, [timeSeparator(extended), timeSecond, [timeFraction]]]);
seq(
withCode(hour, (data, result) => (data.hour = +result)),
[
timeSeparator(extended),
withCode(minuteSecond, (data, result) => (data.minute = +result)),
[
timeSeparator(extended),
timeSecond,
[
withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const fraction = result.padEnd(9, '0');
data.millisecond = +fraction.slice(0, 3);
data.microsecond = +fraction.slice(3, 6);
data.nanosecond = +fraction.slice(6, 9);
})
]
]
]
);
const time = choice(timeSpec(true), timeSpec(false));

function validateDayOfMonth(result, { year, month, day }) {
Expand Down Expand Up @@ -349,72 +352,84 @@ const annotatedMonthDay = withSyntaxConstraints(
}
);

const durationSecondsFraction = withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const fraction = result.padEnd(9, '0');
data.milliseconds = +fraction.slice(0, 3) * data.factor;
data.microseconds = +fraction.slice(3, 6) * data.factor;
data.nanoseconds = +fraction.slice(6, 9) * data.factor;
});
const durationMinutesFraction = withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const ns = +result.padEnd(9, '0') * 60;
data.seconds = Math.trunc(ns / 1e9) * data.factor;
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
});
const durationHoursFraction = withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const ns = +result.padEnd(9, '0') * 3600;
data.minutes = Math.trunc(ns / 6e10) * data.factor;
data.seconds = Math.trunc((ns % 6e10) / 1e9) * data.factor;
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
});

const uint32Digits = withSyntaxConstraints(between(1, 10, digit()), (result) => {
if (+result >= 2 ** 32) throw new SyntaxError('try again for an uint32');
});
const timeDurationDigits = (factor) =>
withSyntaxConstraints(between(1, 16, digit()), (result) => {
if (!Number.isSafeInteger(+result * factor)) throw new SyntaxError('try again on unsafe integer');
});
const durationSeconds = seq(
const durationSecondsPart = seq(
withCode(timeDurationDigits(1), (data, result) => (data.seconds = +result * data.factor)),
[durationSecondsFraction],
[
withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const fraction = result.padEnd(9, '0');
data.milliseconds = +fraction.slice(0, 3) * data.factor;
data.microseconds = +fraction.slice(3, 6) * data.factor;
data.nanoseconds = +fraction.slice(6, 9) * data.factor;
})
],
secondsDesignator
);
const durationMinutes = seq(
const durationMinutesPart = seq(
withCode(timeDurationDigits(60), (data, result) => (data.minutes = +result * data.factor)),
choice(seq(minutesDesignator, [durationSeconds]), seq(durationMinutesFraction, minutesDesignator))
choice(
seq(minutesDesignator, [durationSecondsPart]),
seq(
withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const ns = +result.padEnd(9, '0') * 60;
data.seconds = Math.trunc(ns / 1e9) * data.factor;
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
}),
minutesDesignator
)
)
);
const durationHours = seq(
const durationHoursPart = seq(
withCode(timeDurationDigits(3600), (data, result) => (data.hours = +result * data.factor)),
choice(seq(hoursDesignator, [choice(durationMinutes, durationSeconds)]), seq(durationHoursFraction, hoursDesignator))
choice(
seq(hoursDesignator, [choice(durationMinutesPart, durationSecondsPart)]),
seq(
withCode(temporalDecimalFraction, (data, result) => {
result = result.slice(1);
const ns = +result.padEnd(9, '0') * 3600;
data.minutes = Math.trunc(ns / 6e10) * data.factor;
data.seconds = Math.trunc((ns % 6e10) / 1e9) * data.factor;
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
}),
hoursDesignator
)
)
);
const durationTime = seq(timeDesignator, choice(durationHours, durationMinutes, durationSeconds));
const durationDays = seq(
const durationTime = seq(timeDesignator, choice(durationHoursPart, durationMinutesPart, durationSecondsPart));
const durationDaysPart = seq(
withCode(timeDurationDigits(86400), (data, result) => (data.days = +result * data.factor)),
daysDesignator
);
const durationWeeks = seq(
const durationWeeksPart = seq(
withCode(uint32Digits, (data, result) => (data.weeks = +result * data.factor)),
weeksDesignator,
[durationDays]
[durationDaysPart]
);
const durationMonths = seq(
const durationMonthsPart = seq(
withCode(uint32Digits, (data, result) => (data.months = +result * data.factor)),
monthsDesignator,
[choice(durationWeeks, durationDays)]
[choice(durationWeeksPart, durationDaysPart)]
);
const durationYears = seq(
const durationYearsPart = seq(
withCode(uint32Digits, (data, result) => (data.years = +result * data.factor)),
yearsDesignator,
[choice(durationMonths, durationWeeks, durationDays)]
[choice(durationMonthsPart, durationWeeksPart, durationDaysPart)]
);
const durationDate = seq(choice(durationYears, durationMonths, durationWeeks, durationDays), [durationTime]);
const durationDate = seq(choice(durationYearsPart, durationMonthsPart, durationWeeksPart, durationDaysPart), [
durationTime
]);
const duration = withSyntaxConstraints(
seq(
withCode([temporalSign], (data, result) => (data.factor = result === '-' || result === '\u2212' ? -1 : 1)),
Expand Down
121 changes: 60 additions & 61 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -1265,19 +1265,10 @@ <h1>ISO 8601 grammar</h1>
DateSpec[+Extended]
DateSpec[~Extended]

TimeHour :::
Hour

TimeMinute :::
MinuteSecond

TimeSecond :::
MinuteSecond
`60`

TimeFraction :::
TemporalDecimalFraction

NormalizedUTCOffset :::
ASCIISign Hour TimeSeparator[+Extended] MinuteSecond

Expand All @@ -1292,9 +1283,6 @@ <h1>ISO 8601 grammar</h1>
[+Z] UTCDesignator
UTCOffset[+SubMinutePrecision]

TimeZoneUTCOffsetName :::
UTCOffset[~SubMinutePrecision]

TZLeadingChar :::
Alpha
`.`
Expand All @@ -1315,7 +1303,7 @@ <h1>ISO 8601 grammar</h1>
TimeZoneIANAName `/` TimeZoneIANANameComponent

TimeZoneIdentifier :::
TimeZoneUTCOffsetName
UTCOffset[~SubMinutePrecision]
TimeZoneIANAName

TimeZoneAnnotation :::
Expand Down Expand Up @@ -1349,9 +1337,9 @@ <h1>ISO 8601 grammar</h1>
Annotation Annotations?

TimeSpec[Extended] :::
TimeHour
TimeHour TimeSeparator[?Extended] TimeMinute
TimeHour TimeSeparator[?Extended] TimeMinute TimeSeparator[?Extended] TimeSecond TimeFraction?
Hour
Hour TimeSeparator[?Extended] MinuteSecond
Hour TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] TimeSecond TemporalDecimalFraction?

Time :::
TimeSpec[+Extended]
Expand All @@ -1375,67 +1363,37 @@ <h1>ISO 8601 grammar</h1>
AnnotatedMonthDay :::
DateSpecMonthDay TimeZoneAnnotation? Annotations?

DurationWholeSeconds :::
DecimalDigits[~Sep]

DurationSecondsFraction :::
TimeFraction

DurationSecondsPart :::
DurationWholeSeconds DurationSecondsFraction? SecondsDesignator

DurationWholeMinutes :::
DecimalDigits[~Sep]

DurationMinutesFraction :::
TimeFraction
DecimalDigits[~Sep] TemporalDecimalFraction? SecondsDesignator

DurationMinutesPart :::
DurationWholeMinutes DurationMinutesFraction MinutesDesignator
DurationWholeMinutes MinutesDesignator DurationSecondsPart?

DurationWholeHours :::
DecimalDigits[~Sep]

DurationHoursFraction :::
TimeFraction
DecimalDigits[~Sep] TemporalDecimalFraction MinutesDesignator
DecimalDigits[~Sep] MinutesDesignator DurationSecondsPart?

DurationHoursPart :::
DurationWholeHours DurationHoursFraction HoursDesignator
DurationWholeHours HoursDesignator DurationMinutesPart
DurationWholeHours HoursDesignator DurationSecondsPart?
DecimalDigits[~Sep] TemporalDecimalFraction HoursDesignator
DecimalDigits[~Sep] HoursDesignator DurationMinutesPart
DecimalDigits[~Sep] HoursDesignator DurationSecondsPart?

DurationTime :::
TimeDesignator DurationHoursPart
TimeDesignator DurationMinutesPart
TimeDesignator DurationSecondsPart

DurationDays :::
DecimalDigits[~Sep]

DurationDaysPart :::
DurationDays DaysDesignator

DurationWeeks :::
DecimalDigits[~Sep]
DecimalDigits[~Sep] DaysDesignator

DurationWeeksPart :::
DurationWeeks WeeksDesignator DurationDaysPart?

DurationMonths :::
DecimalDigits[~Sep]
DecimalDigits[~Sep] WeeksDesignator DurationDaysPart?

DurationMonthsPart :::
DurationMonths MonthsDesignator DurationWeeksPart
DurationMonths MonthsDesignator DurationDaysPart?

DurationYears :::
DecimalDigits[~Sep]
DecimalDigits[~Sep] MonthsDesignator DurationWeeksPart
DecimalDigits[~Sep] MonthsDesignator DurationDaysPart?

DurationYearsPart :::
DurationYears YearsDesignator DurationMonthsPart
DurationYears YearsDesignator DurationWeeksPart
DurationYears YearsDesignator DurationDaysPart?
DecimalDigits[~Sep] YearsDesignator DurationMonthsPart
DecimalDigits[~Sep] YearsDesignator DurationWeeksPart
DecimalDigits[~Sep] YearsDesignator DurationDaysPart?

DurationDate :::
DurationYearsPart DurationTime?
Expand Down Expand Up @@ -1579,7 +1537,7 @@ <h1>
1. If _goal_ is |TemporalMonthDayString| or |TemporalYearMonthString|, _calendar_ is not ~empty~, and the ASCII-lowercase of _calendar_ is not *"iso8601"*, throw a *RangeError* exception.
1. If _parseResult_ is not a Parse Node, throw a *RangeError* exception.
1. NOTE: Applications of StringToNumber below do not lose precision, since each of the parsed values is guaranteed to be a sufficiently short string of decimal digits.
1. Let each of _year_, _month_, _day_, _hour_, _minute_, _second_, and _fSeconds_ be the source text matched by the respective |DateYear|, |DateMonth|, |DateDay|, |TimeHour|, |TimeMinute|, |TimeSecond|, and |TimeFraction| Parse Node contained within _parseResult_, or an empty sequence of code points if not present.
1. Let each of _year_, _month_, _day_, _hour_, _minute_, _second_, and _fSeconds_ be the source text matched by the respective |DateYear|, |DateMonth|, |DateDay|, the first |Hour|, the first |MinuteSecond|, |TimeSecond|, and the first |TemporalDecimalFraction| Parse Node contained within _parseResult_, or an empty sequence of code points if not present.
1. If the first code point of _year_ is U+2212 (MINUS SIGN), replace the first code point with U+002D (HYPHEN-MINUS).
1. Let _yearMV_ be ℝ(StringToNumber(CodePointsToString(_year_))).
1. If _month_ is empty, then
Expand Down Expand Up @@ -1766,7 +1724,48 @@ <h1>
<emu-alg>
1. Let _duration_ be ParseText(StringToCodePoints(_isoString_), |TemporalDurationString|).
1. If _duration_ is a List of errors, throw a *RangeError* exception.
1. Let each of _sign_, _years_, _months_, _weeks_, _days_, _hours_, _fHours_, _minutes_, _fMinutes_, _seconds_, and _fSeconds_ be the source text matched by the respective |TemporalSign|, |DurationYears|, |DurationMonths|, |DurationWeeks|, |DurationDays|, |DurationWholeHours|, |DurationHoursFraction|, |DurationWholeMinutes|, |DurationMinutesFraction|, |DurationWholeSeconds|, and |DurationSecondsFraction| Parse Node contained within _duration_, or an empty sequence of code points if not present.
1. Let _sign_ be the source text matched by the |TemporalSign| Parse Node contained within _duration_, or an empty sequence of code points if not present.
1. If _duration_ contains a |DurationYearsPart| Parse Node, then
1. Let _yearsNode_ be that |DurationYearsPart| Parse Node contained within _duration_.
1. Let _years_ be the source text matched by the |DecimalDigits| Parse Node contained within _yearsNode_.
1. Else,
1. Let _years_ be an empty sequence of code points.
1. If _duration_ contains a |DurationMonthsPart| Parse Node, then
1. Let _monthsNode_ be the |DurationMonthsPart| Parse Node contained within _duration_.
1. Let _months_ be the source text matched by the |DecimalDigits| Parse Node contained within _monthsNode_.
1. Else,
1. Let _months_ be an empty sequence of code points.
1. If _duration_ contains a |DurationWeeksPart| Parse Node, then
1. Let _weeksNode_ be the |DurationWeeksPart| Parse Node contained within _duration_.
1. Let _weeks_ be the source text matched by the |DecimalDigits| Parse Node contained within _weeksNode_.
1. Else,
1. Let _weeks_ be an empty sequence of code points.
1. If _duration_ contains a |DurationDaysPart| Parse Node, then
1. Let _daysNode_ be the |DurationDaysPart| Parse Node contained within _duration_.
1. Let _days_ be the source text matched by the |DecimalDigits| Parse Node contained within _daysNode_.
1. Else,
1. Let _days_ be an empty sequence of code points.
1. If _duration_ contains a |DurationHoursPart| Parse Node, then
1. Let _hoursNode_ be the |DurationHoursPart| Parse Node contained within _duration_.
1. Let _hours_ be the source text matched by the |DecimalDigits| Parse Node contained within _hoursNode_.
1. Let _fHours_ be the source text matched by the |TemporalDecimalFraction| Parse Node contained within _hoursNode_, or an empty sequence of code points if not present.
1. Else,
1. Let _hours_ be an empty sequence of code points.
1. Let _fHours_ be an empty sequence of code points.
1. If _duration_ contains a |DurationMinutesPart| Parse Node, then
1. Let _minutesNode_ be the |DurationMinutesPart| Parse Node contained within _duration_.
1. Let _minutes_ be the source text matched by the |DecimalDigits| Parse Node contained within _minutesNode_.
1. Let _fMinutes_ be the source text matched by the |TemporalDecimalFraction| Parse Node contained within _minutesNode_, or an empty sequence of code points if not present.
1. Else,
1. Let _minutes_ be an empty sequence of code points.
1. Let _fMinutes_ be an empty sequence of code points.
1. If _duration_ contains a |DurationSecondsPart| Parse Node, then
1. Let _secondsNode_ be the |DurationSecondsPart| Parse Node contained within _duration_.
1. Let _seconds_ be the source text matched by the |DecimalDigits| Parse Node contained within _secondsNode_.
1. Let _fSeconds_ be the source text matched by the |TemporalDecimalFraction| Parse Node contained within _secondsNode_, or an empty sequence of code points if not present.
1. Else,
1. Let _seconds_ be an empty sequence of code points.
1. Let _fSeconds_ be an empty sequence of code points.
1. Let _yearsMV_ be ? ToIntegerWithTruncation(CodePointsToString(_years_)).
1. Let _monthsMV_ be ? ToIntegerWithTruncation(CodePointsToString(_months_)).
1. Let _weeksMV_ be ? ToIntegerWithTruncation(CodePointsToString(_weeks_)).
Expand Down
Loading
Loading