|
@@ -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();
|
|
|
}
|
|
|
+
|
|
|
}
|