Skip to content

Commit

Permalink
Clean up parse output nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss committed Oct 5, 2023
1 parent 9db8b47 commit b52631b
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 174 deletions.
166 changes: 62 additions & 104 deletions boa_ast/src/temporal/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
//! AST nodes for Temporal's implementation of ISO8601 grammar.
/// An `ISOParseRecord` is the full record of a node that is returned via the parse records.
///
/// This node comes complete with the parsed date, time, time zone, and calendar data.
#[derive(Default, Debug)]
pub struct IsoParseRecord {
/// Parsed Date Record
pub date: DateRecord,
/// Parsed Time
pub time: Option<TimeSpec>,
/// Parsed `TimeZone` data (UTCOffset | IANA name)
pub tz: Option<TimeZone>,
/// The parsed calendar value.
pub calendar: Option<String>,
}

/// An ISO Date Node consisting of only date fields and any calendar value.
/// An ISO Date Node consisting of non-validated date fields and calendar value.
#[derive(Default, Debug)]
pub struct ISODate {
/// Date Year
Expand All @@ -28,51 +13,54 @@ pub struct ISODate {
pub calendar: Option<String>,
}

/// The `ISOTime` node consists of non-validated time fields.
#[derive(Default, Debug, Clone, Copy)]
/// The record of a parsed date.
pub struct DateRecord {
/// Date Year
pub year: i32,
/// Date Month
pub month: i32,
/// Date Day
pub day: i32,
pub struct ISOTime {
/// An hour value between 0-23
pub hour: u8,
/// A minute value between 0-59
pub minute: u8,
/// A second value between 0-60
pub second: u8,
/// A millisecond value between 0-999
pub millisecond: u16,
/// A microsecond value between 0-999
pub microsecond: u16,
/// A nanosecond value between 0-999
pub nanosecond: u16,
}

/// Parsed Time info
#[derive(Debug, Default, Clone, Copy)]
#[allow(dead_code)]
pub struct TimeSpec {
/// An hour
pub hour: i8,
/// A minute value
pub minute: i8,
/// A floating point second value.
pub second: f64,
}

/// `TimeZone` UTC Offset info.
#[derive(Debug, Clone, Copy)]
pub struct DateTimeUtcOffset;
impl ISOTime {
#[must_use]
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
/// A utility initialization function to create `ISOTime` from the `TimeSpec` components.
pub fn from_components(hour: u8, minute: u8, second: u8, fraction: f64) -> Self {
// Note: Precision on nanoseconds drifts, so opting for round over floor or ceil for now.
// e.g. 0.329402834 becomes 329.402833.999
let millisecond = fraction * 1000.0;
let micros = millisecond.rem_euclid(1.0) * 1000.0;
let nanos = micros.rem_euclid(1.0) * 1000.0;

#[derive(Debug, Default, Clone)]
/// A `DateTime` Parse Node that contains the date, time, and offset info.
pub struct DateTimeRecord {
/// Date
pub date: DateRecord,
/// Time
pub time: Option<TimeSpec>,
/// Tz Offset
pub time_zone: Option<TimeZone>,
Self {
hour,
minute,
second,
millisecond: millisecond.floor() as u16,
microsecond: micros.floor() as u16,
nanosecond: nanos.round() as u16,
}
}
}

/// A `TimeZoneAnnotation`.
#[derive(Debug, Clone)]
pub struct TimeZoneAnnotation {
/// Critical Flag for the annotation.
pub critical: bool,
/// TimeZone Data
pub tz: TimeZone,
/// The `ISODateTime` node output by the ISO parser
#[derive(Default, Debug)]
pub struct ISODateTime {
/// The `ISODate` record
pub date: ISODate,
/// The `ISOTime` record
pub time: ISOTime,
/// The `TimeZone` value for this `ISODateTime`
pub tz: Option<TimeZone>,
}

/// `TimeZone` data
Expand All @@ -84,55 +72,24 @@ pub struct TimeZone {
pub offset: Option<UTCOffset>,
}

/// A valid `TimeZoneIdentifier` that is defined by
/// the specification as either a UTC Offset to minute
/// precision or a `TimeZoneIANAName`
#[derive(Debug, Clone)]
pub enum TzIdentifier {
/// A valid UTC `TimeZoneIdentifier` value
UtcOffset(UTCOffset),
/// A valid IANA name `TimeZoneIdentifier` value
TzIANAName(String),
}

/// A full precision `UtcOffset`
#[derive(Debug, Clone, Copy)]
pub struct UTCOffset {
/// The `+`/`-` sign of this `UtcOffset`
pub sign: i8,
/// The hour value of the `UtcOffset`
pub hour: i8,
pub hour: u8,
/// The minute value of the `UtcOffset`.
pub minute: i8,
/// A float representing the second value of the `UtcOffset`.
pub second: f64,
}

/// A `KeyValueAnnotation` Parse Node.
#[derive(Debug, Clone)]
pub struct KeyValueAnnotation {
/// An `Annotation`'s Key.
pub key: String,
/// An `Annotation`'s value.
pub value: String,
/// Whether the annotation was flagged as critical.
pub critical: bool,
}

/// A ISO8601 `DurationRecord` Parse Node.
#[derive(Debug, Clone, Copy)]
pub struct DurationParseRecord {
/// Duration Sign
pub sign: bool,
/// A `DateDuration` record.
pub date: DateDuration,
/// A `TimeDuration` record.
pub time: TimeDuration,
pub minute: u8,
/// The second value of the `UtcOffset`.
pub second: u8,
/// Any sub second components of the `UTCOffset`
pub fraction: f64,
}

/// A `DateDuration` Parse Node.
#[derive(Default, Debug, Clone, Copy)]
pub struct DateDuration {
/// An `ISODuration` Node output by the ISO parser.
#[derive(Debug, Default, Clone, Copy)]
pub struct ISODuration {
/// Years value.
pub years: i32,
/// Months value.
Expand All @@ -141,15 +98,16 @@ pub struct DateDuration {
pub weeks: i32,
/// Days value.
pub days: i32,
}

/// A `TimeDuration` Parse Node
#[derive(Default, Debug, Clone, Copy)]
pub struct TimeDuration {
/// Hours value with fraction.
pub hours: f64,
/// Minutes value with fraction.
/// Hours value.
pub hours: i32,
/// Minutes value.
pub minutes: f64,
/// Seconds value with fraction.
/// Seconds value.
pub seconds: f64,
/// Milliseconds value.
pub milliseconds: f64,
/// Microseconds value.
pub microseconds: f64,
/// Nanoseconds value.
pub nanoseconds: f64,
}
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/temporal/duration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ pub(crate) fn to_temporal_duration(item: &JsValue) -> JsResult<DurationRecord> {
// a. Return item.
let obj = o.borrow();
let duration = obj.as_duration().expect("must be a duration.");
return Ok(duration.inner.clone());
return Ok(duration.inner);
}
}

Expand Down
1 change: 1 addition & 0 deletions boa_engine/src/builtins/temporal/plain_date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ pub(crate) fn to_temporal_date(
// 8. Let calendar be result.[[Calendar]].
// 9. If calendar is undefined, set calendar to "iso8601".
let identifier = result
.date
.calendar
.map_or_else(|| js_string!("iso8601"), JsString::from);

Expand Down
20 changes: 15 additions & 5 deletions boa_parser/src/temporal/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@ use crate::{
is_a_key_char, is_a_key_leading_char, is_annotation_close,
is_annotation_key_value_separator, is_annotation_value_component, is_critical_flag,
},
time_zone, IsoCursor,
time_zone,
time_zone::TimeZoneAnnotation,
IsoCursor,
},
};

use boa_ast::{
temporal::{KeyValueAnnotation, TimeZoneAnnotation},
Position, Span,
};
use boa_ast::{Position, Span};

use super::grammar::{is_annotation_open, is_hyphen};

/// A `KeyValueAnnotation` Parse Node.
#[derive(Debug, Clone)]
pub(crate) struct KeyValueAnnotation {
/// An `Annotation`'s Key.
pub(crate) key: String,
/// An `Annotation`'s value.
pub(crate) value: String,
/// Whether the annotation was flagged as critical.
pub(crate) critical: bool,
}

/// Strictly a Parsing Intermediary for the checking the common annotation backing.
pub(crate) struct AnnotationSet {
pub(crate) tz: Option<TimeZoneAnnotation>,
Expand Down
31 changes: 26 additions & 5 deletions boa_parser/src/temporal/date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,38 @@ use crate::{
temporal::{
annotations,
grammar::{is_date_time_separator, is_sign, is_utc_designator},
time, time_zone, IsoCursor,
time,
time::TimeSpec,
time_zone, IsoCursor, IsoParseRecord,
},
};

use boa_ast::{
temporal::{DateRecord, DateTimeRecord, IsoParseRecord, TimeZone},
Position, Span,
};
use boa_ast::{temporal::TimeZone, Position, Span};

use super::grammar::{is_annotation_open, is_hyphen};

#[derive(Debug, Default, Clone)]
/// A `DateTime` Parse Node that contains the date, time, and offset info.
pub(crate) struct DateTimeRecord {
/// Date
pub(crate) date: DateRecord,
/// Time
pub(crate) time: Option<TimeSpec>,
/// Tz Offset
pub(crate) time_zone: Option<TimeZone>,
}

#[derive(Default, Debug, Clone, Copy)]
/// The record of a parsed date.
pub(crate) struct DateRecord {
/// Date Year
pub(crate) year: i32,
/// Date Month
pub(crate) month: i32,
/// Date Day
pub(crate) day: i32,
}

/// This function handles parsing for [`AnnotatedDateTime`][datetime],
/// [`AnnotatedDateTimeTimeRequred`][time], and
/// [`TemporalInstantString.`][instant] according to the requirements
Expand Down
Loading

0 comments on commit b52631b

Please sign in to comment.