ISO8601.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/GenericLexer.h>
  8. #include <AK/Optional.h>
  9. #include <AK/StringView.h>
  10. #include <AK/Vector.h>
  11. namespace JS::Temporal {
  12. struct ParseResult {
  13. Optional<StringView> sign;
  14. Optional<StringView> date_year;
  15. Optional<StringView> date_month;
  16. Optional<StringView> date_day;
  17. Optional<StringView> time_hour;
  18. Optional<StringView> time_minute;
  19. Optional<StringView> time_second;
  20. Optional<StringView> time_fraction;
  21. Optional<StringView> time_hour_not_valid_month;
  22. Optional<StringView> time_hour_not_thirty_one_day_month;
  23. Optional<StringView> time_hour_two_only;
  24. Optional<StringView> time_minute_not_valid_day;
  25. Optional<StringView> time_minute_thirty_only;
  26. Optional<StringView> time_minute_thirty_one_only;
  27. Optional<StringView> time_second_not_valid_month;
  28. Optional<StringView> calendar_name;
  29. Optional<StringView> utc_designator;
  30. Optional<StringView> time_zone_numeric_utc_offset;
  31. Optional<StringView> time_zone_utc_offset_sign;
  32. Optional<StringView> time_zone_utc_offset_hour;
  33. Optional<StringView> time_zone_utc_offset_minute;
  34. Optional<StringView> time_zone_utc_offset_second;
  35. Optional<StringView> time_zone_utc_offset_fractional_part;
  36. Optional<StringView> time_zone_iana_name;
  37. Optional<StringView> duration_years;
  38. Optional<StringView> duration_months;
  39. Optional<StringView> duration_weeks;
  40. Optional<StringView> duration_days;
  41. Optional<StringView> duration_whole_hours;
  42. Optional<StringView> duration_hours_fraction;
  43. Optional<StringView> duration_whole_minutes;
  44. Optional<StringView> duration_minutes_fraction;
  45. Optional<StringView> duration_whole_seconds;
  46. Optional<StringView> duration_seconds_fraction;
  47. };
  48. enum class Production {
  49. TemporalInstantString,
  50. TemporalDateString,
  51. TemporalDateTimeString,
  52. TemporalDurationString,
  53. TemporalMonthDayString,
  54. TemporalTimeString,
  55. TemporalTimeZoneString,
  56. TemporalYearMonthString,
  57. TemporalZonedDateTimeString,
  58. TemporalCalendarString,
  59. TemporalRelativeToString,
  60. };
  61. Optional<ParseResult> parse_iso8601(Production, StringView);
  62. namespace Detail {
  63. // 13.33 ISO 8601 grammar, https://tc39.es/proposal-temporal/#sec-temporal-iso8601grammar
  64. class ISO8601Parser {
  65. public:
  66. explicit ISO8601Parser(StringView input)
  67. : m_input(input)
  68. , m_state({
  69. .lexer = GenericLexer { input },
  70. .parse_result = {},
  71. })
  72. {
  73. }
  74. [[nodiscard]] GenericLexer const& lexer() const { return m_state.lexer; }
  75. [[nodiscard]] ParseResult const& parse_result() const { return m_state.parse_result; }
  76. [[nodiscard]] bool parse_decimal_digits();
  77. [[nodiscard]] bool parse_decimal_digit();
  78. [[nodiscard]] bool parse_non_zero_digit();
  79. [[nodiscard]] bool parse_ascii_sign();
  80. [[nodiscard]] bool parse_sign();
  81. [[nodiscard]] bool parse_hour();
  82. [[nodiscard]] bool parse_minute_second();
  83. [[nodiscard]] bool parse_decimal_separator();
  84. [[nodiscard]] bool parse_days_designator();
  85. [[nodiscard]] bool parse_hours_designator();
  86. [[nodiscard]] bool parse_minutes_designator();
  87. [[nodiscard]] bool parse_months_designator();
  88. [[nodiscard]] bool parse_duration_designator();
  89. [[nodiscard]] bool parse_seconds_designator();
  90. [[nodiscard]] bool parse_date_time_separator();
  91. [[nodiscard]] bool parse_time_designator();
  92. [[nodiscard]] bool parse_weeks_designator();
  93. [[nodiscard]] bool parse_years_designator();
  94. [[nodiscard]] bool parse_utc_designator();
  95. [[nodiscard]] bool parse_date_year();
  96. [[nodiscard]] bool parse_date_month();
  97. [[nodiscard]] bool parse_date_day();
  98. [[nodiscard]] bool parse_date_spec_year_month();
  99. [[nodiscard]] bool parse_date_spec_month_day();
  100. [[nodiscard]] bool parse_date();
  101. [[nodiscard]] bool parse_time_hour();
  102. [[nodiscard]] bool parse_time_minute();
  103. [[nodiscard]] bool parse_time_second();
  104. [[nodiscard]] bool parse_time_hour_not_valid_month();
  105. [[nodiscard]] bool parse_time_hour_not_thirty_one_day_month();
  106. [[nodiscard]] bool parse_time_hour_two_only();
  107. [[nodiscard]] bool parse_time_minute_not_valid_day();
  108. [[nodiscard]] bool parse_time_minute_thirty_only();
  109. [[nodiscard]] bool parse_time_minute_thirty_one_only();
  110. [[nodiscard]] bool parse_time_second_not_valid_month();
  111. [[nodiscard]] bool parse_fractional_part();
  112. [[nodiscard]] bool parse_fraction();
  113. [[nodiscard]] bool parse_time_fraction();
  114. [[nodiscard]] bool parse_time_zone_utc_offset_sign();
  115. [[nodiscard]] bool parse_time_zone_utc_offset_hour();
  116. [[nodiscard]] bool parse_time_zone_utc_offset_minute();
  117. [[nodiscard]] bool parse_time_zone_utc_offset_second();
  118. [[nodiscard]] bool parse_time_zone_utc_offset_fractional_part();
  119. [[nodiscard]] bool parse_time_zone_utc_offset_fraction();
  120. [[nodiscard]] bool parse_time_zone_numeric_utc_offset();
  121. [[nodiscard]] bool parse_time_zone_utc_offset();
  122. [[nodiscard]] bool parse_time_zone_numeric_utc_offset_not_ambiguous();
  123. [[nodiscard]] bool parse_time_zone_numeric_utc_offset_not_ambiguous_allowed_negative_hour();
  124. [[nodiscard]] bool parse_time_zone_utc_offset_name();
  125. [[nodiscard]] bool parse_tz_leading_char();
  126. [[nodiscard]] bool parse_tz_char();
  127. [[nodiscard]] bool parse_time_zone_iana_component();
  128. [[nodiscard]] bool parse_time_zone_iana_name_tail();
  129. [[nodiscard]] bool parse_time_zone_iana_name();
  130. [[nodiscard]] bool parse_time_zone_bracketed_name();
  131. [[nodiscard]] bool parse_time_zone_bracketed_annotation();
  132. [[nodiscard]] bool parse_time_zone_offset_required();
  133. [[nodiscard]] bool parse_time_zone_name_required();
  134. [[nodiscard]] bool parse_time_zone();
  135. [[nodiscard]] bool parse_calendar_name();
  136. [[nodiscard]] bool parse_calendar();
  137. [[nodiscard]] bool parse_time_spec();
  138. [[nodiscard]] bool parse_time_hour_minute_basic_format_not_ambiguous();
  139. [[nodiscard]] bool parse_time_spec_with_optional_time_zone_not_ambiguous();
  140. [[nodiscard]] bool parse_time_spec_separator();
  141. [[nodiscard]] bool parse_date_time();
  142. [[nodiscard]] bool parse_calendar_time();
  143. [[nodiscard]] bool parse_calendar_date_time();
  144. [[nodiscard]] bool parse_calendar_date_time_time_required();
  145. [[nodiscard]] bool parse_duration_whole_seconds();
  146. [[nodiscard]] bool parse_duration_seconds_fraction();
  147. [[nodiscard]] bool parse_duration_seconds_part();
  148. [[nodiscard]] bool parse_duration_whole_minutes();
  149. [[nodiscard]] bool parse_duration_minutes_fraction();
  150. [[nodiscard]] bool parse_duration_minutes_part();
  151. [[nodiscard]] bool parse_duration_whole_hours();
  152. [[nodiscard]] bool parse_duration_hours_fraction();
  153. [[nodiscard]] bool parse_duration_hours_part();
  154. [[nodiscard]] bool parse_duration_time();
  155. [[nodiscard]] bool parse_duration_days();
  156. [[nodiscard]] bool parse_duration_days_part();
  157. [[nodiscard]] bool parse_duration_weeks();
  158. [[nodiscard]] bool parse_duration_weeks_part();
  159. [[nodiscard]] bool parse_duration_months();
  160. [[nodiscard]] bool parse_duration_months_part();
  161. [[nodiscard]] bool parse_duration_years();
  162. [[nodiscard]] bool parse_duration_years_part();
  163. [[nodiscard]] bool parse_duration_date();
  164. [[nodiscard]] bool parse_duration();
  165. [[nodiscard]] bool parse_temporal_instant_string();
  166. [[nodiscard]] bool parse_temporal_date_string();
  167. [[nodiscard]] bool parse_temporal_date_time_string();
  168. [[nodiscard]] bool parse_temporal_duration_string();
  169. [[nodiscard]] bool parse_temporal_month_day_string();
  170. [[nodiscard]] bool parse_temporal_time_string();
  171. [[nodiscard]] bool parse_temporal_time_zone_identifier();
  172. [[nodiscard]] bool parse_temporal_time_zone_string();
  173. [[nodiscard]] bool parse_temporal_year_month_string();
  174. [[nodiscard]] bool parse_temporal_zoned_date_time_string();
  175. [[nodiscard]] bool parse_temporal_calendar_string();
  176. [[nodiscard]] bool parse_temporal_relative_to_string();
  177. private:
  178. struct State {
  179. GenericLexer lexer;
  180. ParseResult parse_result;
  181. };
  182. struct StateTransaction {
  183. explicit StateTransaction(ISO8601Parser& parser)
  184. : m_parser(parser)
  185. , m_saved_state(parser.m_state)
  186. , m_start_index(parser.m_state.lexer.tell())
  187. {
  188. }
  189. ~StateTransaction()
  190. {
  191. if (!m_commit)
  192. m_parser.m_state = move(m_saved_state);
  193. }
  194. void commit() { m_commit = true; }
  195. StringView parsed_string_view() const
  196. {
  197. return m_parser.m_input.substring_view(m_start_index, m_parser.m_state.lexer.tell() - m_start_index);
  198. }
  199. private:
  200. ISO8601Parser& m_parser;
  201. State m_saved_state;
  202. size_t m_start_index { 0 };
  203. bool m_commit { false };
  204. };
  205. StringView m_input;
  206. State m_state;
  207. };
  208. }
  209. }