rrule-ts 0.2.0 → 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.
- package/README.md +24 -0
- package/dist/expand.d.ts.map +1 -1
- package/dist/expand.js +95 -11
- package/dist/expand.js.map +1 -1
- package/dist/locales/de.d.ts +8 -4
- package/dist/locales/de.d.ts.map +1 -1
- package/dist/locales/de.js +126 -26
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +7 -26
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/en.js +166 -26
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/types.d.ts +113 -0
- package/dist/locales/types.d.ts.map +1 -0
- package/dist/locales/types.js +7 -0
- package/dist/locales/types.js.map +1 -0
- package/dist/text/fromText.d.ts +23 -0
- package/dist/text/fromText.d.ts.map +1 -0
- package/dist/text/fromText.js +604 -0
- package/dist/text/fromText.js.map +1 -0
- package/dist/text/index.d.ts +58 -13
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.js +56 -16
- package/dist/text/index.js.map +1 -1
- package/dist/text/toText.d.ts +20 -0
- package/dist/text/toText.d.ts.map +1 -0
- package/dist/text/toText.js +230 -0
- package/dist/text/toText.js.map +1 -0
- package/package.json +1 -1
|
@@ -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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"}
|