1 // ♓️🪡 सूत्र ∷ xsd/productions.js
2 // ====================================================================
4 // Copyright © 2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
18 const dayOfMonthValuesConstraint
= (day
, month
, year
= "1972") => {
22 return m
=== 4 || m
=== 6 || m
=== 9 || m
=== 11
24 : m
=== 2 && (y
% 4 || !(y
% 100) && y
% 400)
26 : m
=== 2 && (!(y
% 400) || !(y
% 4) && y
% 100)
32 /** `[1] stringRep ::= Char*` */
35 /** `[2] booleanRep ::= 'true' | 'false' | '1' | '0'` */
38 /** `[3] decimalLexicalRep ::= decimalPtNumeral | noDecimalPtNumeral` */
41 /** `[4] floatRep ::= noDecimalPtNumeral | decimalPtNumeral | scientificNotationNumeral | numericalSpecialRep` */
44 /** `[5] doubleRep ::= noDecimalPtNumeral | decimalPtNumeral | scientificNotationNumeral | numericalSpecialRep` */
47 /** `[6] duYearFrag ::= unsignedNoDecimalPtNumeral 'Y'` */
50 /** `[7] duMonthFrag ::= unsignedNoDecimalPtNumeral 'M'` */
53 /** `[8] duDayFrag ::= unsignedNoDecimalPtNumeral 'D'` */
56 /** `[9] duHourFrag ::= unsignedNoDecimalPtNumeral 'H'` */
59 /** `[10] duMinuteFrag ::= unsignedNoDecimalPtNumeral 'M'` */
63 * `[11] duSecondFrag ::= (unsignedNoDecimalPtNumeral | unsignedFullDecimalPtNumeral) 'S'`
65 * ※ The X·S·D specification specifies unsignedDecimalPtNumeral, not
66 * unsignedFullDecimalPtNumeral, but the specification text and
67 * provided regular expressions imply that the latter was intended.
71 /** `[12] duYearMonthFrag ::= (duYearFrag duMonthFrag?) | duMonthFrag` */
74 /** `[13] duTimeFrag ::= 'T' ((duHourFrag duMinuteFrag? duSecondFrag?) | (duMinuteFrag duSecondFrag?) | duSecondFrag)` */
77 /** `[14] duDayTimeFrag ::= (duDayFrag duTimeFrag?) | duTimeFrag` */
80 /** `[15] durationLexicalRep ::= '-'? 'P' ((duYearMonthFrag duDayTimeFrag?) | duDayTimeFrag)` */
84 * `[16] dateTimeLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?`
86 * **Constraint: Day-of-month Values**
88 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
89 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
90 * divisible by 4, or is divisible by 100 but not by 400; and no more
91 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
94 * **Constraint: Day-of-month Representations**
96 * Within a dateTimeLexicalRep, a dayFrag must not begin with the
97 * digit '3' or be '29' unless the value to which it would map would
98 * satisfy the value constraint on ·day· values ("Constraint:
99 * Day-of-month Values") given above.
103 /** `[17] timeLexicalRep ::= ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?` */
107 * `[18] dateLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag timezoneFrag?`
109 * **Constraint: Day-of-month Values**
111 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
112 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
113 * divisible by 4, or is divisible by 100 but not by 400; and no more
114 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
117 * **Constraint: Day-of-month Representations**
119 * Within a dateLexicalRep, a dayFrag must not begin with the digit
120 * '3' or be '29' unless the value to which it would map would
121 * satisfy the value constraint on ·day· values ("Constraint:
122 * Day-of-month Values") given above.
126 /** `[19] gYearMonthLexicalRep ::= yearFrag '-' monthFrag timezoneFrag?` */
127 gYearMonthLexicalRep
,
129 /** `[20] gYearLexicalRep ::= yearFrag timezoneFrag?` */
133 * `[21] gMonthDayLexicalRep ::= '--' monthFrag '-' dayFrag timezoneFrag?`
135 * **Constraint: Day-of-month Values**
137 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
138 * 9, or 11, and no more than 29 if ·month· is 2.
140 * **Constraint: Day-of-month Representations**
142 * Within a gMonthDayLexicalRep, a dayFrag must not begin with the
143 * digit '3' or be '29' unless the value to which it would map would
144 * satisfy the value constraint on ·day· values ("Constraint:
145 * Day-of-month Values") given above.
149 /** `[22] gDayLexicalRep ::= '---' dayFrag timezoneFrag?` */
152 /** `[23] gMonthLexicalRep ::= '--' monthFrag timezoneFrag?` */
155 /** `[24] hexDigit ::= [0-9a-fA-F]` */
158 /** `[25] hexOctet ::= hexDigit hexDigit` */
161 /** `[26] hexBinary ::= hexOctet*` */
164 /** `[27] Base64Binary ::= (B64quad* B64final)?` */
167 /** `[28] B64quad ::= (B64 B64 B64 B64)` */
170 /** `[29] B64final ::= B64finalquad | Padded16 | Padded8` */
173 /** `[30] B64finalquad ::= (B64 B64 B64 B64char)` */
176 /** `[31] Padded16 ::= B64 B64 B16 '='` */
179 /** `[32] Padded8 ::= B64 B04 '=' #x20? '='` */
182 /** `[33] B64 ::= B64char #x20?` */
185 /** `[34] B64char ::= [A-Za-z0-9+/]` */
188 /** `[35] B16 ::= B16char #x20?` */
191 /** `[36] B16char ::= [AEIMQUYcgkosw048]` */
194 /** `[37] B04 ::= B04char #x20?` */
197 /** `[38] B04char ::= [AQgw]` */
200 /** `[39] Canonical-base64Binary ::= CanonicalQuad* CanonicalPadded?` */
201 Canonical
·base64Binary
,
203 /** `[40] CanonicalQuad ::= B64char B64char B64char B64char` */
206 /** `[41] CanonicalPadded ::= B64char B64char B16char '=' | B64char B04char '=='` */
209 /** `[42] yearMonthDurationLexicalRep ::= '-'? 'P' duYearMonthFrag` */
210 yearMonthDurationLexicalRep
,
212 /** `[43] dayTimeDurationLexicalRep ::= '-'? 'P' duDayTimeFrag` */
213 dayTimeDurationLexicalRep
,
216 * `[44] dateTimeStampLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag`
218 * **Constraint: Day-of-month Values**
220 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
221 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
222 * divisible by 4, or is divisible by 100 but not by 400; and no more
223 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
226 * **Constraint: Day-of-month Representations**
228 * Within a dateTimeStampLexicalRep, a dayFrag must not begin with
229 * the digit '3' or be '29' unless the value to which it would map
230 * would satisfy the value constraint on ·day· values ("Constraint:
231 * Day-of-month Values") given above.
233 dateTimeStampLexicalRep
,
235 /** `[45] digit ::= [0-9]` */
238 /** `[46] unsignedNoDecimalPtNumeral ::= digit+` */
239 unsignedNoDecimalPtNumeral
,
241 /** `[47] noDecimalPtNumeral ::= ('+' | '-')? unsignedNoDecimalPtNumeral` */
244 /** `[48] fracFrag ::= digit+` */
247 /** `[49] unsignedDecimalPtNumeral ::= (unsignedNoDecimalPtNumeral '.' fracFrag?) | ('.' fracFrag)` */
248 unsignedDecimalPtNumeral
,
250 /** `[50] unsignedFullDecimalPtNumeral ::= unsignedNoDecimalPtNumeral '.' fracFrag` */
251 unsignedFullDecimalPtNumeral
,
253 /** `[51] decimalPtNumeral ::= ('+' | '-')? unsignedDecimalPtNumeral` */
256 /** `[52] unsignedScientificNotationNumeral ::= (unsignedNoDecimalPtNumeral | unsignedDecimalPtNumeral) ('e' | 'E') noDecimalPtNumeral` */
257 unsignedScientificNotationNumeral
,
259 /** `[53] scientificNotationNumeral ::= ('+' | '-')? unsignedScientificNotationNumeral` */
260 scientificNotationNumeral
,
262 /** `[54] minimalNumericalSpecialRep ::= 'INF' | '-INF' | 'NaN'` */
263 minimalNumericalSpecialRep
,
265 /** `[55] numericalSpecialRep ::= ('+' | '-')? unsignedScientificNotationNumeral` */
268 /** `[56] yearFrag ::= '-'? (([1-9] digit digit digit+)) | ('0' digit digit digit))` */
271 /** `[57] monthFrag ::= ('0' [1-9]) | ('1' [0-2])` */
274 /** `[58] dayFrag ::= ('0' [1-9]) | ([12] digit) | ('3' [01])` */
277 /** `[59] hourFrag ::= ([01] digit) | ('2' [0-3])` */
280 /** `[60] minuteFrag ::= [0-5] digit` */
283 /** `[61] secondFrag ::= ([0-5] digit) ('.' digit+)?` */
286 /** `[62] endOfDayFrag ::= '24:00:00' ('.' '0'+)?` */
289 /** `[63] timezoneFrag ::= 'Z' | ('+' | '-') (('0' digit | '1' [0-3]) ':' minuteFrag | '14:00')` */
292 const matchers
= objectCreate(null);
294 (name
, constraint
= null) => (strings
, ...substitutions
) => {
295 const source
= `(?:${rawString(strings, ...substitutions)})`;
296 matchers
[name
] = new Matcher(`^${source}$`, name
, constraint
);
300 const stringRep
= match(
302 )`[^\u{0}\u{D800}-\u{DFFF}\u{FFFE}\u{FFFF}]*`;
303 const booleanRep
= match("booleanRep")`true|false|1|0`;
304 const digit
= match("digit")`[0-9]`;
305 const unsignedNoDecimalPtNumeral
= match(
306 "unsignedNoDecimalPtNumeral",
308 const noDecimalPtNumeral
= match(
309 "noDecimalPtNumeral",
310 )`[+-]?${unsignedNoDecimalPtNumeral}`;
311 const fracFrag
= match("fracFrag")`${digit}+`;
312 const unsignedDecimalPtNumeral
= match(
313 "unsignedDecimalPtNumeral",
314 )`${unsignedNoDecimalPtNumeral}\.${fracFrag}?|\.${fracFrag}`;
315 const unsignedFullDecimalPtNumeral
= match(
316 "unsignedFullDecimalPtNumeral",
317 )`${unsignedNoDecimalPtNumeral}\.${fracFrag}`;
318 const decimalPtNumeral
= match(
320 )`[+-]?${unsignedDecimalPtNumeral}`;
321 const unsignedScientificNotationNumeral
= match(
322 "unsignedScientificNotationNumeral",
323 )`(?:${unsignedNoDecimalPtNumeral}|${unsignedDecimalPtNumeral})[eE]${noDecimalPtNumeral}`;
324 const scientificNotationNumeral
= match(
325 "scientificNotationNumeral",
326 )`[+-]?${unsignedScientificNotationNumeral}`;
327 const minimalNumericalSpecialRep
= match(
328 "minimalNumericalSpecialRep",
330 const numericalSpecialRep
= match(
331 "numericalSpecialRep",
332 )`\+INF|${minimalNumericalSpecialRep}`;
333 const decimalLexicalRep
= match(
335 )`${decimalPtNumeral}|${noDecimalPtNumeral}`;
336 const floatRep
= match(
338 )`${noDecimalPtNumeral}|${decimalPtNumeral}|${scientificNotationNumeral}|${numericalSpecialRep}`;
339 const doubleRep
= match(
341 )`${noDecimalPtNumeral}|${decimalPtNumeral}|${scientificNotationNumeral}|${numericalSpecialRep}`;
342 const duYearFrag
= match(
344 )`${unsignedNoDecimalPtNumeral}Y`;
345 const duMonthFrag
= match(
347 )`${unsignedNoDecimalPtNumeral}M`;
348 const duDayFrag
= match("duDayFrag")`${unsignedNoDecimalPtNumeral}D`;
349 const duHourFrag
= match(
351 )`${unsignedNoDecimalPtNumeral}H`;
352 const duMinuteFrag
= match(
354 )`${unsignedNoDecimalPtNumeral}M`;
355 const duSecondFrag
= match(
357 )`(?:${unsignedNoDecimalPtNumeral}|${unsignedFullDecimalPtNumeral})S`;
358 const duYearMonthFrag
= match(
360 )`${duYearFrag}${duMonthFrag}?|${duMonthFrag}`;
361 const duTimeFrag
= match(
363 )`T(?:${duHourFrag}${duMinuteFrag}?${duSecondFrag}?|${duMinuteFrag}${duSecondFrag}?|${duSecondFrag})`;
364 const duDayTimeFrag
= match(
366 )`${duDayFrag}${duTimeFrag}?|${duTimeFrag}`;
367 const durationLexicalRep
= match(
368 "durationLexicalRep",
369 )`-?P(?:${duYearMonthFrag}${duDayTimeFrag}?|${duDayTimeFrag})`;
370 const yearFrag
= match(
372 )`-?(?:[1-9]${digit}{3,}|0${digit}{3})`;
373 const monthFrag
= match("monthFrag")`0[1-9]|1[0-2]`;
374 const dayFrag
= match("dayFrag")`0[1-9]|[12]${digit}|3[01]`;
375 const hourFrag
= match("hourFrag")`[01]${digit}|2[0-3]`;
376 const minuteFrag
= match("minuteFrag")`[0-5]${digit}`;
377 const secondFrag
= match(
379 )`[0-5]${digit}(?:\.${digit}+)?`;
380 const endOfDayFrag
= match("endOfDayFrag")`24:00:00(?:\.0+)?`;
381 const timezoneFrag
= match(
383 )`Z|[+-](?:(?:0${digit}|1[0-3]):${minuteFrag}|14:00)`;
384 const dateTimeLexicalRep
= match("dateTimeLexicalRep", ($) => {
385 const components
= stringSplit($, "-");
386 return components
[0] === ""
387 ? dayOfMonthValuesConstraint(
388 substring(components
[3], 0, 2),
392 : dayOfMonthValuesConstraint(
393 substring(components
[2], 0, 2),
397 })`${yearFrag}-${monthFrag}-${dayFrag}T(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}?`;
398 const timeLexicalRep
= match(
400 )`(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}?`;
401 const dateLexicalRep
= match("dateLexicalRep", ($) => {
402 const components
= stringSplit($, "-");
403 return components
[0] === ""
404 ? dayOfMonthValuesConstraint(
405 substring(components
[3], 0, 2),
409 : dayOfMonthValuesConstraint(
410 substring(components
[2], 0, 2),
414 })`${yearFrag}-${monthFrag}-${dayFrag}${timezoneFrag}?`;
415 const gYearMonthLexicalRep
= match(
416 "gYearMonthLexicalRep",
417 )`${yearFrag}-${monthFrag}${timezoneFrag}?`;
418 const gYearLexicalRep
= match(
420 )`${yearFrag}${timezoneFrag}?`;
421 const gMonthDayLexicalRep
= match("gMonthDayLexicalRep", ($) => {
422 const components
= stringSplit(substring($, 2), "-");
423 return dayOfMonthValuesConstraint(
424 substring(components
[1], 0, 2),
427 })`--${monthFrag}-${dayFrag}${timezoneFrag}?`;
428 const gDayLexicalRep
= match(
430 )`---${dayFrag}${timezoneFrag}?`;
431 const gMonthLexicalRep
= match(
433 )`--${monthFrag}${timezoneFrag}?`;
434 const hexDigit
= match("hexDigit")`[0-9a-fA-F]`;
435 const hexOctet
= match("hexOctet")`${hexDigit}{2}`;
436 const hexBinary
= match("hexBinary")`${hexOctet}*`;
437 const B04char
= match("B04char")`[AQgw]`;
438 const B04
= match("B04")`${B04char}\u{20}?`;
439 const B16char
= match("B16char")`[AEIMQUYcgkosw048]`;
440 const B16
= match("B16")`${B16char}\u{20}?`;
441 const B64char
= match("B64char")`[A-Za-z0-9+/]`;
442 const B64
= match("B64")`${B64char}\u{20}?`;
443 const Padded8
= match("Padded8")`${B64}${B04}=\u{20}?=`;
444 const Padded16
= match("Padded16")`${B64}{2}${B16}=`;
445 const B64finalquad
= match("B64finalquad")`${B64}{3}${B64char}`;
446 const B64final
= match(
448 )`${B64finalquad}|${Padded16}|${Padded8}`;
449 const B64quad
= match("B64quad")`${B64}{4}`;
450 const Base64Binary
= match(
452 )`(?:${B64quad}*${B64final})?`;
453 const CanonicalPadded
= match(
455 )`${B64char}{2}${B16char}=|${B64char}${B04char}==`;
456 const CanonicalQuad
= match("CanonicalQuad")`${B64char}{4}`;
457 const Canonical
·base64Binary
= match(
458 "Canonical·base64Binary",
459 )`${CanonicalQuad}*${CanonicalPadded}?`;
460 const yearMonthDurationLexicalRep
= match(
461 "yearMonthDurationLexicalRep",
462 )`-?P${duYearMonthFrag}`;
463 const dayTimeDurationLexicalRep
= match(
464 "dayTimeDurationLexicalRep",
465 )`-?P${duDayTimeFrag}`;
466 const dateTimeStampLexicalRep
= match(
467 "dateTimeStampLexicalRep",
469 const components
= stringSplit($, "-");
470 return components
[0] === ""
471 ? dayOfMonthValuesConstraint(
472 substring(components
[3], 0, 2),
476 : dayOfMonthValuesConstraint(
477 substring(components
[2], 0, 2),
482 )`${yearFrag}-${monthFrag}-${dayFrag}T(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}`;