ISO8601.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  1. /*
  2. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/CharacterTypes.h>
  7. #include <LibJS/Runtime/Temporal/ISO8601.h>
  8. namespace JS::Temporal {
  9. namespace Detail {
  10. // https://tc39.es/proposal-temporal/#prod-DecimalDigits
  11. bool ISO8601Parser::parse_decimal_digits()
  12. {
  13. // DecimalDigits[Sep] ::
  14. // DecimalDigit
  15. // DecimalDigits[?Sep] DecimalDigit
  16. // [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit
  17. // NOTE: Temporal exclusively uses the variant without a separator ([~Sep])
  18. if (!parse_decimal_digit())
  19. return false;
  20. while (parse_decimal_digit())
  21. ;
  22. return true;
  23. }
  24. // https://tc39.es/proposal-temporal/#prod-DecimalDigit
  25. bool ISO8601Parser::parse_decimal_digit()
  26. {
  27. // DecimalDigit : one of
  28. // 0 1 2 3 4 5 6 7 8 9
  29. if (m_state.lexer.next_is(is_ascii_digit)) {
  30. m_state.lexer.consume();
  31. return true;
  32. }
  33. return false;
  34. }
  35. // https://tc39.es/proposal-temporal/#prod-NonZeroDigit
  36. bool ISO8601Parser::parse_non_zero_digit()
  37. {
  38. // NonZeroDigit : one of
  39. // 1 2 3 4 5 6 7 8 9
  40. if (m_state.lexer.next_is(is_ascii_digit) && !m_state.lexer.next_is('0')) {
  41. m_state.lexer.consume();
  42. return true;
  43. }
  44. return false;
  45. }
  46. // https://tc39.es/proposal-temporal/#prod-ASCIISign
  47. bool ISO8601Parser::parse_ascii_sign()
  48. {
  49. // ASCIISign : one of
  50. // + -
  51. return m_state.lexer.consume_specific('+')
  52. || m_state.lexer.consume_specific('-');
  53. }
  54. // https://tc39.es/proposal-temporal/#prod-Sign
  55. bool ISO8601Parser::parse_sign()
  56. {
  57. // Sign :
  58. // ASCIISign
  59. // U+2212
  60. StateTransaction transaction { *this };
  61. auto success = parse_ascii_sign()
  62. || m_state.lexer.consume_specific("\xE2\x88\x92"sv);
  63. if (!success)
  64. return false;
  65. m_state.parse_result.sign = transaction.parsed_string_view();
  66. transaction.commit();
  67. return true;
  68. }
  69. // https://tc39.es/proposal-temporal/#prod-Hour
  70. bool ISO8601Parser::parse_hour()
  71. {
  72. // Hour :
  73. // 0 DecimalDigit
  74. // 1 DecimalDigit
  75. // 20
  76. // 21
  77. // 22
  78. // 23
  79. StateTransaction transaction { *this };
  80. if (m_state.lexer.consume_specific('0') || m_state.lexer.consume_specific('1')) {
  81. if (!parse_decimal_digit())
  82. return false;
  83. } else {
  84. auto success = m_state.lexer.consume_specific("20"sv)
  85. || m_state.lexer.consume_specific("21"sv)
  86. || m_state.lexer.consume_specific("22"sv)
  87. || m_state.lexer.consume_specific("23"sv);
  88. if (!success)
  89. return false;
  90. }
  91. transaction.commit();
  92. return true;
  93. }
  94. // https://tc39.es/proposal-temporal/#prod-MinuteSecond
  95. bool ISO8601Parser::parse_minute_second()
  96. {
  97. // MinuteSecond :
  98. // 0 DecimalDigit
  99. // 1 DecimalDigit
  100. // 2 DecimalDigit
  101. // 3 DecimalDigit
  102. // 4 DecimalDigit
  103. // 5 DecimalDigit
  104. StateTransaction transaction { *this };
  105. auto success = m_state.lexer.consume_specific('0')
  106. || m_state.lexer.consume_specific('1')
  107. || m_state.lexer.consume_specific('2')
  108. || m_state.lexer.consume_specific('3')
  109. || m_state.lexer.consume_specific('4')
  110. || m_state.lexer.consume_specific('5');
  111. if (!success)
  112. return false;
  113. if (!parse_decimal_digit())
  114. return false;
  115. transaction.commit();
  116. return true;
  117. }
  118. // https://tc39.es/proposal-temporal/#prod-DecimalSeparator
  119. bool ISO8601Parser::parse_decimal_separator()
  120. {
  121. // DecimalSeparator : one of
  122. // . ,
  123. return m_state.lexer.consume_specific('.')
  124. || m_state.lexer.consume_specific(',');
  125. }
  126. // https://tc39.es/proposal-temporal/#prod-DaysDesignator
  127. bool ISO8601Parser::parse_days_designator()
  128. {
  129. // DaysDesignator : one of
  130. // D d
  131. return m_state.lexer.consume_specific('D')
  132. || m_state.lexer.consume_specific('d');
  133. }
  134. // https://tc39.es/proposal-temporal/#prod-HoursDesignator
  135. bool ISO8601Parser::parse_hours_designator()
  136. {
  137. // HoursDesignator : one of
  138. // H h
  139. return m_state.lexer.consume_specific('H')
  140. || m_state.lexer.consume_specific('h');
  141. }
  142. // https://tc39.es/proposal-temporal/#prod-MinutesDesignator
  143. bool ISO8601Parser::parse_minutes_designator()
  144. {
  145. // MinutesDesignator : one of
  146. // M m
  147. return m_state.lexer.consume_specific('M')
  148. || m_state.lexer.consume_specific('m');
  149. }
  150. // https://tc39.es/proposal-temporal/#prod-MonthsDesignator
  151. bool ISO8601Parser::parse_months_designator()
  152. {
  153. // MonthsDesignator : one of
  154. // M m
  155. return m_state.lexer.consume_specific('M')
  156. || m_state.lexer.consume_specific('m');
  157. }
  158. // https://tc39.es/proposal-temporal/#prod-DurationDesignator
  159. bool ISO8601Parser::parse_duration_designator()
  160. {
  161. // DurationDesignator : one of
  162. // P p
  163. return m_state.lexer.consume_specific('P')
  164. || m_state.lexer.consume_specific('p');
  165. }
  166. // https://tc39.es/proposal-temporal/#prod-SecondsDesignator
  167. bool ISO8601Parser::parse_seconds_designator()
  168. {
  169. // SecondsDesignator : one of
  170. // S s
  171. return m_state.lexer.consume_specific('S')
  172. || m_state.lexer.consume_specific('s');
  173. }
  174. // https://tc39.es/proposal-temporal/#prod-DateTimeSeparator
  175. bool ISO8601Parser::parse_date_time_separator()
  176. {
  177. // DateTimeSeparator :
  178. // <SP>
  179. // T
  180. // t
  181. return m_state.lexer.consume_specific(' ')
  182. || m_state.lexer.consume_specific('T')
  183. || m_state.lexer.consume_specific('t');
  184. }
  185. // https://tc39.es/proposal-temporal/#prod-DurationTimeDesignator
  186. bool ISO8601Parser::parse_duration_time_designator()
  187. {
  188. // DurationTimeDesignator : one of
  189. // T t
  190. return m_state.lexer.consume_specific('T')
  191. || m_state.lexer.consume_specific('t');
  192. }
  193. // https://tc39.es/proposal-temporal/#prod-WeeksDesignator
  194. bool ISO8601Parser::parse_weeks_designator()
  195. {
  196. // WeeksDesignator : one of
  197. // W w
  198. return m_state.lexer.consume_specific('W')
  199. || m_state.lexer.consume_specific('w');
  200. }
  201. // https://tc39.es/proposal-temporal/#prod-YearsDesignator
  202. bool ISO8601Parser::parse_years_designator()
  203. {
  204. // YearsDesignator : one of
  205. // Y y
  206. return m_state.lexer.consume_specific('Y')
  207. || m_state.lexer.consume_specific('y');
  208. }
  209. // https://tc39.es/proposal-temporal/#prod-UTCDesignator
  210. bool ISO8601Parser::parse_utc_designator()
  211. {
  212. // UTCDesignator : one of
  213. // Z z
  214. StateTransaction transaction { *this };
  215. auto success = m_state.lexer.consume_specific('Z')
  216. || m_state.lexer.consume_specific('z');
  217. if (!success)
  218. return false;
  219. m_state.parse_result.utc_designator = transaction.parsed_string_view();
  220. transaction.commit();
  221. return true;
  222. }
  223. // https://tc39.es/proposal-temporal/#prod-DateYear
  224. bool ISO8601Parser::parse_date_year()
  225. {
  226. // DateFourDigitYear :
  227. // DecimalDigit DecimalDigit DecimalDigit DecimalDigit
  228. // DateExtendedYear :
  229. // Sign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit
  230. // DateYear :
  231. // DateFourDigitYear
  232. // DateExtendedYear
  233. StateTransaction transaction { *this };
  234. if (parse_sign()) {
  235. for (size_t i = 0; i < 6; ++i) {
  236. if (!parse_decimal_digit())
  237. return false;
  238. }
  239. } else {
  240. for (size_t i = 0; i < 4; ++i) {
  241. if (!parse_decimal_digit())
  242. return false;
  243. }
  244. }
  245. m_state.parse_result.date_year = transaction.parsed_string_view();
  246. transaction.commit();
  247. return true;
  248. }
  249. // https://tc39.es/proposal-temporal/#prod-DateMonth
  250. bool ISO8601Parser::parse_date_month()
  251. {
  252. // DateMonth :
  253. // 0 NonZeroDigit
  254. // 10
  255. // 11
  256. // 12
  257. StateTransaction transaction { *this };
  258. if (m_state.lexer.consume_specific('0')) {
  259. if (!parse_non_zero_digit())
  260. return false;
  261. } else {
  262. auto success = m_state.lexer.consume_specific("10"sv)
  263. || m_state.lexer.consume_specific("11"sv)
  264. || m_state.lexer.consume_specific("12"sv);
  265. if (!success)
  266. return false;
  267. }
  268. m_state.parse_result.date_month = transaction.parsed_string_view();
  269. transaction.commit();
  270. return true;
  271. }
  272. // https://tc39.es/proposal-temporal/#prod-DateDay
  273. bool ISO8601Parser::parse_date_day()
  274. {
  275. // DateDay :
  276. // 0 NonZeroDigit
  277. // 1 DecimalDigit
  278. // 2 DecimalDigit
  279. // 30
  280. // 31
  281. StateTransaction transaction { *this };
  282. if (m_state.lexer.consume_specific('0')) {
  283. if (!parse_non_zero_digit())
  284. return false;
  285. } else if (m_state.lexer.consume_specific('1') || m_state.lexer.consume_specific('2')) {
  286. if (!parse_decimal_digit())
  287. return false;
  288. } else {
  289. auto success = m_state.lexer.consume_specific("30"sv)
  290. || m_state.lexer.consume_specific("31"sv);
  291. if (!success)
  292. return false;
  293. }
  294. m_state.parse_result.date_day = transaction.parsed_string_view();
  295. transaction.commit();
  296. return true;
  297. }
  298. // https://tc39.es/proposal-temporal/#prod-DateSpecYearMonth
  299. bool ISO8601Parser::parse_date_spec_year_month()
  300. {
  301. // DateSpecYearMonth :
  302. // DateYear -[opt] DateMonth
  303. StateTransaction transaction { *this };
  304. if (!parse_date_year())
  305. return false;
  306. m_state.lexer.consume_specific('-');
  307. if (!parse_date_month())
  308. return false;
  309. transaction.commit();
  310. return true;
  311. }
  312. // https://tc39.es/proposal-temporal/#prod-DateSpecMonthDay
  313. bool ISO8601Parser::parse_date_spec_month_day()
  314. {
  315. // TwoDashes :
  316. // --
  317. // DateSpecMonthDay :
  318. // TwoDashes[opt] DateMonth -[opt] DateDay
  319. StateTransaction transaction { *this };
  320. m_state.lexer.consume_specific("--"sv);
  321. if (!parse_date_month())
  322. return false;
  323. m_state.lexer.consume_specific('-');
  324. if (!parse_date_day())
  325. return false;
  326. transaction.commit();
  327. return true;
  328. }
  329. // https://tc39.es/proposal-temporal/#prod-Date
  330. bool ISO8601Parser::parse_date()
  331. {
  332. // Date :
  333. // DateYear - DateMonth - DateDay
  334. // DateYear DateMonth DateDay
  335. StateTransaction transaction { *this };
  336. if (!parse_date_year())
  337. return false;
  338. auto with_dashes = m_state.lexer.consume_specific('-');
  339. if (!parse_date_month())
  340. return false;
  341. if (with_dashes && !m_state.lexer.consume_specific('-'))
  342. return false;
  343. if (!parse_date_day())
  344. return false;
  345. transaction.commit();
  346. return true;
  347. }
  348. // https://tc39.es/proposal-temporal/#prod-TimeHour
  349. bool ISO8601Parser::parse_time_hour()
  350. {
  351. // TimeHour :
  352. // Hour
  353. StateTransaction transaction { *this };
  354. if (!parse_hour())
  355. return false;
  356. m_state.parse_result.time_hour = transaction.parsed_string_view();
  357. transaction.commit();
  358. return true;
  359. }
  360. // https://tc39.es/proposal-temporal/#prod-TimeMinute
  361. bool ISO8601Parser::parse_time_minute()
  362. {
  363. // TimeMinute :
  364. // MinuteSecond
  365. StateTransaction transaction { *this };
  366. if (!parse_minute_second())
  367. return false;
  368. m_state.parse_result.time_minute = transaction.parsed_string_view();
  369. transaction.commit();
  370. return true;
  371. }
  372. // https://tc39.es/proposal-temporal/#prod-TimeSecond
  373. bool ISO8601Parser::parse_time_second()
  374. {
  375. // TimeSecond :
  376. // MinuteSecond
  377. // 60
  378. StateTransaction transaction { *this };
  379. auto success = parse_minute_second()
  380. || m_state.lexer.consume_specific("60"sv);
  381. if (!success)
  382. return false;
  383. m_state.parse_result.time_second = transaction.parsed_string_view();
  384. transaction.commit();
  385. return true;
  386. }
  387. // https://tc39.es/proposal-temporal/#prod-FractionalPart
  388. bool ISO8601Parser::parse_fractional_part()
  389. {
  390. // FractionalPart :
  391. // DecimalDigit DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt]
  392. if (!parse_decimal_digit())
  393. return false;
  394. for (size_t i = 0; i < 8; ++i) {
  395. if (!parse_decimal_digit())
  396. break;
  397. }
  398. return true;
  399. }
  400. // https://tc39.es/proposal-temporal/#prod-Fraction
  401. bool ISO8601Parser::parse_fraction()
  402. {
  403. // Fraction :
  404. // DecimalSeparator FractionalPart
  405. StateTransaction transaction { *this };
  406. if (!parse_decimal_separator())
  407. return false;
  408. if (!parse_fractional_part())
  409. return false;
  410. m_state.parse_result.fractional_part = transaction.parsed_string_view();
  411. transaction.commit();
  412. return true;
  413. }
  414. // https://tc39.es/proposal-temporal/#prod-TimeFraction
  415. bool ISO8601Parser::parse_time_fraction()
  416. {
  417. // TimeFraction :
  418. // Fraction
  419. return parse_fraction();
  420. }
  421. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSign
  422. bool ISO8601Parser::parse_time_zone_utc_offset_sign()
  423. {
  424. // TimeZoneUTCOffsetSign :
  425. // Sign
  426. StateTransaction transaction { *this };
  427. if (!parse_sign())
  428. return false;
  429. m_state.parse_result.time_zone_utc_offset_sign = transaction.parsed_string_view();
  430. transaction.commit();
  431. return true;
  432. }
  433. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetHour
  434. bool ISO8601Parser::parse_time_zone_utc_offset_hour()
  435. {
  436. // TimeZoneUTCOffsetHour :
  437. // Hour
  438. StateTransaction transaction { *this };
  439. if (!parse_hour())
  440. return false;
  441. m_state.parse_result.time_zone_utc_offset_hour = transaction.parsed_string_view();
  442. transaction.commit();
  443. return true;
  444. }
  445. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetMinute
  446. bool ISO8601Parser::parse_time_zone_utc_offset_minute()
  447. {
  448. // TimeZoneUTCOffsetMinute :
  449. // MinuteSecond
  450. StateTransaction transaction { *this };
  451. if (!parse_minute_second())
  452. return false;
  453. m_state.parse_result.time_zone_utc_offset_minute = transaction.parsed_string_view();
  454. transaction.commit();
  455. return true;
  456. }
  457. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSecond
  458. bool ISO8601Parser::parse_time_zone_utc_offset_second()
  459. {
  460. // TimeZoneUTCOffsetSecond :
  461. // MinuteSecond
  462. StateTransaction transaction { *this };
  463. if (!parse_minute_second())
  464. return false;
  465. m_state.parse_result.time_zone_utc_offset_second = transaction.parsed_string_view();
  466. transaction.commit();
  467. return true;
  468. }
  469. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFractionalPart
  470. bool ISO8601Parser::parse_time_zone_utc_offset_fractional_part()
  471. {
  472. // TimeZoneUTCOffsetFractionalPart :
  473. // FractionalPart
  474. StateTransaction transaction { *this };
  475. if (!parse_fractional_part())
  476. return false;
  477. m_state.parse_result.time_zone_utc_offset_fractional_part = transaction.parsed_string_view();
  478. transaction.commit();
  479. return true;
  480. }
  481. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFraction
  482. bool ISO8601Parser::parse_time_zone_utc_offset_fraction()
  483. {
  484. // TimeZoneUTCOffsetFraction :
  485. // DecimalSeparator TimeZoneUTCOffsetFractionalPart
  486. StateTransaction transaction { *this };
  487. if (!parse_decimal_separator())
  488. return false;
  489. if (!parse_time_zone_utc_offset_fractional_part())
  490. return false;
  491. transaction.commit();
  492. return true;
  493. }
  494. // https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffset
  495. bool ISO8601Parser::parse_time_zone_numeric_utc_offset()
  496. {
  497. // TimeZoneNumericUTCOffset :
  498. // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour
  499. // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute
  500. // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute
  501. // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute : TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
  502. // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt]
  503. StateTransaction transaction { *this };
  504. if (!parse_time_zone_utc_offset_sign())
  505. return false;
  506. if (!parse_time_zone_utc_offset_hour())
  507. return false;
  508. if (m_state.lexer.consume_specific(':')) {
  509. if (!parse_time_zone_utc_offset_minute())
  510. return false;
  511. if (m_state.lexer.consume_specific(':')) {
  512. if (!parse_time_zone_utc_offset_second())
  513. return false;
  514. (void)parse_time_zone_utc_offset_fraction();
  515. }
  516. } else if (parse_time_zone_utc_offset_minute()) {
  517. if (parse_time_zone_utc_offset_second())
  518. (void)parse_time_zone_utc_offset_fraction();
  519. }
  520. transaction.commit();
  521. return true;
  522. }
  523. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffset
  524. bool ISO8601Parser::parse_time_zone_utc_offset()
  525. {
  526. // TimeZoneUTCOffset :
  527. // TimeZoneNumericUTCOffset
  528. // UTCDesignator
  529. return parse_time_zone_numeric_utc_offset()
  530. || parse_utc_designator();
  531. }
  532. // https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetName
  533. bool ISO8601Parser::parse_time_zone_utc_offset_name()
  534. {
  535. // TimeZoneUTCOffsetName :
  536. // Sign Hour
  537. // Sign Hour : MinuteSecond
  538. // Sign Hour MinuteSecond
  539. // Sign Hour : MinuteSecond : MinuteSecond Fraction[opt]
  540. // Sign Hour MinuteSecond MinuteSecond Fraction[opt]
  541. StateTransaction transaction { *this };
  542. if (!parse_sign())
  543. return false;
  544. if (!parse_hour())
  545. return false;
  546. if (m_state.lexer.consume_specific(':')) {
  547. if (!parse_minute_second())
  548. return false;
  549. if (m_state.lexer.consume_specific(':')) {
  550. if (!parse_minute_second())
  551. return false;
  552. (void)parse_fraction();
  553. }
  554. } else if (parse_minute_second()) {
  555. if (parse_minute_second())
  556. (void)parse_fraction();
  557. }
  558. transaction.commit();
  559. return true;
  560. }
  561. // https://tc39.es/proposal-temporal/#prod-TimeZoneIANAName
  562. bool ISO8601Parser::parse_time_zone_iana_name()
  563. {
  564. // TZLeadingChar :
  565. // Alpha
  566. // .
  567. // _
  568. // TZChar :
  569. // Alpha
  570. // .
  571. // -
  572. // _
  573. // TimeZoneIANANameComponent :
  574. // 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 ..
  575. // TimeZoneIANANameTail :
  576. // TimeZoneIANANameComponent
  577. // TimeZoneIANANameComponent / TimeZoneIANANameTail
  578. // TimeZoneIANAName :
  579. // TimeZoneIANANameTail
  580. StateTransaction transaction { *this };
  581. // TODO: Implement the full production. Currently, anything other than "UTC" would get rejected as unknown anyway.
  582. auto success = (m_state.lexer.consume_specific('U') || m_state.lexer.consume_specific('u'))
  583. && (m_state.lexer.consume_specific('T') || m_state.lexer.consume_specific('t'))
  584. && (m_state.lexer.consume_specific('C') || m_state.lexer.consume_specific('c'));
  585. if (!success)
  586. return false;
  587. m_state.parse_result.time_zone_iana_name = transaction.parsed_string_view();
  588. transaction.commit();
  589. return true;
  590. }
  591. // https://tc39.es/proposal-temporal/#prod-TimeZoneBracketedName
  592. bool ISO8601Parser::parse_time_zone_bracketed_name()
  593. {
  594. // TimeZoneBracketedName :
  595. // TimeZoneIANAName
  596. // Etc/GMT ASCIISign Hour
  597. // TimeZoneUTCOffsetName
  598. StateTransaction transaction { *this };
  599. if (parse_time_zone_iana_name()) {
  600. // no-op.
  601. } else if (m_state.lexer.consume_specific("Etc/GMT"sv)) {
  602. if (!parse_ascii_sign())
  603. return false;
  604. if (!parse_hour())
  605. return false;
  606. } else if (!parse_time_zone_utc_offset_name()) {
  607. return false;
  608. }
  609. transaction.commit();
  610. return true;
  611. }
  612. // https://tc39.es/proposal-temporal/#prod-TimeZoneBracketedAnnotation
  613. bool ISO8601Parser::parse_time_zone_bracketed_annotation()
  614. {
  615. // TimeZoneBracketedAnnotation :
  616. // [ TimeZoneBracketedName ]
  617. StateTransaction transaction { *this };
  618. if (!m_state.lexer.consume_specific('['))
  619. return false;
  620. if (!parse_time_zone_bracketed_name())
  621. return false;
  622. if (!m_state.lexer.consume_specific(']'))
  623. return false;
  624. transaction.commit();
  625. return true;
  626. }
  627. // https://tc39.es/proposal-temporal/#prod-TimeZoneOffsetRequired
  628. bool ISO8601Parser::parse_time_zone_offset_required()
  629. {
  630. // TimeZoneOffsetRequired :
  631. // TimeZoneUTCOffset TimeZoneBracketedAnnotation[opt]
  632. StateTransaction transaction { *this };
  633. if (!parse_time_zone_utc_offset())
  634. return false;
  635. (void)parse_time_zone_bracketed_annotation();
  636. transaction.commit();
  637. return true;
  638. }
  639. // https://tc39.es/proposal-temporal/#prod-TimeZoneNameRequired
  640. bool ISO8601Parser::parse_time_zone_name_required()
  641. {
  642. // TimeZoneNameRequired :
  643. // TimeZoneUTCOffset[opt] TimeZoneBracketedAnnotation
  644. StateTransaction transaction { *this };
  645. (void)parse_time_zone_utc_offset();
  646. if (!parse_time_zone_bracketed_annotation())
  647. return false;
  648. transaction.commit();
  649. return true;
  650. }
  651. // https://tc39.es/proposal-temporal/#prod-TimeZone
  652. bool ISO8601Parser::parse_time_zone()
  653. {
  654. // TimeZone :
  655. // TimeZoneOffsetRequired
  656. // TimeZoneNameRequired
  657. return parse_time_zone_offset_required()
  658. || parse_time_zone_name_required();
  659. }
  660. // https://tc39.es/proposal-temporal/#prod-CalendarName
  661. bool ISO8601Parser::parse_calendar_name()
  662. {
  663. // CalChar :
  664. // Alpha
  665. // DecimalDigit
  666. // CalendarNameComponent :
  667. // CalChar CalChar CalChar CalChar[opt] CalChar[opt] CalChar[opt] CalChar[opt] CalChar[opt]
  668. // CalendarNameTail :
  669. // CalendarNameComponent
  670. // CalendarNameComponent - CalendarNameTail
  671. // CalendarName :
  672. // CalendarNameTail
  673. auto parse_calendar_name_component = [&] {
  674. for (size_t i = 0; i < 8; ++i) {
  675. if (!m_state.lexer.next_is(is_ascii_alphanumeric))
  676. return i > 2;
  677. m_state.lexer.consume();
  678. }
  679. return true;
  680. };
  681. StateTransaction transaction { *this };
  682. do {
  683. if (!parse_calendar_name_component())
  684. return false;
  685. } while (m_state.lexer.consume_specific('-'));
  686. m_state.parse_result.calendar_name = transaction.parsed_string_view();
  687. transaction.commit();
  688. return true;
  689. }
  690. // https://tc39.es/proposal-temporal/#prod-Calendar
  691. bool ISO8601Parser::parse_calendar()
  692. {
  693. // Calendar :
  694. // [u-ca= CalendarName ]
  695. StateTransaction transaction { *this };
  696. if (!m_state.lexer.consume_specific("[u-ca="sv))
  697. return false;
  698. if (!parse_calendar_name())
  699. return false;
  700. if (!m_state.lexer.consume_specific(']'))
  701. return false;
  702. transaction.commit();
  703. return true;
  704. }
  705. // https://tc39.es/proposal-temporal/#prod-TimeSpec
  706. bool ISO8601Parser::parse_time_spec()
  707. {
  708. // TimeSpec :
  709. // TimeHour
  710. // TimeHour : TimeMinute
  711. // TimeHour TimeMinute
  712. // TimeHour : TimeMinute : TimeSecond TimeFraction[opt]
  713. // TimeHour TimeMinute TimeSecond TimeFraction[opt]
  714. StateTransaction transaction { *this };
  715. if (!parse_time_hour())
  716. return false;
  717. if (m_state.lexer.consume_specific(':')) {
  718. if (!parse_time_minute())
  719. return false;
  720. if (m_state.lexer.consume_specific(':')) {
  721. if (!parse_time_second())
  722. return false;
  723. (void)parse_time_fraction();
  724. }
  725. } else if (parse_time_minute()) {
  726. if (parse_time_second())
  727. (void)parse_time_fraction();
  728. }
  729. transaction.commit();
  730. return true;
  731. }
  732. // https://tc39.es/proposal-temporal/#prod-Time
  733. bool ISO8601Parser::parse_time()
  734. {
  735. // Time :
  736. // TimeSpec TimeZone[opt]
  737. if (!parse_time_spec())
  738. return false;
  739. (void)parse_time_zone();
  740. return true;
  741. }
  742. // https://tc39.es/proposal-temporal/#prod-TimeSpecSeparator
  743. bool ISO8601Parser::parse_time_spec_separator()
  744. {
  745. // TimeSpecSeparator :
  746. // DateTimeSeparator TimeSpec
  747. StateTransaction transaction { *this };
  748. if (!parse_date_time_separator())
  749. return false;
  750. if (!parse_time_spec())
  751. return false;
  752. transaction.commit();
  753. return true;
  754. }
  755. // https://tc39.es/proposal-temporal/#prod-DateTime
  756. bool ISO8601Parser::parse_date_time()
  757. {
  758. // DateTime :
  759. // Date TimeSpecSeparator[opt] TimeZone[opt]
  760. if (!parse_date())
  761. return false;
  762. (void)parse_time_spec_separator();
  763. (void)parse_time_zone();
  764. return true;
  765. }
  766. // https://tc39.es/proposal-temporal/#prod-CalendarDateTime
  767. bool ISO8601Parser::parse_calendar_date_time()
  768. {
  769. // CalendarDateTime :
  770. // DateTime Calendar[opt]
  771. if (!parse_date_time())
  772. return false;
  773. (void)parse_calendar();
  774. return true;
  775. }
  776. // https://tc39.es/proposal-temporal/#prod-DurationWholeSeconds
  777. bool ISO8601Parser::parse_duration_whole_seconds()
  778. {
  779. // DurationWholeSeconds :
  780. // DecimalDigits[~Sep]
  781. StateTransaction transaction { *this };
  782. if (!parse_decimal_digits())
  783. return false;
  784. m_state.parse_result.duration_whole_seconds = transaction.parsed_string_view();
  785. transaction.commit();
  786. return true;
  787. }
  788. // https://tc39.es/proposal-temporal/#prod-DurationSecondsFraction
  789. bool ISO8601Parser::parse_duration_seconds_fraction()
  790. {
  791. // DurationSecondsFraction :
  792. // TimeFraction
  793. StateTransaction transaction { *this };
  794. if (!parse_time_fraction())
  795. return false;
  796. m_state.parse_result.duration_seconds_fraction = transaction.parsed_string_view();
  797. transaction.commit();
  798. return true;
  799. }
  800. // https://tc39.es/proposal-temporal/#prod-DurationSecondsPart
  801. bool ISO8601Parser::parse_duration_seconds_part()
  802. {
  803. // DurationSecondsPart :
  804. // DurationWholeSeconds DurationSecondsFraction[opt] SecondsDesignator
  805. StateTransaction transaction { *this };
  806. if (!parse_duration_whole_seconds())
  807. return false;
  808. (void)parse_duration_seconds_fraction();
  809. if (!parse_seconds_designator())
  810. return false;
  811. transaction.commit();
  812. return true;
  813. }
  814. // https://tc39.es/proposal-temporal/#prod-DurationWholeMinutes
  815. bool ISO8601Parser::parse_duration_whole_minutes()
  816. {
  817. // DurationWholeMinutes :
  818. // DecimalDigits[~Sep]
  819. StateTransaction transaction { *this };
  820. if (!parse_decimal_digits())
  821. return false;
  822. m_state.parse_result.duration_whole_minutes = transaction.parsed_string_view();
  823. transaction.commit();
  824. return true;
  825. }
  826. // https://tc39.es/proposal-temporal/#prod-DurationMinutesFraction
  827. bool ISO8601Parser::parse_duration_minutes_fraction()
  828. {
  829. // DurationMinutesFraction :
  830. // TimeFraction
  831. StateTransaction transaction { *this };
  832. if (!parse_time_fraction())
  833. return false;
  834. m_state.parse_result.duration_minutes_fraction = transaction.parsed_string_view();
  835. transaction.commit();
  836. return true;
  837. }
  838. // https://tc39.es/proposal-temporal/#prod-DurationMinutesPart
  839. bool ISO8601Parser::parse_duration_minutes_part()
  840. {
  841. // DurationMinutesPart :
  842. // DurationWholeMinutes DurationMinutesFraction[opt] MinutesDesignator DurationSecondsPart[opt]
  843. StateTransaction transaction { *this };
  844. if (!parse_duration_whole_minutes())
  845. return false;
  846. (void)parse_duration_minutes_fraction();
  847. if (!parse_minutes_designator())
  848. return false;
  849. (void)parse_duration_seconds_part();
  850. transaction.commit();
  851. return true;
  852. }
  853. // https://tc39.es/proposal-temporal/#prod-DurationWholeHours
  854. bool ISO8601Parser::parse_duration_whole_hours()
  855. {
  856. // DurationWholeHours :
  857. // DecimalDigits[~Sep]
  858. StateTransaction transaction { *this };
  859. if (!parse_decimal_digits())
  860. return false;
  861. m_state.parse_result.duration_whole_hours = transaction.parsed_string_view();
  862. transaction.commit();
  863. return true;
  864. }
  865. // https://tc39.es/proposal-temporal/#prod-DurationHoursFraction
  866. bool ISO8601Parser::parse_duration_hours_fraction()
  867. {
  868. // DurationHoursFraction :
  869. // TimeFraction
  870. StateTransaction transaction { *this };
  871. if (!parse_time_fraction())
  872. return false;
  873. m_state.parse_result.duration_hours_fraction = transaction.parsed_string_view();
  874. transaction.commit();
  875. return true;
  876. }
  877. // https://tc39.es/proposal-temporal/#prod-DurationHoursPart
  878. bool ISO8601Parser::parse_duration_hours_part()
  879. {
  880. // DurationHoursPart :
  881. // DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationMinutesPart
  882. // DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationSecondsPart[opt]
  883. StateTransaction transaction { *this };
  884. if (!parse_duration_whole_hours())
  885. return false;
  886. (void)parse_duration_hours_fraction();
  887. if (!parse_hours_designator())
  888. return false;
  889. (void)(parse_duration_minutes_part()
  890. || parse_duration_seconds_part());
  891. transaction.commit();
  892. return true;
  893. }
  894. // https://tc39.es/proposal-temporal/#prod-DurationTime
  895. bool ISO8601Parser::parse_duration_time()
  896. {
  897. // DurationTime :
  898. // DurationTimeDesignator DurationHoursPart
  899. // DurationTimeDesignator DurationMinutesPart
  900. // DurationTimeDesignator DurationSecondsPart
  901. StateTransaction transaction { *this };
  902. if (!parse_duration_time_designator())
  903. return false;
  904. auto success = parse_duration_hours_part()
  905. || parse_duration_minutes_part()
  906. || parse_duration_seconds_part();
  907. if (!success)
  908. return false;
  909. transaction.commit();
  910. return true;
  911. }
  912. // https://tc39.es/proposal-temporal/#prod-DurationDays
  913. bool ISO8601Parser::parse_duration_days()
  914. {
  915. // DurationDays :
  916. // DecimalDigits[~Sep]
  917. StateTransaction transaction { *this };
  918. if (!parse_decimal_digits())
  919. return false;
  920. m_state.parse_result.duration_days = transaction.parsed_string_view();
  921. transaction.commit();
  922. return true;
  923. }
  924. // https://tc39.es/proposal-temporal/#prod-DurationDaysPart
  925. bool ISO8601Parser::parse_duration_days_part()
  926. {
  927. // DurationDaysPart :
  928. // DurationDays DaysDesignator
  929. StateTransaction transaction { *this };
  930. if (!parse_duration_days())
  931. return false;
  932. if (!parse_days_designator())
  933. return false;
  934. transaction.commit();
  935. return true;
  936. }
  937. // https://tc39.es/proposal-temporal/#prod-DurationWeeks
  938. bool ISO8601Parser::parse_duration_weeks()
  939. {
  940. // DurationWeeks :
  941. // DecimalDigits[~Sep]
  942. StateTransaction transaction { *this };
  943. if (!parse_decimal_digits())
  944. return false;
  945. m_state.parse_result.duration_weeks = transaction.parsed_string_view();
  946. transaction.commit();
  947. return true;
  948. }
  949. // https://tc39.es/proposal-temporal/#prod-DurationWeeksPart
  950. bool ISO8601Parser::parse_duration_weeks_part()
  951. {
  952. // DurationWeeksPart :
  953. // DurationWeeks WeeksDesignator DurationDaysPart[opt]
  954. StateTransaction transaction { *this };
  955. if (!parse_duration_weeks())
  956. return false;
  957. if (!parse_weeks_designator())
  958. return false;
  959. (void)parse_duration_days_part();
  960. transaction.commit();
  961. return true;
  962. }
  963. // https://tc39.es/proposal-temporal/#prod-DurationMonths
  964. bool ISO8601Parser::parse_duration_months()
  965. {
  966. // DurationMonths :
  967. // DecimalDigits[~Sep]
  968. StateTransaction transaction { *this };
  969. if (!parse_decimal_digits())
  970. return false;
  971. m_state.parse_result.duration_months = transaction.parsed_string_view();
  972. transaction.commit();
  973. return true;
  974. }
  975. // https://tc39.es/proposal-temporal/#prod-DurationMonthsPart
  976. bool ISO8601Parser::parse_duration_months_part()
  977. {
  978. // DurationMonthsPart :
  979. // DurationMonths MonthsDesignator DurationWeeksPart
  980. // DurationMonths MonthsDesignator DurationDaysPart[opt]
  981. StateTransaction transaction { *this };
  982. if (!parse_duration_months())
  983. return false;
  984. if (!parse_months_designator())
  985. return false;
  986. (void)(parse_duration_weeks_part()
  987. || parse_duration_days_part());
  988. transaction.commit();
  989. return true;
  990. }
  991. // https://tc39.es/proposal-temporal/#prod-DurationYears
  992. bool ISO8601Parser::parse_duration_years()
  993. {
  994. // DurationYears :
  995. // DecimalDigits[~Sep]
  996. StateTransaction transaction { *this };
  997. if (!parse_decimal_digits())
  998. return false;
  999. m_state.parse_result.duration_years = transaction.parsed_string_view();
  1000. transaction.commit();
  1001. return true;
  1002. }
  1003. // https://tc39.es/proposal-temporal/#prod-DurationYearsPart
  1004. bool ISO8601Parser::parse_duration_years_part()
  1005. {
  1006. // DurationYearsPart :
  1007. // DurationYears YearsDesignator DurationMonthsPart
  1008. // DurationYears YearsDesignator DurationWeeksPart
  1009. // DurationYears YearsDesignator DurationDaysPart[opt]
  1010. StateTransaction transaction { *this };
  1011. if (!parse_duration_years())
  1012. return false;
  1013. if (!parse_years_designator())
  1014. return false;
  1015. (void)(parse_duration_months_part()
  1016. || parse_duration_weeks_part()
  1017. || parse_duration_days_part());
  1018. transaction.commit();
  1019. return true;
  1020. }
  1021. // https://tc39.es/proposal-temporal/#prod-DurationDate
  1022. bool ISO8601Parser::parse_duration_date()
  1023. {
  1024. // DurationDate :
  1025. // DurationYearsPart DurationTime[opt]
  1026. // DurationMonthsPart DurationTime[opt]
  1027. // DurationWeeksPart DurationTime[opt]
  1028. // DurationDaysPart DurationTime[opt]
  1029. auto success = parse_duration_years_part()
  1030. || parse_duration_months_part()
  1031. || parse_duration_weeks_part()
  1032. || parse_duration_days_part();
  1033. if (!success)
  1034. return false;
  1035. (void)parse_duration_time();
  1036. return true;
  1037. }
  1038. // https://tc39.es/proposal-temporal/#prod-Duration
  1039. bool ISO8601Parser::parse_duration()
  1040. {
  1041. // Duration :
  1042. // Sign[opt] DurationDesignator DurationDate
  1043. // Sign[opt] DurationDesignator DurationTime
  1044. StateTransaction transaction { *this };
  1045. (void)parse_sign();
  1046. if (!parse_duration_designator())
  1047. return false;
  1048. auto success = parse_duration_date()
  1049. || parse_duration_time();
  1050. if (!success)
  1051. return false;
  1052. transaction.commit();
  1053. return true;
  1054. }
  1055. // https://tc39.es/proposal-temporal/#prod-TemporalInstantString
  1056. bool ISO8601Parser::parse_temporal_instant_string()
  1057. {
  1058. // TemporalInstantString :
  1059. // Date TimeSpecSeparator[opt] TimeZoneOffsetRequired
  1060. StateTransaction transaction { *this };
  1061. if (!parse_date())
  1062. return false;
  1063. (void)parse_time_spec_separator();
  1064. if (!parse_time_zone_offset_required())
  1065. return false;
  1066. transaction.commit();
  1067. return true;
  1068. }
  1069. // https://tc39.es/proposal-temporal/#prod-TemporalDateString
  1070. bool ISO8601Parser::parse_temporal_date_string()
  1071. {
  1072. // TemporalDateString :
  1073. // CalendarDateTime
  1074. return parse_calendar_date_time();
  1075. }
  1076. // https://tc39.es/proposal-temporal/#prod-TemporalDateTimeString
  1077. bool ISO8601Parser::parse_temporal_date_time_string()
  1078. {
  1079. // TemporalDateTimeString :
  1080. // CalendarDateTime
  1081. return parse_calendar_date_time();
  1082. }
  1083. // https://tc39.es/proposal-temporal/#prod-TemporalDurationString
  1084. bool ISO8601Parser::parse_temporal_duration_string()
  1085. {
  1086. // TemporalDurationString :
  1087. // Duration
  1088. return parse_duration();
  1089. }
  1090. // https://tc39.es/proposal-temporal/#prod-TemporalMonthDayString
  1091. bool ISO8601Parser::parse_temporal_month_day_string()
  1092. {
  1093. // TemporalMonthDayString :
  1094. // DateSpecMonthDay
  1095. // DateTime
  1096. // NOTE: Reverse order here because `DateSpecMonthDay` can be a subset of `DateTime`,
  1097. // so we'd not attempt to parse that but may not exhaust the input string.
  1098. return parse_date_time()
  1099. || parse_date_spec_month_day();
  1100. }
  1101. // https://tc39.es/proposal-temporal/#prod-TemporalTimeString
  1102. bool ISO8601Parser::parse_temporal_time_string()
  1103. {
  1104. // TemporalTimeString :
  1105. // Time
  1106. // DateTime
  1107. // NOTE: Reverse order here because `Time` can be a subset of `DateTime`,
  1108. // so we'd not attempt to parse that but may not exhaust the input string.
  1109. return parse_date_time()
  1110. || parse_time();
  1111. }
  1112. // https://tc39.es/proposal-temporal/#prod-TemporalTimeZoneIdentifier
  1113. bool ISO8601Parser::parse_temporal_time_zone_identifier()
  1114. {
  1115. // TemporalTimeZoneIdentifier :
  1116. // TimeZoneNumericUTCOffset
  1117. // TimeZoneIANAName
  1118. return parse_time_zone_numeric_utc_offset()
  1119. || parse_time_zone_iana_name();
  1120. }
  1121. // https://tc39.es/proposal-temporal/#prod-TemporalTimeZoneString
  1122. bool ISO8601Parser::parse_temporal_time_zone_string()
  1123. {
  1124. // TemporalTimeZoneString :
  1125. // TemporalTimeZoneIdentifier
  1126. // Date TimeSpecSeparator[opt] TimeZone Calendar[opt]
  1127. StateTransaction transaction { *this };
  1128. if (!parse_temporal_time_zone_identifier()) {
  1129. if (!parse_date())
  1130. return false;
  1131. (void)parse_time_spec_separator();
  1132. if (!parse_time_zone())
  1133. return false;
  1134. (void)parse_calendar();
  1135. }
  1136. transaction.commit();
  1137. return true;
  1138. }
  1139. // https://tc39.es/proposal-temporal/#prod-TemporalYearMonthString
  1140. bool ISO8601Parser::parse_temporal_year_month_string()
  1141. {
  1142. // TemporalYearMonthString :
  1143. // DateSpecYearMonth
  1144. // DateTime
  1145. // NOTE: Reverse order here because `DateSpecYearMonth` can be a subset of `DateTime`,
  1146. // so we'd not attempt to parse that but may not exhaust the input string.
  1147. return parse_date_time()
  1148. || parse_date_spec_year_month();
  1149. }
  1150. // https://tc39.es/proposal-temporal/#prod-TemporalZonedDateTimeString
  1151. bool ISO8601Parser::parse_temporal_zoned_date_time_string()
  1152. {
  1153. // TemporalZonedDateTimeString :
  1154. // Date TimeSpecSeparator[opt] TimeZoneNameRequired Calendar[opt]
  1155. StateTransaction transaction { *this };
  1156. if (!parse_date())
  1157. return false;
  1158. (void)parse_time_spec_separator();
  1159. if (!parse_time_zone_name_required())
  1160. return false;
  1161. (void)parse_calendar();
  1162. transaction.commit();
  1163. return true;
  1164. }
  1165. // https://tc39.es/proposal-temporal/#prod-TemporalCalendarString
  1166. bool ISO8601Parser::parse_temporal_calendar_string()
  1167. {
  1168. // TemporalCalendarString :
  1169. // CalendarName
  1170. // TemporalInstantString
  1171. // CalendarDateTime
  1172. // Time
  1173. // DateSpecYearMonth
  1174. // DateSpecMonthDay
  1175. return parse_calendar_name()
  1176. || parse_temporal_instant_string()
  1177. || parse_calendar_date_time()
  1178. || parse_date_spec_year_month()
  1179. || parse_date_spec_month_day()
  1180. || parse_time();
  1181. }
  1182. // https://tc39.es/proposal-temporal/#prod-TemporalRelativeToString
  1183. bool ISO8601Parser::parse_temporal_relative_to_string()
  1184. {
  1185. // TemporalRelativeToString :
  1186. // TemporalDateTimeString
  1187. return parse_temporal_date_time_string();
  1188. }
  1189. }
  1190. #define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \
  1191. __JS_ENUMERATE(TemporalInstantString, parse_temporal_instant_string) \
  1192. __JS_ENUMERATE(TemporalDateString, parse_temporal_date_string) \
  1193. __JS_ENUMERATE(TemporalDateTimeString, parse_temporal_date_time_string) \
  1194. __JS_ENUMERATE(TemporalDurationString, parse_temporal_duration_string) \
  1195. __JS_ENUMERATE(TemporalMonthDayString, parse_temporal_month_day_string) \
  1196. __JS_ENUMERATE(TemporalTimeString, parse_temporal_time_string) \
  1197. __JS_ENUMERATE(TemporalTimeZoneString, parse_temporal_time_zone_string) \
  1198. __JS_ENUMERATE(TemporalYearMonthString, parse_temporal_year_month_string) \
  1199. __JS_ENUMERATE(TemporalZonedDateTimeString, parse_temporal_zoned_date_time_string) \
  1200. __JS_ENUMERATE(TemporalCalendarString, parse_temporal_calendar_string) \
  1201. __JS_ENUMERATE(TemporalRelativeToString, parse_temporal_relative_to_string)
  1202. Optional<ParseResult> parse_iso8601(Production production, StringView input)
  1203. {
  1204. auto parser = Detail::ISO8601Parser { input };
  1205. switch (production) {
  1206. #define __JS_ENUMERATE(ProductionName, parse_production) \
  1207. case Production::ProductionName: \
  1208. if (!parser.parse_production()) \
  1209. return {}; \
  1210. break;
  1211. JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS
  1212. #undef __JS_ENUMERATE
  1213. default:
  1214. VERIFY_NOT_REACHED();
  1215. }
  1216. // If we parsed successfully but didn't reach the end, the string doesn't match the given production.
  1217. if (!parser.lexer().is_eof())
  1218. return {};
  1219. return parser.parse_result();
  1220. }
  1221. }