2021-11-19 18:04:50 +00:00
/*
2022-01-06 19:00:48 +01:00
* Copyright ( c ) 2021 - 2022 , Linus Groh < linusg @ serenityos . org >
2021-11-19 18:04:50 +00:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/CharacterTypes.h>
# include <LibJS/Runtime/Temporal/ISO8601.h>
namespace JS : : Temporal {
namespace Detail {
2021-11-27 23:38:29 +00:00
// https://tc39.es/proposal-temporal/#prod-DecimalDigits
bool ISO8601Parser : : parse_decimal_digits ( )
{
// DecimalDigits[Sep] ::
// DecimalDigit
// DecimalDigits[?Sep] DecimalDigit
// [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit
// NOTE: Temporal exclusively uses the variant without a separator ([~Sep])
if ( ! parse_decimal_digit ( ) )
return false ;
while ( parse_decimal_digit ( ) )
;
return true ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-DecimalDigit
bool ISO8601Parser : : parse_decimal_digit ( )
{
// DecimalDigit : one of
// 0 1 2 3 4 5 6 7 8 9
if ( m_state . lexer . next_is ( is_ascii_digit ) ) {
m_state . lexer . consume ( ) ;
return true ;
}
return false ;
}
// https://tc39.es/proposal-temporal/#prod-NonZeroDigit
bool ISO8601Parser : : parse_non_zero_digit ( )
{
// NonZeroDigit : one of
// 1 2 3 4 5 6 7 8 9
if ( m_state . lexer . next_is ( is_ascii_digit ) & & ! m_state . lexer . next_is ( ' 0 ' ) ) {
m_state . lexer . consume ( ) ;
return true ;
}
return false ;
}
// https://tc39.es/proposal-temporal/#prod-ASCIISign
bool ISO8601Parser : : parse_ascii_sign ( )
{
// ASCIISign : one of
// + -
return m_state . lexer . consume_specific ( ' + ' )
| | m_state . lexer . consume_specific ( ' - ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-Sign
bool ISO8601Parser : : parse_sign ( )
{
// Sign :
// ASCIISign
// U+2212
StateTransaction transaction { * this } ;
auto success = parse_ascii_sign ( )
| | m_state . lexer . consume_specific ( " \xE2 \x88 \x92 " sv ) ;
if ( ! success )
return false ;
m_state . parse_result . sign = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
2022-03-30 18:36:16 +01:00
// https://tc39.es/proposal-temporal/#prod-UnpaddedHour
bool ISO8601Parser : : parse_unpadded_hour ( )
{
// UnpaddedHour :
// DecimalDigit
// 1 DecimalDigit
// 20
// 21
// 22
// 23
StateTransaction transaction { * this } ;
auto success = 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 ) {
// This could be either of the first two productions.
if ( m_state . lexer . consume_specific ( ' 1 ' ) )
( void ) parse_decimal_digit ( ) ;
else if ( ! parse_decimal_digit ( ) )
return false ;
}
transaction . commit ( ) ;
return true ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-Hour
bool ISO8601Parser : : parse_hour ( )
{
// Hour :
// 0 DecimalDigit
// 1 DecimalDigit
// 20
// 21
// 22
// 23
StateTransaction transaction { * this } ;
if ( m_state . lexer . consume_specific ( ' 0 ' ) | | m_state . lexer . consume_specific ( ' 1 ' ) ) {
if ( ! parse_decimal_digit ( ) )
return false ;
} else {
auto success = 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 ;
}
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-MinuteSecond
bool ISO8601Parser : : parse_minute_second ( )
{
// MinuteSecond :
// 0 DecimalDigit
// 1 DecimalDigit
// 2 DecimalDigit
// 3 DecimalDigit
// 4 DecimalDigit
// 5 DecimalDigit
StateTransaction transaction { * this } ;
auto success = m_state . lexer . consume_specific ( ' 0 ' )
| | m_state . lexer . consume_specific ( ' 1 ' )
| | 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 ( ! success )
return false ;
if ( ! parse_decimal_digit ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DecimalSeparator
bool ISO8601Parser : : parse_decimal_separator ( )
{
// DecimalSeparator : one of
// . ,
return m_state . lexer . consume_specific ( ' . ' )
| | m_state . lexer . consume_specific ( ' , ' ) ;
}
2021-11-27 23:38:29 +00:00
// https://tc39.es/proposal-temporal/#prod-DaysDesignator
bool ISO8601Parser : : parse_days_designator ( )
{
// DaysDesignator : one of
// D d
return m_state . lexer . consume_specific ( ' D ' )
| | m_state . lexer . consume_specific ( ' d ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-HoursDesignator
bool ISO8601Parser : : parse_hours_designator ( )
{
// HoursDesignator : one of
// H h
return m_state . lexer . consume_specific ( ' H ' )
| | m_state . lexer . consume_specific ( ' h ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-MinutesDesignator
bool ISO8601Parser : : parse_minutes_designator ( )
{
// MinutesDesignator : one of
// M m
return m_state . lexer . consume_specific ( ' M ' )
| | m_state . lexer . consume_specific ( ' m ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-MonthsDesignator
bool ISO8601Parser : : parse_months_designator ( )
{
// MonthsDesignator : one of
// M m
return m_state . lexer . consume_specific ( ' M ' )
| | m_state . lexer . consume_specific ( ' m ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-DurationDesignator
bool ISO8601Parser : : parse_duration_designator ( )
{
// DurationDesignator : one of
// P p
return m_state . lexer . consume_specific ( ' P ' )
| | m_state . lexer . consume_specific ( ' p ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-SecondsDesignator
bool ISO8601Parser : : parse_seconds_designator ( )
{
// SecondsDesignator : one of
// S s
return m_state . lexer . consume_specific ( ' S ' )
| | m_state . lexer . consume_specific ( ' s ' ) ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-DateTimeSeparator
bool ISO8601Parser : : parse_date_time_separator ( )
{
// DateTimeSeparator :
// <SP>
// T
// t
return m_state . lexer . consume_specific ( ' ' )
| | m_state . lexer . consume_specific ( ' T ' )
| | m_state . lexer . consume_specific ( ' t ' ) ;
}
2021-12-18 20:58:36 +00:00
// https://tc39.es/proposal-temporal/#prod-TimeDesignator
bool ISO8601Parser : : parse_time_designator ( )
2021-11-27 23:38:29 +00:00
{
2021-12-18 20:58:36 +00:00
// TimeDesignator : one of
2021-11-27 23:38:29 +00:00
// T t
return m_state . lexer . consume_specific ( ' T ' )
| | m_state . lexer . consume_specific ( ' t ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-WeeksDesignator
bool ISO8601Parser : : parse_weeks_designator ( )
{
// WeeksDesignator : one of
// W w
return m_state . lexer . consume_specific ( ' W ' )
| | m_state . lexer . consume_specific ( ' w ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-YearsDesignator
bool ISO8601Parser : : parse_years_designator ( )
{
// YearsDesignator : one of
// Y y
return m_state . lexer . consume_specific ( ' Y ' )
| | m_state . lexer . consume_specific ( ' y ' ) ;
}
2021-11-19 20:53:07 +00:00
// https://tc39.es/proposal-temporal/#prod-UTCDesignator
bool ISO8601Parser : : parse_utc_designator ( )
{
// UTCDesignator : one of
// Z z
StateTransaction transaction { * this } ;
auto success = m_state . lexer . consume_specific ( ' Z ' )
| | m_state . lexer . consume_specific ( ' z ' ) ;
if ( ! success )
return false ;
m_state . parse_result . utc_designator = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-AnnotationCriticalFlag
bool ISO8601Parser : : parse_annotation_critical_flag ( )
{
// AnnotationCriticalFlag :
// !
return m_state . lexer . consume_specific ( ' ! ' ) ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-DateYear
bool ISO8601Parser : : parse_date_year ( )
{
// DateFourDigitYear :
// DecimalDigit DecimalDigit DecimalDigit DecimalDigit
// DateExtendedYear :
// Sign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit
// DateYear :
// DateFourDigitYear
// DateExtendedYear
StateTransaction transaction { * this } ;
if ( parse_sign ( ) ) {
for ( size_t i = 0 ; i < 6 ; + + i ) {
if ( ! parse_decimal_digit ( ) )
return false ;
}
} else {
for ( size_t i = 0 ; i < 4 ; + + i ) {
if ( ! parse_decimal_digit ( ) )
return false ;
}
}
2022-03-10 18:10:11 +01:00
// It is a Syntax Error if DateExtendedYear is "-000000" or "− 000000" (U+2212 MINUS SIGN followed by 000000).
if ( transaction . parsed_string_view ( ) . is_one_of ( " -000000 " sv , " − 000000" sv ) )
return false ;
2021-11-19 18:04:50 +00:00
m_state . parse_result . date_year = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DateMonth
bool ISO8601Parser : : parse_date_month ( )
{
// DateMonth :
// 0 NonZeroDigit
// 10
// 11
// 12
StateTransaction transaction { * this } ;
if ( m_state . lexer . consume_specific ( ' 0 ' ) ) {
if ( ! parse_non_zero_digit ( ) )
return false ;
} else {
auto success = m_state . lexer . consume_specific ( " 10 " sv )
| | m_state . lexer . consume_specific ( " 11 " sv )
| | m_state . lexer . consume_specific ( " 12 " sv ) ;
if ( ! success )
return false ;
}
m_state . parse_result . date_month = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
2022-08-25 21:38:29 +01:00
// https://tc39.es/proposal-temporal/#prod-DateMonthWithThirtyOneDays
bool ISO8601Parser : : parse_date_month_with_thirty_days ( )
{
// DateMonthWithThirtyOneDays : one of
// 01 03 05 07 08 10 12
StateTransaction transaction { * this } ;
auto success = m_state . lexer . consume_specific ( " 01 " sv )
| | m_state . lexer . consume_specific ( " 03 " sv )
| | m_state . lexer . consume_specific ( " 05 " sv )
| | m_state . lexer . consume_specific ( " 07 " sv )
| | m_state . lexer . consume_specific ( " 08 " sv )
| | m_state . lexer . consume_specific ( " 10 " sv )
| | m_state . lexer . consume_specific ( " 12 " sv ) ;
if ( ! success )
return false ;
transaction . commit ( ) ;
return true ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-DateDay
bool ISO8601Parser : : parse_date_day ( )
{
// DateDay :
// 0 NonZeroDigit
// 1 DecimalDigit
// 2 DecimalDigit
// 30
// 31
StateTransaction transaction { * this } ;
if ( m_state . lexer . consume_specific ( ' 0 ' ) ) {
if ( ! parse_non_zero_digit ( ) )
return false ;
} else if ( m_state . lexer . consume_specific ( ' 1 ' ) | | m_state . lexer . consume_specific ( ' 2 ' ) ) {
if ( ! parse_decimal_digit ( ) )
return false ;
} else {
auto success = m_state . lexer . consume_specific ( " 30 " sv )
| | m_state . lexer . consume_specific ( " 31 " sv ) ;
if ( ! success )
return false ;
}
m_state . parse_result . date_day = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
2021-11-19 19:19:29 +00:00
// https://tc39.es/proposal-temporal/#prod-DateSpecYearMonth
bool ISO8601Parser : : parse_date_spec_year_month ( )
{
// DateSpecYearMonth :
// DateYear -[opt] DateMonth
StateTransaction transaction { * this } ;
if ( ! parse_date_year ( ) )
return false ;
m_state . lexer . consume_specific ( ' - ' ) ;
if ( ! parse_date_month ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
2021-11-19 19:05:17 +00:00
// https://tc39.es/proposal-temporal/#prod-DateSpecMonthDay
bool ISO8601Parser : : parse_date_spec_month_day ( )
{
// TwoDashes :
// --
// DateSpecMonthDay :
// TwoDashes[opt] DateMonth -[opt] DateDay
StateTransaction transaction { * this } ;
m_state . lexer . consume_specific ( " -- " sv ) ;
if ( ! parse_date_month ( ) )
return false ;
m_state . lexer . consume_specific ( ' - ' ) ;
if ( ! parse_date_day ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
2022-08-25 21:38:29 +01:00
// https://tc39.es/proposal-temporal/#prod-ValidMonthDay
bool ISO8601Parser : : parse_valid_month_day ( )
{
// ValidMonthDay :
// DateMonth -[opt] 0 NonZeroDigit
// DateMonth -[opt] 1 DecimalDigit
// DateMonth -[opt] 2 DecimalDigit
// DateMonth -[opt] 30 but not one of 0230 or 02-30
// DateMonthWithThirtyOneDays -[opt] 31
StateTransaction transaction { * this } ;
if ( parse_date_month ( ) ) {
m_state . lexer . consume_specific ( ' - ' ) ;
if ( m_state . lexer . consume_specific ( ' 0 ' ) ) {
if ( ! parse_non_zero_digit ( ) )
return false ;
} else if ( m_state . lexer . consume_specific ( ' 1 ' ) | | m_state . lexer . consume_specific ( ' 2 ' ) ) {
if ( ! parse_decimal_digit ( ) )
return false ;
} else if ( m_state . lexer . consume_specific ( " 30 " sv ) ) {
if ( transaction . parsed_string_view ( ) . is_one_of ( " 0230 " sv , " 02-30 " sv ) )
return false ;
} else {
return false ;
}
} else if ( parse_date_month_with_thirty_days ( ) ) {
m_state . lexer . consume_specific ( ' - ' ) ;
if ( ! m_state . lexer . consume_specific ( " 31 " sv ) )
return false ;
} else {
return false ;
}
transaction . commit ( ) ;
return true ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-Date
bool ISO8601Parser : : parse_date ( )
{
// Date :
// DateYear - DateMonth - DateDay
// DateYear DateMonth DateDay
StateTransaction transaction { * this } ;
if ( ! parse_date_year ( ) )
return false ;
auto with_dashes = m_state . lexer . consume_specific ( ' - ' ) ;
if ( ! parse_date_month ( ) )
return false ;
if ( with_dashes & & ! m_state . lexer . consume_specific ( ' - ' ) )
return false ;
if ( ! parse_date_day ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeHour
bool ISO8601Parser : : parse_time_hour ( )
{
// TimeHour :
// Hour
StateTransaction transaction { * this } ;
if ( ! parse_hour ( ) )
return false ;
m_state . parse_result . time_hour = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeMinute
bool ISO8601Parser : : parse_time_minute ( )
{
// TimeMinute :
// MinuteSecond
StateTransaction transaction { * this } ;
if ( ! parse_minute_second ( ) )
return false ;
m_state . parse_result . time_minute = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeSecond
bool ISO8601Parser : : parse_time_second ( )
{
// TimeSecond :
// MinuteSecond
// 60
StateTransaction transaction { * this } ;
auto success = parse_minute_second ( )
| | m_state . lexer . consume_specific ( " 60 " sv ) ;
if ( ! success )
return false ;
m_state . parse_result . time_second = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-FractionalPart
bool ISO8601Parser : : parse_fractional_part ( )
{
// FractionalPart :
// DecimalDigit DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt]
if ( ! parse_decimal_digit ( ) )
return false ;
for ( size_t i = 0 ; i < 8 ; + + i ) {
if ( ! parse_decimal_digit ( ) )
break ;
}
return true ;
}
// https://tc39.es/proposal-temporal/#prod-Fraction
bool ISO8601Parser : : parse_fraction ( )
{
// Fraction :
2021-12-18 17:28:04 +00:00
// DecimalSeparator FractionalPart
2021-11-19 18:04:50 +00:00
StateTransaction transaction { * this } ;
if ( ! parse_decimal_separator ( ) )
return false ;
2021-12-18 17:28:04 +00:00
if ( ! parse_fractional_part ( ) )
2021-11-19 18:04:50 +00:00
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeFraction
bool ISO8601Parser : : parse_time_fraction ( )
{
// TimeFraction :
// Fraction
2021-12-19 09:29:46 +00:00
StateTransaction transaction { * this } ;
if ( ! parse_fraction ( ) )
return false ;
m_state . parse_result . time_fraction = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
2021-11-19 18:04:50 +00:00
}
2021-11-19 20:53:07 +00:00
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSign
bool ISO8601Parser : : parse_time_zone_utc_offset_sign ( )
{
// TimeZoneUTCOffsetSign :
// Sign
StateTransaction transaction { * this } ;
if ( ! parse_sign ( ) )
return false ;
m_state . parse_result . time_zone_utc_offset_sign = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetHour
bool ISO8601Parser : : parse_time_zone_utc_offset_hour ( )
{
// TimeZoneUTCOffsetHour :
// Hour
StateTransaction transaction { * this } ;
if ( ! parse_hour ( ) )
return false ;
m_state . parse_result . time_zone_utc_offset_hour = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetMinute
bool ISO8601Parser : : parse_time_zone_utc_offset_minute ( )
{
// TimeZoneUTCOffsetMinute :
// MinuteSecond
StateTransaction transaction { * this } ;
if ( ! parse_minute_second ( ) )
return false ;
m_state . parse_result . time_zone_utc_offset_minute = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSecond
bool ISO8601Parser : : parse_time_zone_utc_offset_second ( )
{
// TimeZoneUTCOffsetSecond :
// MinuteSecond
StateTransaction transaction { * this } ;
if ( ! parse_minute_second ( ) )
return false ;
m_state . parse_result . time_zone_utc_offset_second = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFractionalPart
bool ISO8601Parser : : parse_time_zone_utc_offset_fractional_part ( )
{
// TimeZoneUTCOffsetFractionalPart :
// FractionalPart
2022-06-09 20:45:10 +01:00
return parse_fractional_part ( ) ;
2021-11-19 20:53:07 +00:00
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFraction
bool ISO8601Parser : : parse_time_zone_utc_offset_fraction ( )
{
// TimeZoneUTCOffsetFraction :
// DecimalSeparator TimeZoneUTCOffsetFractionalPart
StateTransaction transaction { * this } ;
if ( ! parse_decimal_separator ( ) )
return false ;
if ( ! parse_time_zone_utc_offset_fractional_part ( ) )
return false ;
2022-06-09 20:45:10 +01:00
m_state . parse_result . time_zone_utc_offset_fraction = transaction . parsed_string_view ( ) ;
2021-11-19 20:53:07 +00:00
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffset
bool ISO8601Parser : : parse_time_zone_numeric_utc_offset ( )
{
// TimeZoneNumericUTCOffset :
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute : TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
// TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
StateTransaction transaction { * this } ;
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 ( ) ) {
if ( parse_time_zone_utc_offset_second ( ) )
( void ) parse_time_zone_utc_offset_fraction ( ) ;
}
2022-01-22 21:52:55 +00:00
m_state . parse_result . time_zone_numeric_utc_offset = transaction . parsed_string_view ( ) ;
2021-11-19 20:53:07 +00:00
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffset
bool ISO8601Parser : : parse_time_zone_utc_offset ( )
{
// TimeZoneUTCOffset :
// TimeZoneNumericUTCOffset
// UTCDesignator
return parse_time_zone_numeric_utc_offset ( )
| | parse_utc_designator ( ) ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetName
bool ISO8601Parser : : parse_time_zone_utc_offset_name ( )
{
// TimeZoneUTCOffsetName :
// Sign Hour
// Sign Hour : MinuteSecond
// Sign Hour MinuteSecond
// Sign Hour : MinuteSecond : MinuteSecond Fraction[opt]
// Sign Hour MinuteSecond MinuteSecond Fraction[opt]
StateTransaction transaction { * this } ;
if ( ! parse_sign ( ) )
return false ;
if ( ! parse_hour ( ) )
return false ;
if ( m_state . lexer . consume_specific ( ' : ' ) ) {
if ( ! parse_minute_second ( ) )
return false ;
if ( m_state . lexer . consume_specific ( ' : ' ) ) {
if ( ! parse_minute_second ( ) )
return false ;
( void ) parse_fraction ( ) ;
}
} else if ( parse_minute_second ( ) ) {
if ( parse_minute_second ( ) )
( void ) parse_fraction ( ) ;
}
transaction . commit ( ) ;
return true ;
}
2022-01-06 19:00:48 +01:00
// https://tc39.es/proposal-temporal/#prod-TZLeadingChar
bool ISO8601Parser : : parse_tz_leading_char ( )
2021-11-19 20:53:07 +00:00
{
// TZLeadingChar :
// Alpha
// .
// _
2022-01-06 19:00:48 +01:00
if ( m_state . lexer . next_is ( is_ascii_alpha ) ) {
m_state . lexer . consume ( ) ;
return true ;
}
return m_state . lexer . consume_specific ( ' . ' )
| | m_state . lexer . consume_specific ( ' _ ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-TZChar
bool ISO8601Parser : : parse_tz_char ( )
{
2021-11-19 20:53:07 +00:00
// TZChar :
// Alpha
// .
// -
// _
2022-01-06 19:00:48 +01:00
if ( m_state . lexer . next_is ( is_ascii_alpha ) ) {
m_state . lexer . consume ( ) ;
return true ;
}
return m_state . lexer . consume_specific ( ' . ' )
| | m_state . lexer . consume_specific ( ' - ' )
| | m_state . lexer . consume_specific ( ' _ ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneIANANameComponent
bool ISO8601Parser : : parse_time_zone_iana_component ( )
{
2021-11-19 20:53:07 +00:00
// TimeZoneIANANameComponent :
// TZLeadingChar TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] but not one of . or ..
2022-01-06 19:00:48 +01:00
StateTransaction transaction { * this } ;
if ( ! parse_tz_leading_char ( ) )
return false ;
for ( size_t i = 0 ; i < 13 ; + + i ) {
if ( ! parse_tz_char ( ) )
break ;
}
if ( transaction . parsed_string_view ( ) . is_one_of ( " . " sv , " .. " sv ) )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-TimeZoneIANANameTail
bool ISO8601Parser : : parse_time_zone_iana_name_tail ( )
{
2021-11-19 20:53:07 +00:00
// TimeZoneIANANameTail :
// TimeZoneIANANameComponent
// TimeZoneIANANameComponent / TimeZoneIANANameTail
2022-01-06 19:00:48 +01:00
StateTransaction transaction { * this } ;
if ( ! parse_time_zone_iana_component ( ) )
return false ;
while ( m_state . lexer . next_is ( ' / ' ) ) {
m_state . lexer . consume ( ) ;
if ( ! parse_time_zone_iana_component ( ) )
return false ;
}
transaction . commit ( ) ;
return true ;
}
2022-07-30 11:00:08 +02:00
// https://tc39.es/proposal-temporal/#prod-TimeZoneIANALegacyName
bool ISO8601Parser : : parse_time_zone_iana_legacy_name ( )
{
// TimeZoneIANALegacyName :
// Etc/GMT0
// GMT0
// GMT-0
// GMT+0
// EST5EDT
// CST6CDT
// MST7MDT
// PST8PDT
return m_state . lexer . consume_specific ( " Etc/GMT0 " sv )
| | m_state . lexer . consume_specific ( " GMT0 " sv )
| | m_state . lexer . consume_specific ( " GMT-0 " sv )
| | m_state . lexer . consume_specific ( " GMT+0 " sv )
| | m_state . lexer . consume_specific ( " EST5EDT " sv )
| | m_state . lexer . consume_specific ( " CST6CDT " sv )
| | m_state . lexer . consume_specific ( " MST7MDT " sv )
| | m_state . lexer . consume_specific ( " PST8PDT " sv ) ;
}
2022-01-06 19:00:48 +01:00
// https://tc39.es/proposal-temporal/#prod-TimeZoneIANAName
bool ISO8601Parser : : parse_time_zone_iana_name ( )
{
2021-11-19 20:53:07 +00:00
// TimeZoneIANAName :
2022-03-30 18:36:16 +01:00
// Etc/GMT ASCIISign UnpaddedHour
2022-08-25 20:48:46 +01:00
// TimeZoneIANANameTail
2022-07-30 11:00:08 +02:00
// TimeZoneIANALegacyName
// NOTE: Reverse order here because `TimeZoneIANANameTail` can be a subset of `TimeZoneIANALegacyName`,
// so we'd not attempt to parse that but may not exhaust the input string.
2022-03-30 18:36:16 +01:00
auto parse_etc_gmt_with_offset = [ this ] {
StateTransaction transaction { * this } ;
if ( ! m_state . lexer . consume_specific ( " Etc/GMT " sv ) )
return false ;
if ( ! parse_ascii_sign ( ) )
return false ;
if ( ! parse_unpadded_hour ( ) )
return false ;
transaction . commit ( ) ;
return true ;
} ;
2022-06-27 23:18:10 +01:00
return parse_etc_gmt_with_offset ( )
2022-07-30 11:00:08 +02:00
| | parse_time_zone_iana_legacy_name ( )
2022-06-27 23:18:10 +01:00
| | parse_time_zone_iana_name_tail ( ) ;
2021-11-19 20:53:07 +00:00
}
2022-05-17 21:14:01 +01:00
// https://tc39.es/proposal-temporal/#prod-TimeZoneIdentifier
bool ISO8601Parser : : parse_time_zone_identifier ( )
2021-11-19 20:53:07 +00:00
{
2022-05-17 21:14:01 +01:00
// TimeZoneIdentifier :
2021-11-19 20:53:07 +00:00
// TimeZoneIANAName
// TimeZoneUTCOffsetName
StateTransaction transaction { * this } ;
if ( parse_time_zone_iana_name ( ) ) {
// no-op.
} else if ( ! parse_time_zone_utc_offset_name ( ) ) {
return false ;
}
2022-06-27 23:18:10 +01:00
m_state . parse_result . time_zone_identifier = transaction . parsed_string_view ( ) ;
2021-11-19 20:53:07 +00:00
transaction . commit ( ) ;
return true ;
}
2023-02-11 01:05:28 +00:00
// https://tc39.es/proposal-temporal/#prod-TimeZoneAnnotation
bool ISO8601Parser : : parse_time_zone_annotation ( )
2021-11-19 20:53:07 +00:00
{
2023-02-11 01:05:28 +00:00
// TimeZoneAnnotation :
2022-11-02 18:26:46 +00:00
// [ AnnotationCriticalFlag[opt] TimeZoneIdentifier ]
2021-11-19 20:53:07 +00:00
StateTransaction transaction { * this } ;
if ( ! m_state . lexer . consume_specific ( ' [ ' ) )
return false ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotation_critical_flag ( ) ;
2022-05-17 21:14:01 +01:00
if ( ! parse_time_zone_identifier ( ) )
2021-11-19 20:53:07 +00:00
return false ;
if ( ! m_state . lexer . consume_specific ( ' ] ' ) )
return false ;
2023-02-11 01:05:28 +00:00
m_state . parse_result . time_zone_annotation = transaction . parsed_string_view ( ) ;
2022-01-22 21:56:06 +00:00
transaction . commit ( ) ;
return true ;
2021-11-19 18:04:50 +00:00
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-AKeyLeadingChar
bool ISO8601Parser : : parse_a_key_leading_char ( )
{
// AKeyLeadingChar :
// LowercaseAlpha
// _
if ( m_state . lexer . next_is ( is_ascii_lower_alpha ) ) {
m_state . lexer . consume ( ) ;
return true ;
}
return m_state . lexer . consume_specific ( ' _ ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-AKeyChar
bool ISO8601Parser : : parse_a_key_char ( )
2021-11-19 18:04:50 +00:00
{
2022-11-02 18:26:46 +00:00
// AKeyChar :
// AKeyLeadingChar
// DecimalDigit
// -
if ( parse_a_key_leading_char ( ) )
return true ;
if ( parse_decimal_digit ( ) )
return true ;
return m_state . lexer . consume_specific ( ' - ' ) ;
}
// https://tc39.es/proposal-temporal/#prod-AValChar
bool ISO8601Parser : : parse_a_val_char ( )
{
// AValChar :
2021-11-19 18:04:50 +00:00
// Alpha
// DecimalDigit
2022-11-02 18:26:46 +00:00
if ( m_state . lexer . next_is ( is_ascii_alpha ) ) {
m_state . lexer . consume ( ) ;
2021-11-19 18:04:50 +00:00
return true ;
2022-11-02 18:26:46 +00:00
}
return parse_decimal_digit ( ) ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotationKeyTail
bool ISO8601Parser : : parse_annotation_key_tail ( )
{
// AnnotationKeyTail :
// AKeyChar AnnotationKeyTail[opt]
if ( ! parse_a_key_char ( ) )
return false ;
// This is implemented without recursion to prevent stack overflow with annotation key tails that have many characters.
while ( parse_a_key_char ( ) )
;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotationKey
bool ISO8601Parser : : parse_annotation_key ( )
{
// AnnotationKey :
// AKeyLeadingChar AnnotationKeyTail[opt]
2021-11-19 18:04:50 +00:00
StateTransaction transaction { * this } ;
2022-11-02 18:26:46 +00:00
if ( ! parse_a_key_leading_char ( ) ) {
m_state . parse_result . annotation_key = Optional < StringView > { } ;
return false ;
}
( void ) parse_annotation_key_tail ( ) ;
m_state . parse_result . annotation_key = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotationValueComponent
bool ISO8601Parser : : parse_annotation_value_component ( )
{
// AnnotationValueComponent :
// AValChar AnnotationValueComponent[opt]
if ( ! parse_a_val_char ( ) )
return false ;
// This is implemented without recursion to prevent stack overflow with annotation value components that have many characters.
while ( parse_a_val_char ( ) )
;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotationValueTail
bool ISO8601Parser : : parse_annotation_value_tail ( )
{
// AnnotationValueTail :
// AnnotationValueComponent
// AnnotationValueComponent - AnnotationValueTail
// This is implemented without recursion to prevent stack overflow with annotation values that have many dashes.
for ( ; ; ) {
if ( ! parse_annotation_value_component ( ) )
2021-11-19 18:04:50 +00:00
return false ;
2022-11-02 18:26:46 +00:00
if ( ! m_state . lexer . consume_specific ( ' - ' ) )
break ;
}
return true ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotationValue
bool ISO8601Parser : : parse_annotation_value ( )
{
// AnnotationValue :
// AnnotationValueTail
StateTransaction transaction { * this } ;
if ( ! parse_annotation_value_tail ( ) ) {
m_state . parse_result . annotation_value = Optional < StringView > { } ;
return false ;
}
m_state . parse_result . annotation_value = transaction . parsed_string_view ( ) ;
2021-11-19 18:04:50 +00:00
transaction . commit ( ) ;
return true ;
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-Annotation
bool ISO8601Parser : : parse_annotation ( )
2021-11-19 18:04:50 +00:00
{
2022-11-02 18:26:46 +00:00
// Annotation :
// [ AnnotationCriticalFlag[opt] AnnotationKey = AnnotationValue ]
2021-11-19 18:04:50 +00:00
StateTransaction transaction { * this } ;
2022-11-02 18:26:46 +00:00
if ( ! m_state . lexer . consume_specific ( ' [ ' ) )
2021-11-19 18:04:50 +00:00
return false ;
2022-11-02 18:26:46 +00:00
Annotation annotation ;
annotation . critical = parse_annotation_critical_flag ( ) ;
if ( ! parse_annotation_key ( ) )
return false ;
annotation . key = m_state . parse_result . annotation_key . value ( ) ;
if ( ! m_state . lexer . consume_specific ( ' = ' ) )
return false ;
if ( ! parse_annotation_value ( ) )
2021-11-19 18:04:50 +00:00
return false ;
2022-11-02 18:26:46 +00:00
annotation . value = m_state . parse_result . annotation_value . value ( ) ;
2021-11-19 18:04:50 +00:00
if ( ! m_state . lexer . consume_specific ( ' ] ' ) )
return false ;
2022-11-02 18:26:46 +00:00
m_state . parse_result . annotations . append ( annotation ) ;
2021-11-19 18:04:50 +00:00
transaction . commit ( ) ;
return true ;
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-Annotations
bool ISO8601Parser : : parse_annotations ( )
{
// Annotations :
// Annotation Annotations[opt]
if ( ! parse_annotation ( ) )
return false ;
// This is implemented without recursion to prevent stack overflow with ISO strings that have many annotations.
while ( parse_annotation ( ) )
;
return true ;
}
2021-11-19 18:04:50 +00:00
// https://tc39.es/proposal-temporal/#prod-TimeSpec
bool ISO8601Parser : : parse_time_spec ( )
{
// TimeSpec :
// TimeHour
// TimeHour : TimeMinute
// TimeHour TimeMinute
// TimeHour : TimeMinute : TimeSecond TimeFraction[opt]
// TimeHour TimeMinute TimeSecond TimeFraction[opt]
StateTransaction transaction { * this } ;
if ( ! parse_time_hour ( ) )
return false ;
if ( m_state . lexer . consume_specific ( ' : ' ) ) {
if ( ! parse_time_minute ( ) )
return false ;
if ( m_state . lexer . consume_specific ( ' : ' ) ) {
if ( ! parse_time_second ( ) )
return false ;
( void ) parse_time_fraction ( ) ;
}
} else if ( parse_time_minute ( ) ) {
if ( parse_time_second ( ) )
( void ) parse_time_fraction ( ) ;
}
transaction . commit ( ) ;
return true ;
}
2023-02-11 01:05:28 +00:00
// https://tc39.es/proposal-temporal/#prod-TimeSpecWithOptionalOffsetNotAmbiguous
bool ISO8601Parser : : parse_time_spec_with_optional_offset_not_ambiguous ( )
2021-12-22 22:44:46 +01:00
{
2023-02-11 01:05:28 +00:00
// TimeSpecWithOptionalOffsetNotAmbiguous :
// TimeSpec TimeZoneUTCOffset[opt] but not one of ValidMonthDay or DateSpecYearMonth
2021-12-22 22:44:46 +01:00
{
StateTransaction transaction { * this } ;
2022-08-25 21:38:29 +01:00
if ( parse_valid_month_day ( ) | | parse_date_spec_year_month ( ) )
return false ;
2021-12-22 22:44:46 +01:00
}
2022-08-25 21:38:29 +01:00
StateTransaction transaction { * this } ;
if ( ! parse_time_spec ( ) )
return false ;
2023-02-11 01:05:28 +00:00
( void ) parse_time_zone_utc_offset ( ) ;
2021-11-19 18:04:50 +00:00
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DateTime
bool ISO8601Parser : : parse_date_time ( )
{
// DateTime :
2023-02-11 01:05:28 +00:00
// Date
// Date DateTimeSeparator TimeSpec TimeZoneUTCOffset[opt]
StateTransaction transaction { * this } ;
2021-11-19 18:04:50 +00:00
if ( ! parse_date ( ) )
return false ;
2023-02-11 01:05:28 +00:00
if ( parse_date_time_separator ( ) ) {
if ( ! parse_time_spec ( ) )
return false ;
( void ) parse_time_zone_utc_offset ( ) ;
}
transaction . commit ( ) ;
2021-11-19 18:04:50 +00:00
return true ;
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-AnnotatedTime
bool ISO8601Parser : : parse_annotated_time ( )
2021-12-18 17:35:06 +00:00
{
2022-11-02 18:26:46 +00:00
// AnnotatedTime :
2023-02-11 01:05:28 +00:00
// TimeDesignator TimeSpec TimeZoneUTCOffset[opt] TimeZoneAnnotation[opt] Annotations[opt]
// TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotation[opt] Annotations[opt]
2021-12-22 22:44:46 +01:00
{
StateTransaction transaction { * this } ;
if ( parse_time_designator ( ) & & parse_time_spec ( ) ) {
2023-02-11 01:05:28 +00:00
( void ) parse_time_zone_utc_offset ( ) ;
( void ) parse_time_zone_annotation ( ) ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2021-12-22 22:44:46 +01:00
transaction . commit ( ) ;
return true ;
}
}
2022-08-25 21:49:28 +01:00
StateTransaction transaction { * this } ;
2023-02-11 01:05:28 +00:00
if ( ! parse_time_spec_with_optional_offset_not_ambiguous ( ) )
2022-08-25 21:49:28 +01:00
return false ;
2023-02-11 01:05:28 +00:00
( void ) parse_time_zone_annotation ( ) ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2022-08-25 21:49:28 +01:00
transaction . commit ( ) ;
return true ;
2021-12-18 17:35:06 +00:00
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-AnnotatedDateTime
bool ISO8601Parser : : parse_annotated_date_time ( )
2021-11-19 18:04:50 +00:00
{
2022-11-02 18:26:46 +00:00
// AnnotatedDateTime :
2023-02-11 01:05:28 +00:00
// DateTime TimeZoneAnnotation[opt] Annotations[opt]
2021-11-19 18:04:50 +00:00
if ( ! parse_date_time ( ) )
return false ;
2023-02-11 01:05:28 +00:00
( void ) parse_time_zone_annotation ( ) ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2021-11-19 18:04:50 +00:00
return true ;
}
2022-11-02 18:26:46 +00:00
// https://tc39.es/proposal-temporal/#prod-AnnotatedDateTimeTimeRequired
bool ISO8601Parser : : parse_annotated_date_time_time_required ( )
2021-12-18 17:50:44 +00:00
{
2022-11-02 18:26:46 +00:00
// AnnotatedDateTimeTimeRequired :
2023-02-11 01:05:28 +00:00
// Date DateTimeSeparator TimeSpec TimeZoneUTCOffset[opt] TimeZoneAnnotation[opt] Annotations[opt]
2021-12-18 17:50:44 +00:00
StateTransaction transaction { * this } ;
if ( ! parse_date ( ) )
return false ;
2023-02-11 01:05:28 +00:00
if ( ! parse_date_time_separator ( ) )
2021-12-18 17:50:44 +00:00
return false ;
2023-02-11 01:05:28 +00:00
if ( ! parse_time_spec ( ) )
return false ;
( void ) parse_time_zone_utc_offset ( ) ;
( void ) parse_time_zone_annotation ( ) ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2021-12-18 17:50:44 +00:00
transaction . commit ( ) ;
return true ;
}
2023-02-11 01:05:28 +00:00
// https://tc39.es/proposal-temporal/#prod-AnnotatedYearMonth
bool ISO8601Parser : : parse_annotated_year_month ( )
{
// AnnotatedYearMonth :
// DateSpecYearMonth TimeZoneAnnotation[opt] Annotations[opt]
if ( ! parse_date_spec_year_month ( ) )
return false ;
( void ) parse_time_zone_annotation ( ) ;
( void ) parse_annotations ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-AnnotatedMonthDay
bool ISO8601Parser : : parse_annotated_month_day ( )
{
// AnnotatedMonthDay :
// DateSpecMonthDay TimeZoneAnnotation[opt] Annotations[opt]
if ( ! parse_date_spec_month_day ( ) )
return false ;
( void ) parse_time_zone_annotation ( ) ;
( void ) parse_annotations ( ) ;
return true ;
}
2021-11-27 23:38:29 +00:00
// https://tc39.es/proposal-temporal/#prod-DurationWholeSeconds
bool ISO8601Parser : : parse_duration_whole_seconds ( )
{
// DurationWholeSeconds :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_whole_seconds = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationSecondsFraction
bool ISO8601Parser : : parse_duration_seconds_fraction ( )
{
// DurationSecondsFraction :
// TimeFraction
StateTransaction transaction { * this } ;
if ( ! parse_time_fraction ( ) )
return false ;
m_state . parse_result . duration_seconds_fraction = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationSecondsPart
bool ISO8601Parser : : parse_duration_seconds_part ( )
{
// DurationSecondsPart :
// DurationWholeSeconds DurationSecondsFraction[opt] SecondsDesignator
StateTransaction transaction { * this } ;
if ( ! parse_duration_whole_seconds ( ) )
return false ;
( void ) parse_duration_seconds_fraction ( ) ;
if ( ! parse_seconds_designator ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationWholeMinutes
bool ISO8601Parser : : parse_duration_whole_minutes ( )
{
// DurationWholeMinutes :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_whole_minutes = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationMinutesFraction
bool ISO8601Parser : : parse_duration_minutes_fraction ( )
{
// DurationMinutesFraction :
// TimeFraction
StateTransaction transaction { * this } ;
if ( ! parse_time_fraction ( ) )
return false ;
m_state . parse_result . duration_minutes_fraction = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationMinutesPart
bool ISO8601Parser : : parse_duration_minutes_part ( )
{
// DurationMinutesPart :
// DurationWholeMinutes DurationMinutesFraction[opt] MinutesDesignator DurationSecondsPart[opt]
StateTransaction transaction { * this } ;
if ( ! parse_duration_whole_minutes ( ) )
return false ;
( void ) parse_duration_minutes_fraction ( ) ;
if ( ! parse_minutes_designator ( ) )
return false ;
( void ) parse_duration_seconds_part ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationWholeHours
bool ISO8601Parser : : parse_duration_whole_hours ( )
{
// DurationWholeHours :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_whole_hours = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationHoursFraction
bool ISO8601Parser : : parse_duration_hours_fraction ( )
{
// DurationHoursFraction :
// TimeFraction
StateTransaction transaction { * this } ;
if ( ! parse_time_fraction ( ) )
return false ;
m_state . parse_result . duration_hours_fraction = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationHoursPart
bool ISO8601Parser : : parse_duration_hours_part ( )
{
// DurationHoursPart :
// DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationMinutesPart
// DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationSecondsPart[opt]
StateTransaction transaction { * this } ;
if ( ! parse_duration_whole_hours ( ) )
return false ;
( void ) parse_duration_hours_fraction ( ) ;
if ( ! parse_hours_designator ( ) )
return false ;
( void ) ( parse_duration_minutes_part ( )
| | parse_duration_seconds_part ( ) ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationTime
bool ISO8601Parser : : parse_duration_time ( )
{
// DurationTime :
2021-12-18 20:58:36 +00:00
// TimeDesignator DurationHoursPart
// TimeDesignator DurationMinutesPart
// TimeDesignator DurationSecondsPart
2021-11-27 23:38:29 +00:00
StateTransaction transaction { * this } ;
2021-12-18 20:58:36 +00:00
if ( ! parse_time_designator ( ) )
2021-11-27 23:38:29 +00:00
return false ;
auto success = parse_duration_hours_part ( )
| | parse_duration_minutes_part ( )
| | parse_duration_seconds_part ( ) ;
if ( ! success )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationDays
bool ISO8601Parser : : parse_duration_days ( )
{
// DurationDays :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_days = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationDaysPart
bool ISO8601Parser : : parse_duration_days_part ( )
{
// DurationDaysPart :
// DurationDays DaysDesignator
StateTransaction transaction { * this } ;
if ( ! parse_duration_days ( ) )
return false ;
if ( ! parse_days_designator ( ) )
return false ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationWeeks
bool ISO8601Parser : : parse_duration_weeks ( )
{
// DurationWeeks :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_weeks = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationWeeksPart
bool ISO8601Parser : : parse_duration_weeks_part ( )
{
// DurationWeeksPart :
// DurationWeeks WeeksDesignator DurationDaysPart[opt]
StateTransaction transaction { * this } ;
if ( ! parse_duration_weeks ( ) )
return false ;
if ( ! parse_weeks_designator ( ) )
return false ;
( void ) parse_duration_days_part ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationMonths
bool ISO8601Parser : : parse_duration_months ( )
{
// DurationMonths :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_months = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationMonthsPart
bool ISO8601Parser : : parse_duration_months_part ( )
{
// DurationMonthsPart :
// DurationMonths MonthsDesignator DurationWeeksPart
// DurationMonths MonthsDesignator DurationDaysPart[opt]
StateTransaction transaction { * this } ;
if ( ! parse_duration_months ( ) )
return false ;
if ( ! parse_months_designator ( ) )
return false ;
( void ) ( parse_duration_weeks_part ( )
| | parse_duration_days_part ( ) ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationYears
bool ISO8601Parser : : parse_duration_years ( )
{
// DurationYears :
// DecimalDigits[~Sep]
StateTransaction transaction { * this } ;
if ( ! parse_decimal_digits ( ) )
return false ;
m_state . parse_result . duration_years = transaction . parsed_string_view ( ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationYearsPart
bool ISO8601Parser : : parse_duration_years_part ( )
{
// DurationYearsPart :
// DurationYears YearsDesignator DurationMonthsPart
// DurationYears YearsDesignator DurationWeeksPart
// DurationYears YearsDesignator DurationDaysPart[opt]
StateTransaction transaction { * this } ;
if ( ! parse_duration_years ( ) )
return false ;
if ( ! parse_years_designator ( ) )
return false ;
( void ) ( parse_duration_months_part ( )
| | parse_duration_weeks_part ( )
| | parse_duration_days_part ( ) ) ;
transaction . commit ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-DurationDate
bool ISO8601Parser : : parse_duration_date ( )
{
// DurationDate :
// DurationYearsPart DurationTime[opt]
// DurationMonthsPart DurationTime[opt]
// DurationWeeksPart DurationTime[opt]
// DurationDaysPart DurationTime[opt]
auto success = parse_duration_years_part ( )
| | parse_duration_months_part ( )
| | parse_duration_weeks_part ( )
| | parse_duration_days_part ( ) ;
if ( ! success )
return false ;
( void ) parse_duration_time ( ) ;
return true ;
}
// https://tc39.es/proposal-temporal/#prod-Duration
bool ISO8601Parser : : parse_duration ( )
{
// Duration :
// Sign[opt] DurationDesignator DurationDate
// Sign[opt] DurationDesignator DurationTime
StateTransaction transaction { * this } ;
( void ) parse_sign ( ) ;
if ( ! parse_duration_designator ( ) )
return false ;
auto success = parse_duration_date ( )
| | parse_duration_time ( ) ;
if ( ! success )
return false ;
transaction . commit ( ) ;
return true ;
}
2021-11-20 16:50:56 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalInstantString
bool ISO8601Parser : : parse_temporal_instant_string ( )
{
// TemporalInstantString :
2023-02-11 01:05:28 +00:00
// Date DateTimeSeparator TimeSpec TimeZoneUTCOffset TimeZoneAnnotation[opt] Annotations[opt]
2021-11-20 16:50:56 +00:00
StateTransaction transaction { * this } ;
if ( ! parse_date ( ) )
return false ;
2023-02-11 01:05:28 +00:00
if ( ! parse_date_time_separator ( ) )
return false ;
if ( ! parse_time_spec ( ) )
2021-12-08 19:57:19 +00:00
return false ;
2023-02-11 01:05:28 +00:00
if ( ! parse_time_zone_utc_offset ( ) )
return false ;
( void ) parse_time_zone_annotation ( ) ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2021-11-20 16:50:56 +00:00
transaction . commit ( ) ;
return true ;
}
2021-11-19 18:21:33 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalDateTimeString
bool ISO8601Parser : : parse_temporal_date_time_string ( )
{
// TemporalDateTimeString :
2022-11-02 18:26:46 +00:00
// AnnotatedDateTime
return parse_annotated_date_time ( ) ;
2021-11-19 18:21:33 +00:00
}
2021-11-27 23:38:29 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalDurationString
bool ISO8601Parser : : parse_temporal_duration_string ( )
{
// TemporalDurationString :
// Duration
return parse_duration ( ) ;
}
2021-11-19 19:05:17 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalMonthDayString
bool ISO8601Parser : : parse_temporal_month_day_string ( )
{
// TemporalMonthDayString :
2023-02-11 01:05:28 +00:00
// AnnotatedMonthDay
2022-11-02 18:26:46 +00:00
// AnnotatedDateTime
2023-02-11 01:05:28 +00:00
// NOTE: Reverse order here because `AnnotatedMonthDay` can be a subset of `AnnotatedDateTime`,
2021-11-19 19:05:17 +00:00
// so we'd not attempt to parse that but may not exhaust the input string.
2022-11-02 18:26:46 +00:00
return parse_annotated_date_time ( )
2023-02-11 01:05:28 +00:00
| | parse_annotated_month_day ( ) ;
2021-11-19 19:05:17 +00:00
}
2021-11-19 18:36:14 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalTimeString
bool ISO8601Parser : : parse_temporal_time_string ( )
{
// TemporalTimeString :
2022-11-02 18:26:46 +00:00
// AnnotatedTime
// AnnotatedDateTimeTimeRequired
// NOTE: Reverse order here because `AnnotatedTime` can be a subset of `AnnotatedDateTimeTimeRequired`,
2021-11-19 18:36:14 +00:00
// so we'd not attempt to parse that but may not exhaust the input string.
2022-11-02 18:26:46 +00:00
return parse_annotated_date_time_time_required ( )
| | parse_annotated_time ( ) ;
2021-11-19 18:36:14 +00:00
}
2021-11-19 19:19:29 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalYearMonthString
bool ISO8601Parser : : parse_temporal_year_month_string ( )
{
// TemporalYearMonthString :
2023-02-11 01:05:28 +00:00
// AnnotatedYearMonth
2022-11-02 18:26:46 +00:00
// AnnotatedDateTime
2023-02-11 01:05:28 +00:00
// NOTE: Reverse order here because `AnnotatedYearMonth` can be a subset of `AnnotatedDateTime`,
2021-11-19 19:19:29 +00:00
// so we'd not attempt to parse that but may not exhaust the input string.
2022-11-02 18:26:46 +00:00
return parse_annotated_date_time ( )
2023-02-11 01:05:28 +00:00
| | parse_annotated_year_month ( ) ;
2021-11-19 19:19:29 +00:00
}
2021-11-19 20:43:52 +00:00
// https://tc39.es/proposal-temporal/#prod-TemporalZonedDateTimeString
bool ISO8601Parser : : parse_temporal_zoned_date_time_string ( )
{
// TemporalZonedDateTimeString :
2023-02-11 01:05:28 +00:00
// DateTime TimeZoneAnnotation Annotations[opt]
2021-11-19 20:43:52 +00:00
StateTransaction transaction { * this } ;
2023-02-11 01:05:28 +00:00
if ( ! parse_date_time ( ) )
2021-11-19 20:43:52 +00:00
return false ;
2023-02-11 01:05:28 +00:00
if ( ! parse_time_zone_annotation ( ) )
2021-11-19 20:43:52 +00:00
return false ;
2022-11-02 18:26:46 +00:00
( void ) parse_annotations ( ) ;
2021-11-19 20:43:52 +00:00
transaction . commit ( ) ;
return true ;
}
2021-11-19 18:04:50 +00:00
}
2021-11-19 20:53:07 +00:00
# define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \
2021-11-20 16:50:56 +00:00
__JS_ENUMERATE ( TemporalInstantString , parse_temporal_instant_string ) \
2021-11-19 20:53:07 +00:00
__JS_ENUMERATE ( TemporalDateTimeString , parse_temporal_date_time_string ) \
2021-11-27 23:38:29 +00:00
__JS_ENUMERATE ( TemporalDurationString , parse_temporal_duration_string ) \
2021-11-19 20:53:07 +00:00
__JS_ENUMERATE ( TemporalMonthDayString , parse_temporal_month_day_string ) \
__JS_ENUMERATE ( TemporalTimeString , parse_temporal_time_string ) \
__JS_ENUMERATE ( TemporalYearMonthString , parse_temporal_year_month_string ) \
__JS_ENUMERATE ( TemporalZonedDateTimeString , parse_temporal_zoned_date_time_string ) \
2022-10-20 00:19:09 +03:00
__JS_ENUMERATE ( TimeZoneIdentifier , parse_time_zone_identifier ) \
2022-08-30 17:43:27 +01:00
__JS_ENUMERATE ( TimeZoneNumericUTCOffset , parse_time_zone_numeric_utc_offset ) \
2022-11-02 18:26:46 +00:00
__JS_ENUMERATE ( AnnotationValue , parse_annotation_value ) \
2022-10-16 12:26:12 +01:00
__JS_ENUMERATE ( DateMonth , parse_date_month )
2021-11-19 18:04:50 +00:00
Optional < ParseResult > parse_iso8601 ( Production production , StringView input )
{
auto parser = Detail : : ISO8601Parser { input } ;
switch ( production ) {
# define __JS_ENUMERATE(ProductionName, parse_production) \
case Production : : ProductionName : \
if ( ! parser . parse_production ( ) ) \
return { } ; \
break ;
JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS
# undef __JS_ENUMERATE
default :
VERIFY_NOT_REACHED ( ) ;
}
// If we parsed successfully but didn't reach the end, the string doesn't match the given production.
if ( ! parser . lexer ( ) . is_eof ( ) )
return { } ;
return parser . parse_result ( ) ;
}
2021-12-22 22:44:46 +01:00
2021-11-19 18:04:50 +00:00
}