1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 19:17:35 +00:00

LibJS: Require 'T' prefix for ambiguous time-only strings

This is a normative change in the Temporal spec.

See: 514ede3
This commit is contained in:
Linus Groh 2021-12-22 22:44:46 +01:00
parent a73c71e877
commit 3ab1c52e2b
4 changed files with 443 additions and 29 deletions

View file

@ -416,6 +416,169 @@ bool ISO8601Parser::parse_time_second()
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeHourNotValidMonth
bool ISO8601Parser::parse_time_hour_not_valid_month()
{
// TimeHourNotValidMonth : one of
// 00 13 14 15 16 17 18 19 20 21 23
StateTransaction transaction { *this };
auto success = m_state.lexer.consume_specific("00"sv)
|| m_state.lexer.consume_specific("13"sv)
|| m_state.lexer.consume_specific("14"sv)
|| m_state.lexer.consume_specific("15"sv)
|| m_state.lexer.consume_specific("16"sv)
|| m_state.lexer.consume_specific("17"sv)
|| m_state.lexer.consume_specific("18"sv)
|| m_state.lexer.consume_specific("19"sv)
|| m_state.lexer.consume_specific("20"sv)
|| m_state.lexer.consume_specific("21"sv)
|| m_state.lexer.consume_specific("22"sv)
|| m_state.lexer.consume_specific("23"sv);
if (!success)
return false;
m_state.parse_result.time_hour_not_valid_month = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeHourNotThirtyOneDayMonth
bool ISO8601Parser::parse_time_hour_not_thirty_one_day_month()
{
// TimeHourNotThirtyOneDayMonth : one of
// 02 04 06 09 11
StateTransaction transaction { *this };
auto success = m_state.lexer.consume_specific("02"sv)
|| m_state.lexer.consume_specific("04"sv)
|| m_state.lexer.consume_specific("06"sv)
|| m_state.lexer.consume_specific("09"sv)
|| m_state.lexer.consume_specific("11"sv);
if (!success)
return false;
m_state.parse_result.time_hour_not_thirty_one_day_month = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeHourTwoOnly
bool ISO8601Parser::parse_time_hour_two_only()
{
// TimeHourTwoOnly :
// 02
StateTransaction transaction { *this };
if (!m_state.lexer.consume_specific("02"sv))
return false;
m_state.parse_result.time_hour_two_only = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeMinuteNotValidDay
bool ISO8601Parser::parse_time_minute_not_valid_day()
{
// TimeMinuteNotValidDay :
// 00
// 32
// 33
// 34
// 35
// 36
// 37
// 38
// 39
// 4 DecimalDigit
// 5 DecimalDigit
// 60
StateTransaction transaction { *this };
if (m_state.lexer.consume_specific('4') || m_state.lexer.consume_specific('5')) {
if (!parse_decimal_digit())
return false;
} else {
auto success = m_state.lexer.consume_specific("00"sv)
|| m_state.lexer.consume_specific("32"sv)
|| m_state.lexer.consume_specific("33"sv)
|| m_state.lexer.consume_specific("34"sv)
|| m_state.lexer.consume_specific("35"sv)
|| m_state.lexer.consume_specific("36"sv)
|| m_state.lexer.consume_specific("37"sv)
|| m_state.lexer.consume_specific("38"sv)
|| m_state.lexer.consume_specific("39"sv)
|| m_state.lexer.consume_specific("60"sv);
if (!success)
return false;
}
m_state.parse_result.time_minute_not_valid_day = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeMinuteThirtyOnly
bool ISO8601Parser::parse_time_minute_thirty_only()
{
// TimeMinuteThirtyOnly :
// 30
StateTransaction transaction { *this };
if (!m_state.lexer.consume_specific("30"sv))
return false;
m_state.parse_result.time_minute_thirty_only = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeMinuteThirtyOneOnly
bool ISO8601Parser::parse_time_minute_thirty_one_only()
{
// TimeMinuteThirtyOneOnly :
// 31
StateTransaction transaction { *this };
if (!m_state.lexer.consume_specific("31"sv))
return false;
m_state.parse_result.time_minute_thirty_one_only = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeSecondNotValidMonth
bool ISO8601Parser::parse_time_second_not_valid_month()
{
// TimeSecondNotValidMonth :
// 00
// 13
// 14
// 15
// 16
// 17
// 18
// 19
// 2 DecimalDigit
// 3 DecimalDigit
// 4 DecimalDigit
// 5 DecimalDigit
// 60
StateTransaction transaction { *this };
if (m_state.lexer.consume_specific('2')
|| m_state.lexer.consume_specific('3')
|| m_state.lexer.consume_specific('4')
|| m_state.lexer.consume_specific('5')) {
if (!parse_decimal_digit())
return false;
} else {
auto success = m_state.lexer.consume_specific("00"sv)
|| m_state.lexer.consume_specific("13"sv)
|| m_state.lexer.consume_specific("14"sv)
|| m_state.lexer.consume_specific("15"sv)
|| m_state.lexer.consume_specific("16"sv)
|| m_state.lexer.consume_specific("17"sv)
|| m_state.lexer.consume_specific("18"sv)
|| m_state.lexer.consume_specific("19"sv)
|| m_state.lexer.consume_specific("60"sv);
if (!success)
return false;
}
m_state.parse_result.time_second_not_valid_month = transaction.parsed_string_view();
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-FractionalPart
bool ISO8601Parser::parse_fractional_part()
{
@ -576,6 +739,61 @@ bool ISO8601Parser::parse_time_zone_utc_offset()
|| parse_utc_designator();
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffsetNotAmbiguous
bool ISO8601Parser::parse_time_zone_numeric_utc_offset_not_ambiguous()
{
// TimeZoneNumericUTCOffsetNotAmbiguous :
// + TimeZoneUTCOffsetHour
// U+2212 TimeZoneUTCOffsetHour
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute : TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
StateTransaction transaction { *this };
if (m_state.lexer.consume_specific('+') || m_state.lexer.consume_specific("\xE2\x88\x92"sv)) {
if (!parse_time_zone_utc_offset_hour())
return false;
} else {
if (!parse_time_zone_utc_offset_sign())
return false;
if (!parse_time_zone_utc_offset_hour())
return false;
if (m_state.lexer.consume_specific(':')) {
if (!parse_time_zone_utc_offset_minute())
return false;
if (m_state.lexer.consume_specific(':')) {
if (!parse_time_zone_utc_offset_second())
return false;
(void)parse_time_zone_utc_offset_fraction();
}
} else {
if (!parse_time_zone_utc_offset_minute())
return false;
if (parse_time_zone_utc_offset_second())
(void)parse_time_zone_utc_offset_fraction();
}
}
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffsetNotAmbiguousAllowedNegativeHour
bool ISO8601Parser::parse_time_zone_numeric_utc_offset_not_ambiguous_allowed_negative_hour()
{
// TimeZoneNumericUTCOffsetNotAmbiguousAllowedNegativeHour :
// TimeZoneNumericUTCOffsetNotAmbiguous
// - TimeHourNotValidMonth
StateTransaction transaction { *this };
if (!parse_time_zone_numeric_utc_offset_not_ambiguous()) {
if (!m_state.lexer.consume_specific('-'))
return false;
if (!parse_time_hour_not_valid_month())
return false;
}
transaction.commit();
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetName
bool ISO8601Parser::parse_time_zone_utc_offset_name()
{
@ -786,6 +1004,120 @@ bool ISO8601Parser::parse_time_spec()
return true;
}
// https://tc39.es/proposal-temporal/#prod-TimeHourMinuteBasicFormatNotAmbiguous
bool ISO8601Parser::parse_time_hour_minute_basic_format_not_ambiguous()
{
// TimeHourMinuteBasicFormatNotAmbiguous :
// TimeHourNotValidMonth TimeMinute
// TimeHour TimeMinuteNotValidDay
// TimeHourNotThirtyOneDayMonth TimeMinuteThirtyOneOnly
// TimeHourTwoOnly TimeMinuteThirtyOnly
{
StateTransaction transaction { *this };
if (parse_time_hour_not_valid_month() && parse_time_minute()) {
transaction.commit();
return true;
}
}
{
StateTransaction transaction { *this };
if (parse_time_hour() && parse_time_minute_not_valid_day()) {
transaction.commit();
return true;
}
}
{
StateTransaction transaction { *this };
if (parse_time_hour_not_thirty_one_day_month() && parse_time_minute_thirty_one_only()) {
transaction.commit();
return true;
}
}
{
StateTransaction transaction { *this };
if (parse_time_hour_two_only() && parse_time_minute_thirty_only()) {
transaction.commit();
return true;
}
}
return false;
}
// https://tc39.es/proposal-temporal/#prod-TimeSpecWithOptionalTimeZoneNotAmbiguous
bool ISO8601Parser::parse_time_spec_with_optional_time_zone_not_ambiguous()
{
// TimeSpecWithOptionalTimeZoneNotAmbiguous :
// TimeHour TimeZoneNumericUTCOffsetNotAmbiguous[opt] TimeZoneBracketedAnnotation[opt]
// TimeHourNotValidMonth TimeZone
// TimeHour : TimeMinute TimeZone[opt]
// TimeHourMinuteBasicFormatNotAmbiguous TimeZoneBracketedAnnotation[opt]
// TimeHour TimeMinute TimeZoneNumericUTCOffsetNotAmbiguousAllowedNegativeHour TimeZoneBracketedAnnotation[opt]
// TimeHour : TimeMinute : TimeSecond TimeFraction[opt] TimeZone[opt]
// TimeHour TimeMinute TimeSecondNotValidMonth TimeZone[opt]
// TimeHour TimeMinute TimeSecond TimeFraction TimeZone[opt]
{
StateTransaction transaction { *this };
if (parse_time_hour()) {
if (m_state.lexer.consume_specific(':')) {
if (parse_time_minute()) {
if (m_state.lexer.consume_specific(':')) {
if (parse_time_second()) {
(void)parse_time_fraction();
(void)parse_time_zone();
transaction.commit();
return true;
}
} else {
(void)parse_time_zone();
transaction.commit();
return true;
}
}
} else if (parse_time_minute()) {
if (parse_time_zone_numeric_utc_offset_not_ambiguous_allowed_negative_hour()) {
(void)parse_time_zone_bracketed_annotation();
transaction.commit();
return true;
}
{
StateTransaction sub_transaction { *this };
if (parse_time_second() && parse_time_fraction()) {
(void)parse_time_zone();
transaction.commit();
return true;
}
}
if (parse_time_second_not_valid_month()) {
(void)parse_time_zone();
transaction.commit();
return true;
}
} else {
(void)parse_time_zone_numeric_utc_offset_not_ambiguous();
(void)parse_time_zone_bracketed_annotation();
transaction.commit();
return true;
}
}
}
{
StateTransaction transaction { *this };
if (parse_time_hour_not_valid_month() && parse_time_zone()) {
transaction.commit();
return true;
}
}
{
StateTransaction transaction { *this };
if (parse_time_hour_minute_basic_format_not_ambiguous()) {
(void)parse_time_zone_bracketed_annotation();
transaction.commit();
return true;
}
}
return false;
}
// https://tc39.es/proposal-temporal/#prod-TimeSpecSeparator
bool ISO8601Parser::parse_time_spec_separator()
{
@ -816,15 +1148,29 @@ bool ISO8601Parser::parse_date_time()
bool ISO8601Parser::parse_calendar_time()
{
// CalendarTime :
// TimeDesignator[opt] TimeSpec TimeZone[opt] Calendar[opt]
StateTransaction transaction { *this };
(void)parse_time_designator();
if (!parse_time_spec())
return false;
(void)parse_time_zone();
(void)parse_calendar();
transaction.commit();
return true;
// TimeDesignator TimeSpec TimeZone[opt] Calendar[opt]
// TimeSpec TimeZone[opt] Calendar
// TimeSpecWithOptionalTimeZoneNotAmbiguous
{
StateTransaction transaction { *this };
if (parse_time_designator() && parse_time_spec()) {
(void)parse_time_zone();
(void)parse_calendar();
transaction.commit();
return true;
}
}
{
StateTransaction transaction { *this };
if (parse_time_spec()) {
(void)parse_time_zone();
if (parse_calendar()) {
transaction.commit();
return true;
}
}
}
return parse_time_spec_with_optional_time_zone_not_ambiguous();
}
// https://tc39.es/proposal-temporal/#prod-CalendarDateTime
@ -1336,4 +1682,5 @@ Optional<ParseResult> parse_iso8601(Production production, StringView input)
return parser.parse_result();
}
}