rrule-ts 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ import type { RRuleOptions } from '../types.js';
2
+ import type { Result } from '../result.js';
3
+ /**
4
+ * Parse a human-readable English recurrence description into RRuleOptions.
5
+ *
6
+ * Only accepts canonical output produced by toText with the EN locale. Not a
7
+ * general natural-language parser.
8
+ *
9
+ * Round-trip guarantee: for all RRuleOptions x where toText(x, {locale: en})
10
+ * does not return the complex-rule fallback string,
11
+ * fromText(toText(x, {locale: en}), {locale: en}).value deep-equals x
12
+ * (excluding dtstart, tzid, wkst, bySecond which are absent from text output,
13
+ * and excluding byMinute=[0] which is indistinguishable from byMinute=undefined
14
+ * in the rendered text).
15
+ *
16
+ * Returns Err if the text cannot be parsed as EN toText output.
17
+ *
18
+ * Out of scope: BYWEEKNO, BYYEARDAY, BYSECOND, WKST,
19
+ * multi-value BYSETPOS, free-form prose not produced by toText.
20
+ * fromText is EN-only: passing DE (or any other locale) text returns Err.
21
+ */
22
+ export declare function fromText(text: string): Result<RRuleOptions, string>;
23
+ //# sourceMappingURL=fromText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromText.d.ts","sourceRoot":"","sources":["../../src/text/fromText.ts"],"names":[],"mappings":"AAgEA,OAAO,KAAK,EAAa,YAAY,EAAuB,MAAM,aAAa,CAAA;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAsiB1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAcnE"}
@@ -0,0 +1,604 @@
1
+ // fromText.ts - Tokenized recursive-descent parser for canonical EN toText output.
2
+ //
3
+ // Returns Result<RRuleOptions, string>. Never throws on user input: all errors
4
+ // are returned as Err values.
5
+ //
6
+ // Supported grammar (formal BNF, EN only):
7
+ //
8
+ // sentence := interval-phrase
9
+ // [ bymonth-clause ]
10
+ // [ byday-clause | bymonthday-clause ]
11
+ // [ time-clause ]
12
+ // [ terminator ]
13
+ //
14
+ // interval-phrase := 'every' singular-unit
15
+ // | 'every' UINT plural-unit
16
+ //
17
+ // singular-unit := 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
18
+ // plural-unit := 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'years'
19
+ //
20
+ // bymonth-clause := 'in' month-name-list
21
+ // month-name-list := month-name { [ ',' ] [ 'and' ] month-name }
22
+ //
23
+ // byday-clause := 'on' 'the' byday-the-spec
24
+ // | 'on' weekday-name-list
25
+ //
26
+ // byday-the-spec := 'last' 'day' -- BYMONTHDAY=-1
27
+ // | 'last' 'weekday' -- BYSETPOS=-1 + Mon-Fri
28
+ // | 'last' weekday-name byday-more* -- BYDAY=-1WD [...]
29
+ // | ordinal weekday-name byday-more* -- BYDAY=NWD [...]
30
+ // | ordinal bymonthday-more* -- BYMONTHDAY=N [,M]*
31
+ // | neg-ordinal 'day' neg-day-more* -- BYMONTHDAY=-N [,-M]*
32
+ //
33
+ // byday-more := ( ',' ['and'] | 'and' ) 'the' ( 'last' | ordinal ) weekday-name
34
+ // bymonthday-more := ( ',' ['and'] | 'and' ) ordinal
35
+ // neg-day-more := ( ',' ['and'] | 'and' ) neg-ordinal 'day'
36
+ //
37
+ // time-clause := 'at' time-string { ( ',' ['and'] | 'and' ) time-string }
38
+ // time-string := UINT ':' MM
39
+ //
40
+ // terminator := ',' UINT ( 'time' | 'times' )
41
+ // | 'until' date-phrase
42
+ //
43
+ // date-phrase := month-name UINT ',' UINT [ 'at' UINT ':' MM ]
44
+ //
45
+ // weekday-name-list := weekday-name { ( ',' ['and'] | 'and' ) weekday-name }
46
+ // weekday-name := 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday'
47
+ // | 'Friday' | 'Saturday' | 'Sunday'
48
+ // month-name := 'January' | 'February' | 'March' | 'April' | 'May'
49
+ // | 'June' | 'July' | 'August' | 'September' | 'October'
50
+ // | 'November' | 'December'
51
+ // ordinal := UINT ( 'st' | 'nd' | 'rd' | 'th' )
52
+ // neg-ordinal := UINT ( 'st' | 'nd' | 'rd' | 'th' ) '-to-last'
53
+ //
54
+ // Out of scope (explicitly not supported):
55
+ // - German (DE) locale or any locale other than 'en'
56
+ // - BYWEEKNO, BYYEARDAY, BYSECOND, WKST
57
+ // - Multi-value BYSETPOS (only BYSETPOS=-1 with the Mon-Fri weekday pattern)
58
+ // - BYSETPOS with a single weekday (parsed as ordinal BYDAY instead)
59
+ // - Free-form prose not produced by toText
60
+ // - Fields absent from toText output: dtstart, tzid, wkst, bySecond
61
+ //
62
+ // Circular dependency note: fromText is pinned to toText's output format.
63
+ // If toText EN output changes, update fromText in the same commit.
64
+ import { ok, err } from '../result.js';
65
+ import { getTemporal } from '../temporal.js';
66
+ // ---------------------------------------------------------------------------
67
+ // Lookup tables
68
+ // ---------------------------------------------------------------------------
69
+ const SINGULAR_FREQ = {
70
+ second: 'SECONDLY',
71
+ minute: 'MINUTELY',
72
+ hour: 'HOURLY',
73
+ day: 'DAILY',
74
+ week: 'WEEKLY',
75
+ month: 'MONTHLY',
76
+ year: 'YEARLY',
77
+ };
78
+ const PLURAL_FREQ = {
79
+ seconds: 'SECONDLY',
80
+ minutes: 'MINUTELY',
81
+ hours: 'HOURLY',
82
+ days: 'DAILY',
83
+ weeks: 'WEEKLY',
84
+ months: 'MONTHLY',
85
+ years: 'YEARLY',
86
+ };
87
+ const EN_MONTH_INDEX = {
88
+ January: 1,
89
+ February: 2,
90
+ March: 3,
91
+ April: 4,
92
+ May: 5,
93
+ June: 6,
94
+ July: 7,
95
+ August: 8,
96
+ September: 9,
97
+ October: 10,
98
+ November: 11,
99
+ December: 12,
100
+ };
101
+ const EN_WEEKDAY = {
102
+ Monday: 'MO',
103
+ Tuesday: 'TU',
104
+ Wednesday: 'WE',
105
+ Thursday: 'TH',
106
+ Friday: 'FR',
107
+ Saturday: 'SA',
108
+ Sunday: 'SU',
109
+ };
110
+ /** The Mon-Fri business-day set used for BYSETPOS=-1 + weekday pattern. */
111
+ const MON_TO_FRI = [
112
+ { weekday: 'MO', ordinal: undefined },
113
+ { weekday: 'TU', ordinal: undefined },
114
+ { weekday: 'WE', ordinal: undefined },
115
+ { weekday: 'TH', ordinal: undefined },
116
+ { weekday: 'FR', ordinal: undefined },
117
+ ];
118
+ // ---------------------------------------------------------------------------
119
+ // Tokenizer
120
+ // ---------------------------------------------------------------------------
121
+ /**
122
+ * Split text into tokens. Commas are separated into standalone tokens so
123
+ * the parser can skip them individually without touching surrounding words.
124
+ */
125
+ function tokenize(text) {
126
+ return text
127
+ .replace(/,/g, ' , ')
128
+ .split(/\s+/)
129
+ .filter((s) => s.length > 0);
130
+ }
131
+ // ---------------------------------------------------------------------------
132
+ // Ordinal helpers
133
+ // ---------------------------------------------------------------------------
134
+ /** Parse a positive English ordinal like '1st', '2nd', '15th'. Returns null on mismatch. */
135
+ function parseOrdinal(s) {
136
+ const m = s.match(/^(\d+)(st|nd|rd|th)$/);
137
+ if (!m)
138
+ return null;
139
+ return parseInt(m[1], 10);
140
+ }
141
+ /**
142
+ * Parse a negative-ordinal token like '2nd-to-last'. Returns the negative
143
+ * number (-2 for '2nd-to-last') or null if not that pattern.
144
+ */
145
+ function parseNegOrdinalToLast(s) {
146
+ const m = s.match(/^(\d+)(st|nd|rd|th)-to-last$/);
147
+ if (!m)
148
+ return null;
149
+ return -parseInt(m[1], 10);
150
+ }
151
+ // ---------------------------------------------------------------------------
152
+ // Parser class
153
+ // ---------------------------------------------------------------------------
154
+ class Parser {
155
+ tokens;
156
+ pos = 0;
157
+ constructor(tokens) {
158
+ this.tokens = tokens;
159
+ }
160
+ peek(offset = 0) {
161
+ return this.tokens[this.pos + offset];
162
+ }
163
+ consume() {
164
+ const t = this.tokens[this.pos];
165
+ if (t === undefined)
166
+ throw new Error('fromText: unexpected end of input');
167
+ this.pos++;
168
+ return t;
169
+ }
170
+ consumeIf(expected) {
171
+ if (this.peek() === expected) {
172
+ this.pos++;
173
+ return true;
174
+ }
175
+ return false;
176
+ }
177
+ /** Save current position for backtracking. */
178
+ save() {
179
+ return this.pos;
180
+ }
181
+ /** Restore a previously saved position. */
182
+ restore(saved) {
183
+ this.pos = saved;
184
+ }
185
+ isDone() {
186
+ return this.pos >= this.tokens.length;
187
+ }
188
+ }
189
+ // ---------------------------------------------------------------------------
190
+ // Grammar rule parsers
191
+ // ---------------------------------------------------------------------------
192
+ function parseIntervalPhrase(p) {
193
+ const first = p.consume();
194
+ if (first !== 'every')
195
+ throw new Error(`fromText: expected 'every', got '${first}'`);
196
+ const next = p.peek();
197
+ if (next === undefined)
198
+ throw new Error("fromText: unexpected end after 'every'");
199
+ if (next in SINGULAR_FREQ) {
200
+ p.consume();
201
+ return { freq: SINGULAR_FREQ[next], interval: 1 };
202
+ }
203
+ const n = parseInt(next, 10);
204
+ if (isNaN(n) || n < 1)
205
+ throw new Error(`fromText: expected freq unit or interval number, got '${next}'`);
206
+ p.consume();
207
+ const unit = p.peek();
208
+ if (unit === undefined || !(unit in PLURAL_FREQ)) {
209
+ throw new Error(`fromText: expected plural frequency unit after interval, got '${unit}'`);
210
+ }
211
+ p.consume();
212
+ return { freq: PLURAL_FREQ[unit], interval: n };
213
+ }
214
+ /** Parse a list separator: optional comma then optional 'and'. Returns true if a separator was consumed. */
215
+ function consumeListSeparator(p) {
216
+ if (p.peek() === ',') {
217
+ p.consume();
218
+ p.consumeIf('and');
219
+ return true;
220
+ }
221
+ if (p.peek() === 'and') {
222
+ p.consume();
223
+ return true;
224
+ }
225
+ return false;
226
+ }
227
+ function parseMonthList(p) {
228
+ const months = [];
229
+ while (true) {
230
+ const token = p.peek();
231
+ if (token === undefined || !(token in EN_MONTH_INDEX))
232
+ break;
233
+ p.consume();
234
+ months.push(EN_MONTH_INDEX[token]);
235
+ // Save position before consuming the separator: restore if the next
236
+ // token is not a month name (the separator may belong to a terminator).
237
+ const saved = p.save();
238
+ if (!consumeListSeparator(p))
239
+ break;
240
+ if (p.peek() === undefined || !(p.peek() in EN_MONTH_INDEX)) {
241
+ p.restore(saved);
242
+ break;
243
+ }
244
+ }
245
+ if (months.length === 0)
246
+ throw new Error("fromText: expected month name after 'in'");
247
+ return months;
248
+ }
249
+ function parsePlainWeekdayList(p) {
250
+ const byDay = [];
251
+ while (true) {
252
+ const token = p.peek();
253
+ if (token === undefined || !(token in EN_WEEKDAY))
254
+ break;
255
+ p.consume();
256
+ byDay.push({ weekday: EN_WEEKDAY[token], ordinal: undefined });
257
+ // Save position before consuming the separator: restore if the next
258
+ // token is not a weekday name (the separator may belong to a terminator).
259
+ const saved = p.save();
260
+ if (!consumeListSeparator(p))
261
+ break;
262
+ if (p.peek() === undefined || !(p.peek() in EN_WEEKDAY)) {
263
+ p.restore(saved);
264
+ break;
265
+ }
266
+ }
267
+ if (byDay.length === 0)
268
+ throw new Error('fromText: expected weekday name');
269
+ return byDay;
270
+ }
271
+ /**
272
+ * Continue collecting ordinal BYDAY entries after the first entry is already added.
273
+ * Expects pattern: { ( ',' ['and'] | 'and' ) 'the' ( 'last' | ordinal ) weekday-name }*
274
+ */
275
+ function continueBydayOrdinalList(p, byDay) {
276
+ while (true) {
277
+ // Look-ahead: check if next tokens are a list separator followed by 'the'.
278
+ // Save position so we can restore it if the pattern does not match (the
279
+ // separator may belong to the COUNT terminator: ', N times').
280
+ if (p.peek() === ',') {
281
+ const saved = p.save();
282
+ p.consume(); // ','
283
+ p.consumeIf('and');
284
+ if (p.peek() !== 'the') {
285
+ p.restore(saved);
286
+ break;
287
+ }
288
+ p.consume(); // 'the'
289
+ }
290
+ else if (p.peek() === 'and') {
291
+ const saved = p.save();
292
+ p.consume(); // 'and'
293
+ if (p.peek() !== 'the') {
294
+ p.restore(saved);
295
+ break;
296
+ }
297
+ p.consume(); // 'the'
298
+ }
299
+ else {
300
+ break;
301
+ }
302
+ // Parse 'last', 'Nth-to-last', or a positive ordinal.
303
+ let nextOrd;
304
+ if (p.peek() === 'last') {
305
+ p.consume();
306
+ nextOrd = -1;
307
+ }
308
+ else {
309
+ const negNo = parseNegOrdinalToLast(p.peek() ?? '');
310
+ if (negNo !== null) {
311
+ p.consume();
312
+ nextOrd = negNo;
313
+ }
314
+ else {
315
+ const no = parseOrdinal(p.peek() ?? '');
316
+ if (no === null)
317
+ throw new Error(`fromText: expected ordinal in BYDAY list, got '${p.peek()}'`);
318
+ p.consume();
319
+ nextOrd = no;
320
+ }
321
+ }
322
+ const nextWD = p.peek();
323
+ if (nextWD === undefined || !(nextWD in EN_WEEKDAY)) {
324
+ throw new Error(`fromText: expected weekday name in BYDAY list, got '${nextWD}'`);
325
+ }
326
+ p.consume();
327
+ byDay.push({ weekday: EN_WEEKDAY[nextWD], ordinal: nextOrd });
328
+ }
329
+ }
330
+ /**
331
+ * Parse the content after 'on the': handles BYMONTHDAY, BYDAY ordinal,
332
+ * BYSETPOS=-1+Mon-Fri, and negative BYMONTHDAY patterns.
333
+ */
334
+ function parseOnThePart(p, opts) {
335
+ const next = p.peek();
336
+ if (next === undefined)
337
+ throw new Error("fromText: unexpected end after 'on the'");
338
+ // --- 'last ...' patterns ---
339
+ if (next === 'last') {
340
+ p.consume(); // 'last'
341
+ const after = p.peek();
342
+ if (after === 'day') {
343
+ p.consume();
344
+ opts.byMonthDay = [-1];
345
+ return;
346
+ }
347
+ if (after === 'weekday') {
348
+ p.consume();
349
+ opts.bySetPos = [-1];
350
+ opts.byDay = [...MON_TO_FRI];
351
+ return;
352
+ }
353
+ if (after !== undefined && after in EN_WEEKDAY) {
354
+ p.consume();
355
+ const byDay = [{ weekday: EN_WEEKDAY[after], ordinal: -1 }];
356
+ continueBydayOrdinalList(p, byDay);
357
+ opts.byDay = byDay;
358
+ return;
359
+ }
360
+ throw new Error(`fromText: expected 'day', 'weekday', or weekday name after 'last', got '${after}'`);
361
+ }
362
+ // --- Nth-to-last: either negative BYMONTHDAY ('2nd-to-last day')
363
+ // or negative ordinal BYDAY ('2nd-to-last Monday') ---
364
+ const negOrd = parseNegOrdinalToLast(next);
365
+ if (negOrd !== null) {
366
+ p.consume(); // 'Nth-to-last'
367
+ const nextTok = p.peek();
368
+ // Nth-to-last weekday: BYDAY with negative ordinal (e.g. '2nd-to-last Monday').
369
+ if (nextTok !== undefined && nextTok in EN_WEEKDAY) {
370
+ p.consume();
371
+ const byDay = [{ weekday: EN_WEEKDAY[nextTok], ordinal: negOrd }];
372
+ continueBydayOrdinalList(p, byDay);
373
+ opts.byDay = byDay;
374
+ return;
375
+ }
376
+ // Otherwise must be followed by 'day': negative BYMONTHDAY.
377
+ const dayToken = p.consume();
378
+ if (dayToken !== 'day') {
379
+ throw new Error(`fromText: expected 'day' or weekday name after neg-ordinal, got '${dayToken}'`);
380
+ }
381
+ const byMonthDay = [negOrd];
382
+ while (true) {
383
+ const saved = p.save();
384
+ if (!consumeListSeparator(p))
385
+ break;
386
+ const nextNeg = parseNegOrdinalToLast(p.peek() ?? '');
387
+ if (nextNeg === null) {
388
+ p.restore(saved);
389
+ break;
390
+ }
391
+ p.consume();
392
+ const d = p.consume();
393
+ if (d !== 'day')
394
+ throw new Error(`fromText: expected 'day' after neg-ordinal, got '${d}'`);
395
+ byMonthDay.push(nextNeg);
396
+ }
397
+ opts.byMonthDay = byMonthDay;
398
+ return;
399
+ }
400
+ // --- Positive ordinal: BYDAY ordinal or positive BYMONTHDAY ---
401
+ const ordinal = parseOrdinal(next);
402
+ if (ordinal === null) {
403
+ throw new Error(`fromText: expected 'last', 'Nth-to-last', or ordinal after 'on the', got '${next}'`);
404
+ }
405
+ p.consume();
406
+ const afterOrd = p.peek();
407
+ if (afterOrd !== undefined && afterOrd in EN_WEEKDAY) {
408
+ // BYDAY ordinal: 'on the Nth Weekday [and the Mth Weekday]*'
409
+ p.consume();
410
+ const byDay = [{ weekday: EN_WEEKDAY[afterOrd], ordinal }];
411
+ continueBydayOrdinalList(p, byDay);
412
+ opts.byDay = byDay;
413
+ return;
414
+ }
415
+ // BYMONTHDAY: 'on the Nth [and Mth]*'
416
+ const byMonthDay = [ordinal];
417
+ while (true) {
418
+ const saved = p.save();
419
+ if (!consumeListSeparator(p))
420
+ break;
421
+ const nextOrd = parseOrdinal(p.peek() ?? '');
422
+ if (nextOrd === null) {
423
+ p.restore(saved);
424
+ break;
425
+ }
426
+ p.consume();
427
+ byMonthDay.push(nextOrd);
428
+ }
429
+ opts.byMonthDay = byMonthDay;
430
+ }
431
+ function parseTimeList(p) {
432
+ const byHour = [];
433
+ let byMinute = undefined;
434
+ while (true) {
435
+ const token = p.peek();
436
+ if (token === undefined || !token.includes(':'))
437
+ break;
438
+ p.consume();
439
+ const colonIdx = token.indexOf(':');
440
+ const h = parseInt(token.slice(0, colonIdx), 10);
441
+ const m = parseInt(token.slice(colonIdx + 1), 10);
442
+ if (isNaN(h) || isNaN(m))
443
+ throw new Error(`fromText: invalid time token '${token}'`);
444
+ byHour.push(h);
445
+ if (m !== 0) {
446
+ // Non-zero minute: record it (overwrites previous if already set, but
447
+ // toText always uses the same minute for all hours).
448
+ byMinute = [m];
449
+ }
450
+ // Use lookahead to decide whether the separator belongs to the time list
451
+ // or to the COUNT terminator (', N times'). Only consume the separator
452
+ // when the token following it (possibly after 'and') is a time string.
453
+ const sep = p.peek();
454
+ if (sep === ',') {
455
+ const afterComma = p.peek(1);
456
+ if (afterComma === 'and') {
457
+ // Pattern: ', and H:MM'
458
+ const afterAnd = p.peek(2);
459
+ if (afterAnd === undefined || !afterAnd.includes(':'))
460
+ break;
461
+ p.consume(); // ','
462
+ p.consume(); // 'and'
463
+ }
464
+ else {
465
+ // Pattern: ', H:MM'
466
+ if (afterComma === undefined || !afterComma.includes(':'))
467
+ break;
468
+ p.consume(); // ','
469
+ }
470
+ }
471
+ else if (sep === 'and') {
472
+ const afterAnd = p.peek(1);
473
+ if (afterAnd === undefined || !afterAnd.includes(':'))
474
+ break;
475
+ p.consume(); // 'and'
476
+ }
477
+ else {
478
+ break;
479
+ }
480
+ }
481
+ if (byHour.length === 0)
482
+ throw new Error("fromText: expected time string after 'at'");
483
+ return { byHour, byMinute };
484
+ }
485
+ function parseUntilDate(p) {
486
+ const T = getTemporal();
487
+ const monthStr = p.consume();
488
+ const month = EN_MONTH_INDEX[monthStr];
489
+ if (month === undefined)
490
+ throw new Error(`fromText: expected month name in UNTIL, got '${monthStr}'`);
491
+ const dayStr = p.consume();
492
+ const day = parseInt(dayStr, 10);
493
+ if (isNaN(day))
494
+ throw new Error(`fromText: expected day number in UNTIL, got '${dayStr}'`);
495
+ p.consumeIf(',');
496
+ const yearStr = p.consume();
497
+ const year = parseInt(yearStr, 10);
498
+ if (isNaN(year))
499
+ throw new Error(`fromText: expected year in UNTIL, got '${yearStr}'`);
500
+ // Optional 'at H:MM' suffix indicates PlainDateTime.
501
+ if (p.peek() === 'at') {
502
+ p.consume();
503
+ const timeStr = p.consume();
504
+ if (!timeStr.includes(':')) {
505
+ throw new Error(`fromText: expected time string after 'at' in UNTIL, got '${timeStr}'`);
506
+ }
507
+ const colonIdx = timeStr.indexOf(':');
508
+ const hour = parseInt(timeStr.slice(0, colonIdx), 10);
509
+ const minute = parseInt(timeStr.slice(colonIdx + 1), 10);
510
+ if (isNaN(hour) || isNaN(minute)) {
511
+ throw new Error(`fromText: invalid time in UNTIL: '${timeStr}'`);
512
+ }
513
+ return T.PlainDateTime.from({ year, month, day, hour, minute });
514
+ }
515
+ return T.PlainDate.from({ year, month, day });
516
+ }
517
+ function parseSentence(p) {
518
+ // 1. Interval phrase: always present.
519
+ const { freq, interval } = parseIntervalPhrase(p);
520
+ const opts = { freq };
521
+ if (interval > 1)
522
+ opts.interval = interval;
523
+ // 2. Optional BYMONTH clause ('in ...').
524
+ if (p.peek() === 'in') {
525
+ p.consume();
526
+ opts.byMonth = parseMonthList(p);
527
+ }
528
+ // 3. Optional BYDAY or BYMONTHDAY clause ('on ...').
529
+ if (p.peek() === 'on') {
530
+ p.consume();
531
+ if (p.peek() === 'the') {
532
+ p.consume();
533
+ parseOnThePart(p, opts);
534
+ }
535
+ else {
536
+ opts.byDay = parsePlainWeekdayList(p);
537
+ }
538
+ }
539
+ // 4. Optional time clause ('at ...').
540
+ if (p.peek() === 'at') {
541
+ p.consume();
542
+ const { byHour, byMinute } = parseTimeList(p);
543
+ opts.byHour = byHour;
544
+ if (byMinute !== undefined)
545
+ opts.byMinute = byMinute;
546
+ }
547
+ // 5. Terminator: ', N times' (COUNT) or 'until date' (UNTIL).
548
+ if (p.peek() === ',') {
549
+ p.consume();
550
+ const numStr = p.consume();
551
+ const n = parseInt(numStr, 10);
552
+ if (isNaN(n) || n < 1)
553
+ throw new Error(`fromText: expected positive count, got '${numStr}'`);
554
+ const unit = p.consume();
555
+ if (unit !== 'time' && unit !== 'times') {
556
+ throw new Error(`fromText: expected 'time' or 'times' after count, got '${unit}'`);
557
+ }
558
+ opts.count = n;
559
+ }
560
+ else if (p.peek() === 'until') {
561
+ p.consume();
562
+ opts.until = parseUntilDate(p);
563
+ }
564
+ return opts;
565
+ }
566
+ // ---------------------------------------------------------------------------
567
+ // Public API
568
+ // ---------------------------------------------------------------------------
569
+ /**
570
+ * Parse a human-readable English recurrence description into RRuleOptions.
571
+ *
572
+ * Only accepts canonical output produced by toText with the EN locale. Not a
573
+ * general natural-language parser.
574
+ *
575
+ * Round-trip guarantee: for all RRuleOptions x where toText(x, {locale: en})
576
+ * does not return the complex-rule fallback string,
577
+ * fromText(toText(x, {locale: en}), {locale: en}).value deep-equals x
578
+ * (excluding dtstart, tzid, wkst, bySecond which are absent from text output,
579
+ * and excluding byMinute=[0] which is indistinguishable from byMinute=undefined
580
+ * in the rendered text).
581
+ *
582
+ * Returns Err if the text cannot be parsed as EN toText output.
583
+ *
584
+ * Out of scope: BYWEEKNO, BYYEARDAY, BYSECOND, WKST,
585
+ * multi-value BYSETPOS, free-form prose not produced by toText.
586
+ * fromText is EN-only: passing DE (or any other locale) text returns Err.
587
+ */
588
+ export function fromText(text) {
589
+ const tokens = tokenize(text.trim());
590
+ if (tokens.length === 0)
591
+ return err('fromText: empty input');
592
+ const p = new Parser(tokens);
593
+ try {
594
+ const result = parseSentence(p);
595
+ if (!p.isDone()) {
596
+ return err(`fromText: unexpected tokens after sentence end: '${p.peek()}'`);
597
+ }
598
+ return ok(result);
599
+ }
600
+ catch (e) {
601
+ return err(e instanceof Error ? e.message : String(e));
602
+ }
603
+ }
604
+ //# sourceMappingURL=fromText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromText.js","sourceRoot":"","sources":["../../src/text/fromText.ts"],"names":[],"mappings":"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"}