]> Lady’s Gitweb - Sutra/blob - xsd/productions.js
Add all X·S·D non‐auxillary functions
[Sutra] / xsd / productions.js
1 //deno-lint-ignore-file no-unused-vars
2 // ♓️🪡 सूत्र ∷ xsd/productions.js
3 // ====================================================================
4 //
5 // Copyright © 2023 Lady [@ Lady’s Computer].
6 //
7 // This Source Code Form is subject to the terms of the Mozilla Public
8 // License, v. 2.0. If a copy of the MPL was not distributed with this
9 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
10
11 import {
12 Matcher,
13 objectCreate,
14 rawString,
15 stringSplit,
16 substring,
17 } from "../deps.js";
18
19 const dayOfMonthValuesConstraint = (day, month, year = "1972") => {
20 const d = +day;
21 const m = +month;
22 const y = +year;
23 return m === 4 || m === 6 || m === 9 || m === 11
24 ? d <= 30
25 : m === 2 && (y % 4 || !(y % 100) && y % 400)
26 ? d <= 28
27 : m === 2 && (!(y % 400) || !(y % 4) && y % 100)
28 ? d <= 29
29 : true;
30 };
31
32 export const {
33 /** `[1] stringRep ::= Char*` */
34 stringRep,
35
36 /** `[2] booleanRep ::= 'true' | 'false' | '1' | '0'` */
37 booleanRep,
38
39 /** `[3] decimalLexicalRep ::= decimalPtNumeral | noDecimalPtNumeral` */
40 decimalLexicalRep,
41
42 /** `[4] floatRep ::= noDecimalPtNumeral | decimalPtNumeral | scientificNotationNumeral | numericalSpecialRep` */
43 floatRep,
44
45 /** `[5] doubleRep ::= noDecimalPtNumeral | decimalPtNumeral | scientificNotationNumeral | numericalSpecialRep` */
46 doubleRep,
47
48 /** `[6] duYearFrag ::= unsignedNoDecimalPtNumeral 'Y'` */
49 duYearFrag,
50
51 /** `[7] duMonthFrag ::= unsignedNoDecimalPtNumeral 'M'` */
52 duMonthFrag,
53
54 /** `[8] duDayFrag ::= unsignedNoDecimalPtNumeral 'D'` */
55 duDayFrag,
56
57 /** `[9] duHourFrag ::= unsignedNoDecimalPtNumeral 'H'` */
58 duHourFrag,
59
60 /** `[10] duMinuteFrag ::= unsignedNoDecimalPtNumeral 'M'` */
61 duMinuteFrag,
62
63 /**
64 * `[11] duSecondFrag ::= (unsignedNoDecimalPtNumeral | unsignedFullDecimalPtNumeral) 'S'`
65 *
66 * ※ The X·S·D specification specifies unsignedDecimalPtNumeral, not
67 * unsignedFullDecimalPtNumeral, but the specification text and
68 * provided regular expressions imply that the latter was intended.
69 */
70 duSecondFrag,
71
72 /** `[12] duYearMonthFrag ::= (duYearFrag duMonthFrag?) | duMonthFrag` */
73 duYearMonthFrag,
74
75 /** `[13] duTimeFrag ::= 'T' ((duHourFrag duMinuteFrag? duSecondFrag?) | (duMinuteFrag duSecondFrag?) | duSecondFrag)` */
76 duTimeFrag,
77
78 /** `[14] duDayTimeFrag ::= (duDayFrag duTimeFrag?) | duTimeFrag` */
79 duDayTimeFrag,
80
81 /** `[15] durationLexicalRep ::= '-'? 'P' ((duYearMonthFrag duDayTimeFrag?) | duDayTimeFrag)` */
82 durationLexicalRep,
83
84 /**
85 * `[16] dateTimeLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?`
86 *
87 * **Constraint: Day-of-month Values**
88 *
89 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
90 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
91 * divisible by 4, or is divisible by 100 but not by 400; and no more
92 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
93 * but not by 100.
94 *
95 * **Constraint: Day-of-month Representations**
96 *
97 * Within a dateTimeLexicalRep, a dayFrag must not begin with the
98 * digit '3' or be '29' unless the value to which it would map would
99 * satisfy the value constraint on ·day· values ("Constraint:
100 * Day-of-month Values") given above.
101 */
102 dateTimeLexicalRep,
103
104 /** `[17] timeLexicalRep ::= ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?` */
105 timeLexicalRep,
106
107 /**
108 * `[18] dateLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag timezoneFrag?`
109 *
110 * **Constraint: Day-of-month Values**
111 *
112 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
113 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
114 * divisible by 4, or is divisible by 100 but not by 400; and no more
115 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
116 * but not by 100.
117 *
118 * **Constraint: Day-of-month Representations**
119 *
120 * Within a dateLexicalRep, a dayFrag must not begin with the digit
121 * '3' or be '29' unless the value to which it would map would
122 * satisfy the value constraint on ·day· values ("Constraint:
123 * Day-of-month Values") given above.
124 */
125 dateLexicalRep,
126
127 /** `[19] gYearMonthLexicalRep ::= yearFrag '-' monthFrag timezoneFrag?` */
128 gYearMonthLexicalRep,
129
130 /** `[20] gYearLexicalRep ::= yearFrag timezoneFrag?` */
131 gYearLexicalRep,
132
133 /**
134 * `[21] gMonthDayLexicalRep ::= '--' monthFrag '-' dayFrag timezoneFrag?`
135 *
136 * **Constraint: Day-of-month Values**
137 *
138 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
139 * 9, or 11, and no more than 29 if ·month· is 2.
140 *
141 * **Constraint: Day-of-month Representations**
142 *
143 * Within a gMonthDayLexicalRep, a dayFrag must not begin with the
144 * digit '3' or be '29' unless the value to which it would map would
145 * satisfy the value constraint on ·day· values ("Constraint:
146 * Day-of-month Values") given above.
147 */
148 gMonthDayLexicalRep,
149
150 /** `[22] gDayLexicalRep ::= '---' dayFrag timezoneFrag?` */
151 gDayLexicalRep,
152
153 /** `[23] gMonthLexicalRep ::= '--' monthFrag timezoneFrag?` */
154 gMonthLexicalRep,
155
156 /** `[24] hexDigit ::= [0-9a-fA-F]` */
157 hexDigit,
158
159 /** `[25] hexOctet ::= hexDigit hexDigit` */
160 hexOctet,
161
162 /** `[26] hexBinary ::= hexOctet*` */
163 hexBinary,
164
165 /** `[27] Base64Binary ::= (B64quad* B64final)?` */
166 Base64Binary,
167
168 /** `[28] B64quad ::= (B64 B64 B64 B64)` */
169 B64quad,
170
171 /** `[29] B64final ::= B64finalquad | Padded16 | Padded8` */
172 B64final,
173
174 /** `[30] B64finalquad ::= (B64 B64 B64 B64char)` */
175 B64finalquad,
176
177 /** `[31] Padded16 ::= B64 B64 B16 '='` */
178 Padded16,
179
180 /** `[32] Padded8 ::= B64 B04 '=' #x20? '='` */
181 Padded8,
182
183 /** `[33] B64 ::= B64char #x20?` */
184 B64,
185
186 /** `[34] B64char ::= [A-Za-z0-9+/]` */
187 B64char,
188
189 /** `[35] B16 ::= B16char #x20?` */
190 B16,
191
192 /** `[36] B16char ::= [AEIMQUYcgkosw048]` */
193 B16char,
194
195 /** `[37] B04 ::= B04char #x20?` */
196 B04,
197
198 /** `[38] B04char ::= [AQgw]` */
199 B04char,
200
201 /** `[39] Canonical-base64Binary ::= CanonicalQuad* CanonicalPadded?` */
202 Canonical·base64Binary,
203
204 /** `[40] CanonicalQuad ::= B64char B64char B64char B64char` */
205 CanonicalQuad,
206
207 /** `[41] CanonicalPadded ::= B64char B64char B16char '=' | B64char B04char '=='` */
208 CanonicalPadded,
209
210 /** `[42] yearMonthDurationLexicalRep ::= '-'? 'P' duYearMonthFrag` */
211 yearMonthDurationLexicalRep,
212
213 /** `[43] dayTimeDurationLexicalRep ::= '-'? 'P' duDayTimeFrag` */
214 dayTimeDurationLexicalRep,
215
216 /**
217 * `[44] dateTimeStampLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag`
218 *
219 * **Constraint: Day-of-month Values**
220 *
221 * The ·day· value must be no more than 30 if ·month· is one of 4, 6,
222 * 9, or 11; no more than 28 if ·month· is 2 and ·year· is not
223 * divisible by 4, or is divisible by 100 but not by 400; and no more
224 * than 29 if ·month· is 2 and ·year· is divisible by 400, or by 4
225 * but not by 100.
226 *
227 * **Constraint: Day-of-month Representations**
228 *
229 * Within a dateTimeStampLexicalRep, a dayFrag must not begin with
230 * the digit '3' or be '29' unless the value to which it would map
231 * would satisfy the value constraint on ·day· values ("Constraint:
232 * Day-of-month Values") given above.
233 */
234 dateTimeStampLexicalRep,
235
236 /** `[45] digit ::= [0-9]` */
237 digit,
238
239 /** `[46] unsignedNoDecimalPtNumeral ::= digit+` */
240 unsignedNoDecimalPtNumeral,
241
242 /** `[47] noDecimalPtNumeral ::= ('+' | '-')? unsignedNoDecimalPtNumeral` */
243 noDecimalPtNumeral,
244
245 /** `[48] fracFrag ::= digit+` */
246 fracFrag,
247
248 /** `[49] unsignedDecimalPtNumeral ::= (unsignedNoDecimalPtNumeral '.' fracFrag?) | ('.' fracFrag)` */
249 unsignedDecimalPtNumeral,
250
251 /** `[50] unsignedFullDecimalPtNumeral ::= unsignedNoDecimalPtNumeral '.' fracFrag` */
252 unsignedFullDecimalPtNumeral,
253
254 /** `[51] decimalPtNumeral ::= ('+' | '-')? unsignedDecimalPtNumeral` */
255 decimalPtNumeral,
256
257 /** `[52] unsignedScientificNotationNumeral ::= (unsignedNoDecimalPtNumeral | unsignedDecimalPtNumeral) ('e' | 'E') noDecimalPtNumeral` */
258 unsignedScientificNotationNumeral,
259
260 /** `[53] scientificNotationNumeral ::= ('+' | '-')? unsignedScientificNotationNumeral` */
261 scientificNotationNumeral,
262
263 /** `[54] minimalNumericalSpecialRep ::= 'INF' | '-INF' | 'NaN'` */
264 minimalNumericalSpecialRep,
265
266 /** `[55] numericalSpecialRep ::= ('+' | '-')? unsignedScientificNotationNumeral` */
267 numericalSpecialRep,
268
269 /** `[56] yearFrag ::= '-'? (([1-9] digit digit digit+)) | ('0' digit digit digit))` */
270 yearFrag,
271
272 /** `[57] monthFrag ::= ('0' [1-9]) | ('1' [0-2])` */
273 monthFrag,
274
275 /** `[58] dayFrag ::= ('0' [1-9]) | ([12] digit) | ('3' [01])` */
276 dayFrag,
277
278 /** `[59] hourFrag ::= ([01] digit) | ('2' [0-3])` */
279 hourFrag,
280
281 /** `[60] minuteFrag ::= [0-5] digit` */
282 minuteFrag,
283
284 /** `[61] secondFrag ::= ([0-5] digit) ('.' digit+)?` */
285 secondFrag,
286
287 /** `[62] endOfDayFrag ::= '24:00:00' ('.' '0'+)?` */
288 endOfDayFrag,
289
290 /** `[63] timezoneFrag ::= 'Z' | ('+' | '-') (('0' digit | '1' [0-3]) ':' minuteFrag | '14:00')` */
291 timezoneFrag,
292 } = (() => {
293 const matchers = objectCreate(null);
294 const match =
295 (name, constraint = null) => (strings, ...substitutions) => {
296 const source = `(?:${rawString(strings, ...substitutions)})`;
297 matchers[name] = new Matcher(`^${source}$`, name, constraint);
298 return source;
299 };
300
301 const stringRep = match(
302 "stringRep",
303 )`[^\u{0}\u{D800}-\u{DFFF}\u{FFFE}\u{FFFF}]*`;
304 const booleanRep = match("booleanRep")`true|false|1|0`;
305 const digit = match("digit")`[0-9]`;
306 const unsignedNoDecimalPtNumeral = match(
307 "unsignedNoDecimalPtNumeral",
308 )`${digit}+`;
309 const noDecimalPtNumeral = match(
310 "noDecimalPtNumeral",
311 )`[+-]?${unsignedNoDecimalPtNumeral}`;
312 const fracFrag = match("fracFrag")`${digit}+`;
313 const unsignedDecimalPtNumeral = match(
314 "unsignedDecimalPtNumeral",
315 )`${unsignedNoDecimalPtNumeral}\.${fracFrag}?|\.${fracFrag}`;
316 const unsignedFullDecimalPtNumeral = match(
317 "unsignedFullDecimalPtNumeral",
318 )`${unsignedNoDecimalPtNumeral}\.${fracFrag}`;
319 const decimalPtNumeral = match(
320 "decimalPtNumeral",
321 )`[+-]?${unsignedDecimalPtNumeral}`;
322 const unsignedScientificNotationNumeral = match(
323 "unsignedScientificNotationNumeral",
324 )`(?:${unsignedNoDecimalPtNumeral}|${unsignedDecimalPtNumeral})[eE]${noDecimalPtNumeral}`;
325 const scientificNotationNumeral = match(
326 "scientificNotationNumeral",
327 )`[+-]?${unsignedScientificNotationNumeral}`;
328 const minimalNumericalSpecialRep = match(
329 "minimalNumericalSpecialRep",
330 )`INF|-INF|NaN`;
331 const numericalSpecialRep = match(
332 "numericalSpecialRep",
333 )`\+INF|${minimalNumericalSpecialRep}`;
334 const decimalLexicalRep = match(
335 "decimalLexicalRep",
336 )`${decimalPtNumeral}|${noDecimalPtNumeral}`;
337 const floatRep = match(
338 "floatRep",
339 )`${noDecimalPtNumeral}|${decimalPtNumeral}|${scientificNotationNumeral}|${numericalSpecialRep}`;
340 const doubleRep = match(
341 "doubleRep",
342 )`${noDecimalPtNumeral}|${decimalPtNumeral}|${scientificNotationNumeral}|${numericalSpecialRep}`;
343 const duYearFrag = match(
344 "duYearFrag",
345 )`${unsignedNoDecimalPtNumeral}Y`;
346 const duMonthFrag = match(
347 "duMonthFrag",
348 )`${unsignedNoDecimalPtNumeral}M`;
349 const duDayFrag = match("duDayFrag")`${unsignedNoDecimalPtNumeral}D`;
350 const duHourFrag = match(
351 "duHourFrag",
352 )`${unsignedNoDecimalPtNumeral}H`;
353 const duMinuteFrag = match(
354 "duMinuteFrag",
355 )`${unsignedNoDecimalPtNumeral}M`;
356 const duSecondFrag = match(
357 "duSecondFrag",
358 )`(?:${unsignedNoDecimalPtNumeral}|${unsignedFullDecimalPtNumeral})S`;
359 const duYearMonthFrag = match(
360 "duYearMonthFrag",
361 )`${duYearFrag}${duMonthFrag}?|${duMonthFrag}`;
362 const duTimeFrag = match(
363 "duTimeFrag",
364 )`T(?:${duHourFrag}${duMinuteFrag}?${duSecondFrag}?|${duMinuteFrag}${duSecondFrag}?|${duSecondFrag})`;
365 const duDayTimeFrag = match(
366 "duDayTimeFrag",
367 )`${duDayFrag}${duTimeFrag}?|${duTimeFrag}`;
368 const durationLexicalRep = match(
369 "durationLexicalRep",
370 )`-?P(?:${duYearMonthFrag}${duDayTimeFrag}?|${duDayTimeFrag})`;
371 const yearFrag = match(
372 "yearFrag",
373 )`-?(?:[1-9]${digit}{3,}|0${digit}{3})`;
374 const monthFrag = match("monthFrag")`0[1-9]|1[0-2]`;
375 const dayFrag = match("dayFrag")`0[1-9]|[12]${digit}|3[01]`;
376 const hourFrag = match("hourFrag")`[01]${digit}|2[0-3]`;
377 const minuteFrag = match("minuteFrag")`[0-5]${digit}`;
378 const secondFrag = match(
379 "secondFrag",
380 )`[0-5]${digit}(?:\.${digit}+)?`;
381 const endOfDayFrag = match("endOfDayFrag")`24:00:00(?:\.0+)?`;
382 const timezoneFrag = match(
383 "timezoneFrag",
384 )`Z|[+-](?:(?:0${digit}|1[0-3]):${minuteFrag}|14:00)`;
385 const dateTimeLexicalRep = match("dateTimeLexicalRep", ($) => {
386 const components = stringSplit($, "-");
387 return components[0] === ""
388 ? dayOfMonthValuesConstraint(
389 substring(components[3], 0, 2),
390 components[2],
391 `-${components[1]}`,
392 )
393 : dayOfMonthValuesConstraint(
394 substring(components[2], 0, 2),
395 components[1],
396 components[0],
397 );
398 })`${yearFrag}-${monthFrag}-${dayFrag}T(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}?`;
399 const timeLexicalRep = match(
400 "timeLexicalRep",
401 )`(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}?`;
402 const dateLexicalRep = match("dateLexicalRep", ($) => {
403 const components = stringSplit($, "-");
404 return components[0] === ""
405 ? dayOfMonthValuesConstraint(
406 substring(components[3], 0, 2),
407 components[2],
408 `-${components[1]}`,
409 )
410 : dayOfMonthValuesConstraint(
411 substring(components[2], 0, 2),
412 components[1],
413 components[0],
414 );
415 })`${yearFrag}-${monthFrag}-${dayFrag}${timezoneFrag}?`;
416 const gYearMonthLexicalRep = match(
417 "gYearMonthLexicalRep",
418 )`${yearFrag}-${monthFrag}${timezoneFrag}?`;
419 const gYearLexicalRep = match(
420 "gYearLexicalRep",
421 )`${yearFrag}${timezoneFrag}?`;
422 const gMonthDayLexicalRep = match("gMonthDayLexicalRep", ($) => {
423 const components = stringSplit(substring($, 2), "-");
424 return dayOfMonthValuesConstraint(
425 substring(components[1], 0, 2),
426 components[0],
427 );
428 })`--${monthFrag}-${dayFrag}${timezoneFrag}?`;
429 const gDayLexicalRep = match(
430 "gDayLexicalRep",
431 )`---${dayFrag}${timezoneFrag}?`;
432 const gMonthLexicalRep = match(
433 "gMonthLexicalRep",
434 )`--${monthFrag}${timezoneFrag}?`;
435 const hexDigit = match("hexDigit")`[0-9a-fA-F]`;
436 const hexOctet = match("hexOctet")`${hexDigit}{2}`;
437 const hexBinary = match("hexBinary")`${hexOctet}*`;
438 const B04char = match("B04char")`[AQgw]`;
439 const B04 = match("B04")`${B04char}\u{20}?`;
440 const B16char = match("B16char")`[AEIMQUYcgkosw048]`;
441 const B16 = match("B16")`${B16char}\u{20}?`;
442 const B64char = match("B64char")`[A-Za-z0-9+/]`;
443 const B64 = match("B64")`${B64char}\u{20}?`;
444 const Padded8 = match("Padded8")`${B64}${B04}=\u{20}?=`;
445 const Padded16 = match("Padded16")`${B64}{2}${B16}=`;
446 const B64finalquad = match("B64finalquad")`${B64}{3}${B64char}`;
447 const B64final = match(
448 "B64final",
449 )`${B64finalquad}|${Padded16}|${Padded8}`;
450 const B64quad = match("B64quad")`${B64}{4}`;
451 const Base64Binary = match(
452 "Base64Binary",
453 )`(?:${B64quad}*${B64final})?`;
454 const CanonicalPadded = match(
455 "CanonicalPadded",
456 )`${B64char}{2}${B16char}=|${B64char}${B04char}==`;
457 const CanonicalQuad = match("CanonicalQuad")`${B64char}{4}`;
458 const Canonical·base64Binary = match(
459 "Canonical·base64Binary",
460 )`${CanonicalQuad}*${CanonicalPadded}?`;
461 const yearMonthDurationLexicalRep = match(
462 "yearMonthDurationLexicalRep",
463 )`-?P${duYearMonthFrag}`;
464 const dayTimeDurationLexicalRep = match(
465 "dayTimeDurationLexicalRep",
466 )`-?P${duDayTimeFrag}`;
467 const dateTimeStampLexicalRep = match(
468 "dateTimeStampLexicalRep",
469 ($) => {
470 const components = stringSplit($, "-");
471 return components[0] === ""
472 ? dayOfMonthValuesConstraint(
473 substring(components[3], 0, 2),
474 components[2],
475 `-${components[1]}`,
476 )
477 : dayOfMonthValuesConstraint(
478 substring(components[2], 0, 2),
479 components[1],
480 components[0],
481 );
482 },
483 )`${yearFrag}-${monthFrag}-${dayFrag}T(?:${hourFrag}:${minuteFrag}:${secondFrag}|${endOfDayFrag})${timezoneFrag}`;
484
485 return matchers;
486 })();
This page took 0.096106 seconds and 5 git commands to generate.