functionalscript 0.0.523 → 0.0.524

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,688 @@
1
+ const operator = require('../../types/function/operator/module.f.cjs')
2
+ const range_map = require('../../types/range_map/module.f.cjs')
3
+ const { merge, fromRange, get } = range_map
4
+ const list = require('../../types/list/module.f.cjs')
5
+ const sorted_list = require('../../types/sorted_list/module.f.cjs')
6
+ const { unsafeCmp } = require('../../types/function/compare/module.f.cjs')
7
+ const _range = require('../../types/range/module.f.cjs')
8
+ const { one } = _range
9
+ const { empty, stateScan, flat, toArray, reduce: listReduce, scan } = list
10
+ const bigfloat = require('../../types/bigfloat/module.f.cjs')
11
+ const { fromCharCode } = String
12
+ const {
13
+ range,
14
+ //
15
+ backspace,
16
+ ht,
17
+ lf,
18
+ ff,
19
+ cr,
20
+ //
21
+ exclamationMark,
22
+ percentSign,
23
+ ampersand,
24
+ asterisk,
25
+ lessThanSign,
26
+ equalsSign,
27
+ greaterThanSign,
28
+ questionMark,
29
+ circumflexAccent,
30
+ verticalLine,
31
+ tilde,
32
+ //
33
+ space,
34
+ quotationMark,
35
+ plusSign,
36
+ comma,
37
+ hyphenMinus,
38
+ fullStop,
39
+ solidus,
40
+ //
41
+ digitRange,
42
+ digit0,
43
+ colon,
44
+ //
45
+ latinCapitalLetterRange,
46
+ latinCapitalLetterA,
47
+ latinCapitalLetterE,
48
+ //
49
+ leftSquareBracket,
50
+ reverseSolidus,
51
+ rightSquareBracket,
52
+ lowLine,
53
+ //
54
+ latinSmallLetterRange,
55
+ latinSmallLetterA,
56
+ latinSmallLetterB,
57
+ latinSmallLetterE,
58
+ latinSmallLetterF,
59
+ latinSmallLetterN,
60
+ latinSmallLetterR,
61
+ latinSmallLetterT,
62
+ latinSmallLetterU,
63
+ //
64
+ leftCurlyBracket,
65
+ rightCurlyBracket,
66
+ dollarSign
67
+ } = require('../../text/ascii/module.f.cjs')
68
+
69
+ /**
70
+ * @typedef {{
71
+ * readonly kind: 'string'
72
+ * readonly value: string
73
+ * }} StringToken
74
+ * */
75
+
76
+ /**
77
+ * @typedef {{
78
+ * readonly kind: 'number'
79
+ * readonly value: string
80
+ * readonly bf: bigfloat.BigFloat
81
+ * }} NumberToken
82
+ * */
83
+
84
+ /**
85
+ * @typedef {{
86
+ * readonly kind: 'bigint'
87
+ * readonly value: bigint
88
+ * }} BigIntToken
89
+ * */
90
+
91
+ /** @typedef {{readonly kind: 'error', message: ErrorMessage}} ErrorToken */
92
+
93
+ /** @typedef {{readonly kind: '{' | '}' | ':' | ',' | '[' | ']' | 'true' | 'false' | 'null'}} SimpleToken */
94
+
95
+ /**
96
+ * @typedef {{
97
+ * readonly kind: 'id'
98
+ * readonly value: string
99
+ * }} IdToken
100
+ * */
101
+
102
+ /**
103
+ * @typedef {|
104
+ * {readonly kind: '==' | '!=' | '===' | '!==' | '>' | '>=' | '<' | '<=' } |
105
+ * {readonly kind: '+' | '-' | '*' | '/' | '%' | '++' | '--' | '**' } |
106
+ * {readonly kind: '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '**='} |
107
+ * {readonly kind: '&' | '|' | '^' | '~' | '<<' | '>>' | '>>>' } |
108
+ * {readonly kind: '&=' | '|=' | '^=' | '<<=' | '>>=' | '>>>='} |
109
+ * {readonly kind: '&&' | '||' | '!' } |
110
+ * {readonly kind: '&&=' | '||=' | '??=' } |
111
+ * {readonly kind: '?' | '?.' | '.' | '=>'}
112
+ * } OperatorToken
113
+ */
114
+
115
+ /**
116
+ * @typedef {|
117
+ * SimpleToken |
118
+ * StringToken |
119
+ * NumberToken |
120
+ * ErrorToken |
121
+ * IdToken |
122
+ * BigIntToken |
123
+ * OperatorToken
124
+ * } JsToken
125
+ */
126
+
127
+ const rangeOneNine = range('19')
128
+
129
+ const rangeSetWhiteSpace = [
130
+ one(ht),
131
+ one(lf),
132
+ one(cr),
133
+ one(space)
134
+ ]
135
+
136
+ const rangeSetTerminalForNumber = [
137
+ one(ht),
138
+ one(lf),
139
+ one(cr),
140
+ one(space),
141
+ one(quotationMark),
142
+ one(comma),
143
+ one(leftCurlyBracket),
144
+ one(rightCurlyBracket),
145
+ one(leftSquareBracket),
146
+ one(rightSquareBracket),
147
+ one(colon)
148
+ ]
149
+
150
+ const rangeSmallAF = range('af')
151
+ const rangeCapitalAF = range('AF')
152
+
153
+ const rangeIdStart = [
154
+ latinSmallLetterRange,
155
+ latinCapitalLetterRange,
156
+ one(lowLine),
157
+ one(dollarSign)
158
+ ]
159
+
160
+ const rangeOpStart = [
161
+ one(exclamationMark),
162
+ one(percentSign),
163
+ one(ampersand),
164
+ one(asterisk),
165
+ one(lessThanSign),
166
+ one(equalsSign),
167
+ one(greaterThanSign),
168
+ one(questionMark),
169
+ one(circumflexAccent),
170
+ one(verticalLine),
171
+ one(tilde),
172
+ one(plusSign),
173
+ one(fullStop),
174
+ one(solidus)
175
+ ]
176
+
177
+ const rangeId = [digitRange, ...rangeIdStart]
178
+
179
+ /**
180
+ * @typedef {|
181
+ * InitialState |
182
+ * ParseIdState |
183
+ * ParseStringState |
184
+ * ParseEscapeCharState |
185
+ * ParseUnicodeCharState |
186
+ * ParseNumberState |
187
+ * InvalidNumberState |
188
+ * ParseOperatorState |
189
+ * ParseMinusState |
190
+ * EofState
191
+ * } TokenizerState
192
+ */
193
+
194
+ /**
195
+ * @typedef {|
196
+ * '" are missing' |
197
+ * 'unescaped character' |
198
+ * 'invalid hex value' |
199
+ * 'unexpected character' |
200
+ * 'invalid number' |
201
+ * 'invalid token' |
202
+ * 'eof'
203
+ * } ErrorMessage
204
+ */
205
+
206
+ /** @typedef {{ readonly kind: 'initial'}} InitialState */
207
+
208
+ /** @typedef {{ readonly kind: 'id', readonly value: string}} ParseIdState */
209
+
210
+ /** @typedef {{ readonly kind: 'string', readonly value: string}} ParseStringState */
211
+
212
+ /** @typedef {{ readonly kind: 'escapeChar', readonly value: string}} ParseEscapeCharState */
213
+
214
+ /** @typedef {{ readonly kind: 'op', readonly value: string}} ParseOperatorState */
215
+
216
+ /** @typedef {{ readonly kind: '-'}} ParseMinusState */
217
+
218
+ /**
219
+ * @typedef {{
220
+ * readonly kind: 'unicodeChar'
221
+ * readonly value: string
222
+ * readonly unicode: number
223
+ * readonly hexIndex: number
224
+ * }} ParseUnicodeCharState
225
+ */
226
+
227
+ /**
228
+ * @typedef {{
229
+ * readonly kind: 'number',
230
+ * readonly numberKind: '0' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits' | 'bigint'
231
+ * readonly value: string
232
+ * readonly b: ParseNumberBuffer
233
+ * }} ParseNumberState
234
+ */
235
+
236
+ /**
237
+ * @typedef {{
238
+ * readonly s: -1n | 1n
239
+ * readonly m: bigint
240
+ * readonly f: number
241
+ * readonly es: -1 | 1
242
+ * readonly e: number
243
+ * }} ParseNumberBuffer
244
+ */
245
+
246
+ /** @typedef {{ readonly kind: 'invalidNumber'}} InvalidNumberState */
247
+
248
+ /** @typedef {{ readonly kind: 'eof'}} EofState */
249
+
250
+ /** @typedef {number|null} CharCodeOrEof */
251
+
252
+ /** @typedef {(input: number) => readonly[list.List<JsToken>, TokenizerState]} ToToken */
253
+
254
+ /**
255
+ * @template T
256
+ * @typedef {(state: T) => ToToken} CreateToToken<T>
257
+ */
258
+
259
+ /** @typedef {list.List<_range.Range>} RangeSet */
260
+
261
+ /**
262
+ * @template T
263
+ * @typedef {(def: CreateToToken<T>) => (RangeMapToToken<T>)} RangeFunc<T>
264
+ */
265
+
266
+ /**
267
+ * @template T
268
+ * @typedef {range_map.RangeMapArray<CreateToToken<T>>} RangeMapToToken<T>
269
+ */
270
+
271
+ /** @type {(old: string) => (input: number) => string} */
272
+ const appendChar = old => input => `${old}${fromCharCode(input)}`
273
+
274
+ /** @type {<T>(def: CreateToToken<T>) => (a: CreateToToken<T>) => (b: CreateToToken<T>) => CreateToToken<T>} */
275
+ const union = def => a => b => {
276
+ if (a === def || a === b) { return b }
277
+ if (b === def) { return a }
278
+ throw [a, b]
279
+ }
280
+
281
+ /** @type {<T>(def: CreateToToken<T>) => range_map.RangeMerge<CreateToToken<T>>} */
282
+ const rangeMapMerge = def => merge({
283
+ union: union(def),
284
+ equal: operator.strictEqual,
285
+ })
286
+
287
+ /** @type {<T>(r: _range.Range) => (f: CreateToToken<T>) => RangeFunc<T>} */
288
+ const rangeFunc = r => f => def => fromRange(def)(r)(f)
289
+
290
+ /** @type {<T>(def: CreateToToken<T>) => (operator.Scan<RangeFunc<T>, RangeMapToToken<T>>)} */
291
+ const scanRangeOp = def => f => [f(def), scanRangeOp(def)]
292
+
293
+ /** @type {<T>(def: CreateToToken<T>) => (a: list.List<RangeFunc<T>>) => RangeMapToToken<T>} */
294
+ const reduceRangeMap = def => a => {
295
+ const rm = scan(scanRangeOp(def))(a)
296
+ return toArray(listReduce(rangeMapMerge(def))(empty)(rm))
297
+ }
298
+
299
+ /** @type {<T>(def: CreateToToken<T>) => (f: CreateToToken<T>) => (operator.Scan<_range.Range, RangeMapToToken<T>>)} */
300
+ const scanRangeSetOp = def => f => r => [fromRange(def)(r)(f), scanRangeSetOp(def)(f)]
301
+
302
+ /** @type {<T>(rs: list.List<_range.Range>) => (f: CreateToToken<T>) => RangeFunc<T>} */
303
+ const rangeSetFunc = rs => f => def => {
304
+ const rm = scan(scanRangeSetOp(def)(f))(rs)
305
+ return toArray(listReduce(rangeMapMerge(def))(empty)(rm))
306
+ }
307
+
308
+ /** @type {<T>(def: CreateToToken<T>) => (a: list.List<RangeFunc<T>>) => CreateToToken<T>} */
309
+ const create = def => a => {
310
+ /** @typedef {typeof def extends CreateToToken<infer T> ? T : never} T */
311
+ const i = reduceRangeMap(def)(a)
312
+ /** @type {(v: number) => (i: RangeMapToToken<T>) => (v: T) => ToToken} */
313
+ const x = get(def)
314
+ return v => c => x(c)(i)(v)(c)
315
+ }
316
+
317
+ /** @type {(digit: number) => bigint} */
318
+ const digitToBigInt = d => BigInt(d - digit0)
319
+
320
+ /** @type {(digit: number) => ParseNumberBuffer} */
321
+ const startNumber = digit => ({ s: 1n, m: digitToBigInt(digit), f: 0, es: 1, e: 0 })
322
+
323
+ /** @type {ParseNumberBuffer} */
324
+ const startNegativeNumber = { s: -1n, m: 0n, f: 0, es: 1, e: 0 }
325
+
326
+ /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
327
+ const addIntDigit = digit => b => ({ ... b, m: b.m * 10n + digitToBigInt(digit)})
328
+
329
+ /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
330
+ const addFracDigit = digit => b => ({ ... b, m: b.m * 10n + digitToBigInt(digit), f: b.f - 1})
331
+
332
+ /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
333
+ const addExpDigit = digit => b => ({ ... b, e: b.e * 10 + digit - digit0})
334
+
335
+ /** @type {(s: ParseNumberState) => JsToken} */
336
+ const bufferToNumberToken = ({numberKind, value, b}) =>
337
+ {
338
+ if (numberKind === 'bigint')
339
+ return { kind: 'bigint', value: b.s * b.m }
340
+ return { kind: 'number', value: value, bf: [b.s * b.m, b.f + b.es * b.e] }
341
+ }
342
+
343
+ /**
344
+ * @typedef {{
345
+ * readonly transitions: sorted_list.SortedArray<number>,
346
+ * readonly token: JsToken
347
+ * }} OperatorTransition
348
+ */
349
+
350
+ /**
351
+ * @typedef {{
352
+ * readonly[state in string]: OperatorTransition
353
+ * }} OperatorDfa
354
+ */
355
+
356
+ /** @type {OperatorDfa} */
357
+ const operatorDfa = {
358
+ '!' : { token: { kind: '!' }, transitions: [equalsSign]},
359
+ '!=' : { token: { kind: '!=' }, transitions: [equalsSign]},
360
+ '!==': { token: { kind: '!=='}, transitions: []},
361
+ '%' : { token: { kind: '%' }, transitions: [equalsSign]},
362
+ '%=' : { token: { kind: '%=' }, transitions: []},
363
+ '&' : { token: { kind: '&' }, transitions: [ampersand, equalsSign]},
364
+ '&&' : { token: { kind: '&&' }, transitions: [equalsSign]},
365
+ '&&=' : { token: { kind: '&&=' }, transitions: []},
366
+ '&=' : { token: { kind: '&=' }, transitions: []},
367
+ '*' : { token: { kind: '*' }, transitions: [asterisk, equalsSign]},
368
+ '**' : { token: { kind: '**' }, transitions: [equalsSign]},
369
+ '**=' : { token: { kind: '**=' }, transitions: []},
370
+ '*=' : { token: { kind: '*=' }, transitions: []},
371
+ '+' : { token: { kind: '+' }, transitions: [plusSign, equalsSign]},
372
+ '++' : { token: { kind: '++' }, transitions: []},
373
+ '+=' : { token: { kind: '+=' }, transitions: []},
374
+ '-' : { token: { kind: '-' }, transitions: [hyphenMinus, equalsSign]},
375
+ '--' : { token: { kind: '--' }, transitions: []},
376
+ '-=' : { token: { kind: '-=' }, transitions: []},
377
+ '.' : { token: { kind: '.' }, transitions: []},
378
+ '/' : { token: { kind: '/' }, transitions: [equalsSign]},
379
+ '/=' : { token: { kind: '/=' }, transitions: []},
380
+ '<' : { token: { kind: '<' }, transitions: [lessThanSign, equalsSign]},
381
+ '<<' : { token: { kind: '<<' }, transitions: [equalsSign]},
382
+ '<<=': { token: { kind: '<<='}, transitions: []},
383
+ '<=': {token: {kind: '<='}, transitions: []},
384
+ '=' : { token: { kind: '=' }, transitions: [equalsSign, greaterThanSign]},
385
+ '==' : { token: { kind: '==' }, transitions: [equalsSign]},
386
+ '===': { token: { kind: '==='}, transitions: []},
387
+ '=>': {token: {kind: '=>'}, transitions: []},
388
+ '>' : { token: { kind: '>' }, transitions: [equalsSign, greaterThanSign]},
389
+ '>=' : { token: { kind: '>=' }, transitions: []},
390
+ '>>': { token: { kind: '>>'}, transitions: [equalsSign, greaterThanSign]},
391
+ '>>=': {token: {kind: '>>='}, transitions: []},
392
+ '>>>': {token: {kind: '>>>'}, transitions: [equalsSign]},
393
+ '>>>=': {token: {kind: '>>>='}, transitions: []},
394
+ '?' : { token: { kind: '?' }, transitions: [fullStop, questionMark]},
395
+ '?.' : { token: { kind: '?.' }, transitions: []},
396
+ '??' : { token: { kind: 'error', message: 'invalid token' }, transitions: [equalsSign]},
397
+ '??=' : { token: { kind: '??=' }, transitions: []},
398
+ '^' : { token: { kind: '^' }, transitions: [equalsSign]},
399
+ '^=' : { token: { kind: '^=' }, transitions: []},
400
+ '|' : { token: { kind: '|' }, transitions: [equalsSign, verticalLine]},
401
+ '|=' : { token: { kind: '|=' }, transitions: []},
402
+ '||' : { token: { kind: '||' }, transitions: [equalsSign]},
403
+ '||=' : { token: { kind: '||=' }, transitions: []},
404
+ '~' : { token: { kind: '~' }, transitions: []}
405
+ }
406
+
407
+ /** @type {(state: InitialState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
408
+ const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpected character' }], state])([
409
+ rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: 'int' }]),
410
+ rangeSetFunc(rangeIdStart)(() => input => [empty, { kind: 'id', value: fromCharCode(input) }]),
411
+ rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
412
+ rangeFunc(one(leftCurlyBracket))(state => () => [[{ kind: '{' }], state]),
413
+ rangeFunc(one(rightCurlyBracket))(state => () => [[{ kind: '}' }], state]),
414
+ rangeFunc(one(colon))(state => () => [[{ kind: ':' }], state]),
415
+ rangeFunc(one(comma))(state => () => [[{ kind: ',' }], state]),
416
+ rangeFunc(one(leftSquareBracket))(state => () => [[{ kind: '[' }], state]),
417
+ rangeFunc(one(rightSquareBracket))(state => () => [[{ kind: ']' }], state]),
418
+ rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
419
+ rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: '0' }]),
420
+ rangeFunc(one(hyphenMinus))(() => () => [empty, { kind: '-'}]),
421
+ rangeSetFunc(rangeOpStart)(() => input => [empty, { kind: 'op', value: fromCharCode(input) }])
422
+ ])
423
+
424
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
425
+ const invalidNumberToToken = state => input =>
426
+ {
427
+ const next = tokenizeOp({ kind: 'initial' })(input)
428
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
429
+ }
430
+
431
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
432
+ const fullStopToToken = state => input => {
433
+ switch (state.numberKind) {
434
+ case '0':
435
+ case 'int': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: '.' }]
436
+ default: return tokenizeOp({ kind: 'invalidNumber' })(input)
437
+ }
438
+ }
439
+
440
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
441
+ const digit0ToToken = state => input => {
442
+ switch (state.numberKind) {
443
+ case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
444
+ case '.':
445
+ case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addFracDigit(input)(state.b), numberKind: 'fractional' }]
446
+ case 'e':
447
+ case 'e+':
448
+ case 'e-':
449
+ case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addExpDigit(input)(state.b), numberKind: 'expDigits' }]
450
+ default: return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addIntDigit(input)(state.b), numberKind: state.numberKind }]
451
+ }
452
+ }
453
+
454
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
455
+ const digit19ToToken = state => input => {
456
+ switch (state.numberKind) {
457
+ case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
458
+ case '.':
459
+ case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addFracDigit(input)(state.b), numberKind: 'fractional' }]
460
+ case 'e':
461
+ case 'e+':
462
+ case 'e-':
463
+ case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addExpDigit(input)(state.b), numberKind: 'expDigits' }]
464
+ default: return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addIntDigit(input)(state.b), numberKind: 'int' }]
465
+ }
466
+ }
467
+
468
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
469
+ const expToToken = state => input => {
470
+ switch (state.numberKind) {
471
+ case '0':
472
+ case 'int':
473
+ case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: 'e' }]
474
+ default: return tokenizeOp({ kind: 'invalidNumber' })(input)
475
+ }
476
+ }
477
+
478
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
479
+ const hyphenMinusToToken = state => input => {
480
+ switch (state.numberKind) {
481
+ case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: { ... state.b, es: -1}, numberKind: 'e-' }]
482
+ default: return tokenizeOp({ kind: 'invalidNumber' })(input)
483
+ }
484
+ }
485
+
486
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
487
+ const plusSignToToken = state => input => {
488
+ switch (state.numberKind) {
489
+ case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: 'e+' }]
490
+ default: return tokenizeOp({ kind: 'invalidNumber' })(input)
491
+ }
492
+ }
493
+
494
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
495
+ const terminalToToken = state => input => {
496
+ switch (state.numberKind) {
497
+ case '.':
498
+ case 'e':
499
+ case 'e+':
500
+ case 'e-':
501
+ {
502
+ const next = tokenizeOp({ kind: 'initial' })(input)
503
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
504
+ }
505
+ default:
506
+ {
507
+ const next = tokenizeOp({ kind: 'initial' })(input)
508
+ return [{ first: bufferToNumberToken(state), tail: next[0] }, next[1]]
509
+ }
510
+ }
511
+ }
512
+
513
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
514
+ const bigintToToken = state => input => {
515
+ switch (state.numberKind) {
516
+ case '0':
517
+ case 'int':
518
+ {
519
+ return [empty, { kind: 'number', value: state.value, b: state.b, numberKind: 'bigint' }]
520
+ }
521
+ default:
522
+ {
523
+ const next = tokenizeOp({ kind: 'initial' })(input)
524
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
525
+ }
526
+ }
527
+ }
528
+
529
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
530
+ const parseNumberStateOp = create(invalidNumberToToken)([
531
+ rangeFunc(one(fullStop))(fullStopToToken),
532
+ rangeFunc(one(digit0))(digit0ToToken),
533
+ rangeFunc(rangeOneNine)(digit19ToToken),
534
+ rangeSetFunc([one(latinSmallLetterE), one(latinCapitalLetterE)])(expToToken),
535
+ rangeFunc(one(hyphenMinus))(hyphenMinusToToken),
536
+ rangeFunc(one(plusSign))(plusSignToToken),
537
+ rangeSetFunc(rangeSetTerminalForNumber)(terminalToToken),
538
+ rangeFunc(one(latinSmallLetterN))(bigintToToken),
539
+ ])
540
+
541
+ /** @type {(state: InvalidNumberState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
542
+ const invalidNumberStateOp = create(() => () => [empty, { kind: 'invalidNumber' }])([
543
+ rangeSetFunc(rangeSetTerminalForNumber)(() => input => {
544
+ const next = tokenizeOp({ kind: 'initial' })(input)
545
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
546
+ })
547
+ ])
548
+
549
+ /** @type {(state: ParseMinusState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
550
+ const parseMinusStateOp = create(() => input => tokenizeOp({ kind: 'op', value: '-' })(input))([
551
+ rangeFunc(one(fullStop))(() => input => tokenizeOp({ kind: 'invalidNumber' })(input)),
552
+ rangeFunc(one(digit0))(() => () => [empty, { kind: 'number', value: '-0', b: startNegativeNumber, numberKind: '0' }]),
553
+ rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: appendChar('-')(input), b: addIntDigit(input)(startNegativeNumber), numberKind: 'int' }]),
554
+ ])
555
+
556
+ /** @type {(state: ParseStringState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
557
+ const parseStringStateOp = create(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }])([
558
+ rangeFunc(one(quotationMark))(state => () => [[{ kind: 'string', value: state.value }], { kind: 'initial' }]),
559
+ rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }])
560
+ ])
561
+
562
+ /** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
563
+ const parseEscapeDefault = state => input => {
564
+ const next = tokenizeOp({ kind: 'string', value: state.value })(input)
565
+ return [{ first: { kind: 'error', message: 'unescaped character' }, tail: next[0] }, next[1]]
566
+ }
567
+
568
+ /** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
569
+ const parseEscapeCharStateOp = create(parseEscapeDefault)([
570
+ rangeSetFunc([one(quotationMark), one(reverseSolidus), one(solidus)])(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }]),
571
+ rangeFunc(one(latinSmallLetterB))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(backspace) }]),
572
+ rangeFunc(one(latinSmallLetterF))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ff) }]),
573
+ rangeFunc(one(latinSmallLetterN))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(lf) }]),
574
+ rangeFunc(one(latinSmallLetterR))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(cr) }]),
575
+ rangeFunc(one(latinSmallLetterT))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ht) }]),
576
+ rangeFunc(one(latinSmallLetterU))(state => () => [empty, { kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0 }]),
577
+ ])
578
+
579
+ /** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
580
+ const parseUnicodeCharDefault = state => input => {
581
+ const next = tokenizeOp({ kind: 'string', value: state.value })(input)
582
+ return [{ first: { kind: 'error', message: 'invalid hex value' }, tail: next[0] }, next[1]]
583
+ }
584
+
585
+ /** @type {(offser: number) => (state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
586
+ const parseUnicodeCharHex = offset => state => input => {
587
+ const hexValue = input - offset
588
+ const newUnicode = state.unicode | (hexValue << (3 - state.hexIndex) * 4)
589
+ return [empty, state.hexIndex === 3 ?
590
+ { kind: 'string', value: appendChar(state.value)(newUnicode) } :
591
+ { kind: 'unicodeChar', value: state.value, unicode: newUnicode, hexIndex: state.hexIndex + 1 }]
592
+ }
593
+
594
+ /** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
595
+ const parseUnicodeCharStateOp = create(parseUnicodeCharDefault)([
596
+ rangeFunc(digitRange)(parseUnicodeCharHex(digit0)),
597
+ rangeFunc(rangeSmallAF)(parseUnicodeCharHex(latinSmallLetterA - 10)),
598
+ rangeFunc(rangeCapitalAF)(parseUnicodeCharHex(latinCapitalLetterA - 10))
599
+ ])
600
+
601
+ /** @type {(s: string) => JsToken} */
602
+ const idToToken = s => {
603
+ switch (s) {
604
+ case 'true': return { kind: 'true' }
605
+ case 'false': return { kind: 'false' }
606
+ case 'null': return { kind: 'null' }
607
+ default: return { kind: 'id', value: s }
608
+ }
609
+ }
610
+
611
+ /** @type {(state: ParseIdState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
612
+ const parseIdDefault = state => input => {
613
+ const keyWordToken = idToToken(state.value)
614
+ const next = tokenizeOp({ kind: 'initial' })(input)
615
+ return [{ first: keyWordToken, tail: next[0] }, next[1]]
616
+ }
617
+
618
+ /** @type {(state: ParseIdState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
619
+ const parseIdStateOp = create(parseIdDefault)([
620
+ rangeSetFunc(rangeId)(state => input => [empty, { kind: 'id', value: appendChar(state.value)(input) }])
621
+ ])
622
+
623
+ /** @type {(state: ParseOperatorState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
624
+ const parseOperatorStateOp = state => input => {
625
+ const r = operatorDfa[state.value]
626
+ const t = sorted_list.find(unsafeCmp)(input)(r.transitions)
627
+ if (t !== null)
628
+ return [empty, { kind: 'op', value: appendChar(state.value)(input) }]
629
+ const next = tokenizeOp({ kind: 'initial' })(input)
630
+ return [{ first: r.token, tail: next[0] }, next[1]]
631
+ }
632
+
633
+ /** @type {(state: EofState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
634
+ const eofStateOp = create(state => () => [[{ kind: 'error', message: 'eof' }], state])([])
635
+
636
+ /** @type {operator.StateScan<number, TokenizerState, list.List<JsToken>>} */
637
+ const tokenizeCharCodeOp = state => {
638
+ switch (state.kind) {
639
+ case 'initial': return initialStateOp(state)
640
+ case 'id': return parseIdStateOp(state)
641
+ case 'string': return parseStringStateOp(state)
642
+ case 'escapeChar': return parseEscapeCharStateOp(state)
643
+ case 'unicodeChar': return parseUnicodeCharStateOp(state)
644
+ case 'invalidNumber': return invalidNumberStateOp(state)
645
+ case 'number': return parseNumberStateOp(state)
646
+ case 'op': return parseOperatorStateOp(state)
647
+ case '-': return parseMinusStateOp(state)
648
+ case 'eof': return eofStateOp(state)
649
+ }
650
+ }
651
+
652
+ /** @type {(state: TokenizerState) => readonly[list.List<JsToken>, TokenizerState]} */
653
+ const tokenizeEofOp = state => {
654
+ switch (state.kind) {
655
+ case 'initial': return [empty, { kind: 'eof' }]
656
+ case 'id': return [[idToToken(state.value)], { kind: 'eof' }]
657
+ case 'string':
658
+ case 'escapeChar':
659
+ case 'unicodeChar': return [[{ kind: 'error', message: '" are missing' }], { kind: 'eof' }]
660
+ case 'invalidNumber': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof' }]
661
+ case 'number':
662
+ switch (state.numberKind) {
663
+ case '.':
664
+ case 'e':
665
+ case 'e+':
666
+ case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'invalidNumber', }]
667
+ default: return [[bufferToNumberToken(state)], { kind: 'eof' }]
668
+ }
669
+ case 'op': return [[operatorDfa[state.value].token], { kind: 'eof' }]
670
+ case '-': return [[{kind: '-'}], { kind: 'eof' }]
671
+ case 'eof': return [[{ kind: 'error', message: 'eof' }], state]
672
+ }
673
+ }
674
+
675
+ /** @type {operator.StateScan<CharCodeOrEof, TokenizerState, list.List<JsToken>>} */
676
+ const tokenizeOp = state => input => input === null ? tokenizeEofOp(state) : tokenizeCharCodeOp(state)(input)
677
+
678
+ const scanTokenize = stateScan(tokenizeOp)
679
+
680
+ const initial = scanTokenize({ kind: 'initial' })
681
+
682
+ /** @type {(input: list.List<number>) => list.List<JsToken>} */
683
+ const tokenize = input => flat(initial(flat([/** @type {list.List<CharCodeOrEof>} */(input), [null]])))
684
+
685
+ module.exports = {
686
+ /** @readonly */
687
+ tokenize
688
+ }