functionalscript 0.0.522 → 0.0.523

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.
@@ -6,7 +6,6 @@ const _range = require('../../types/range/module.f.cjs')
6
6
  const { one } = _range
7
7
  const { empty, stateScan, flat, toArray, reduce: listReduce, scan } = list
8
8
  const bigfloat = require('../../types/bigfloat/module.f.cjs')
9
- const jsonTokenizer = require('../../json/tokenizer/module.f.cjs')
10
9
  const { fromCharCode } = String
11
10
  const {
12
11
  range,
@@ -53,6 +52,32 @@ const {
53
52
  dollarSign
54
53
  } = require('../../text/ascii/module.f.cjs')
55
54
 
55
+ /**
56
+ * @typedef {{
57
+ * readonly kind: 'string'
58
+ * readonly value: string
59
+ * }} StringToken
60
+ * */
61
+
62
+ /**
63
+ * @typedef {{
64
+ * readonly kind: 'number'
65
+ * readonly value: string
66
+ * readonly bf: bigfloat.BigFloat
67
+ * }} NumberToken
68
+ * */
69
+
70
+ /**
71
+ * @typedef {{
72
+ * readonly kind: 'bigint'
73
+ * readonly value: bigint
74
+ * }} BigIntToken
75
+ * */
76
+
77
+ /** @typedef {{readonly kind: 'error', message: ErrorMessage}} ErrorToken */
78
+
79
+ /** @typedef {{readonly kind: '{' | '}' | ':' | ',' | '[' | ']' | 'true' | 'false' | 'null'}} SimpleToken */
80
+
56
81
  /**
57
82
  * @typedef {{
58
83
  * readonly kind: 'id'
@@ -62,8 +87,12 @@ const {
62
87
 
63
88
  /**
64
89
  * @typedef {|
65
- * jsonTokenizer.JsonToken |
66
- * IdToken
90
+ * SimpleToken |
91
+ * StringToken |
92
+ * NumberToken |
93
+ * ErrorToken |
94
+ * IdToken |
95
+ * BigIntToken
67
96
  * } FjsonToken
68
97
  */
69
98
 
@@ -117,12 +146,12 @@ const rangeId = [digitRange, ...rangeIdStart]
117
146
 
118
147
  /**
119
148
  * @typedef {|
120
- * 'invalid keyword' |
121
- * '" are missing' |
149
+ * '" are missing' |
122
150
  * 'unescaped character' |
123
151
  * 'invalid hex value' |
124
152
  * 'unexpected character' |
125
153
  * 'invalid number' |
154
+ * 'invalid token' |
126
155
  * 'eof'
127
156
  * } ErrorMessage
128
157
  */
@@ -147,7 +176,7 @@ const rangeId = [digitRange, ...rangeIdStart]
147
176
  /**
148
177
  * @typedef {{
149
178
  * readonly kind: 'number',
150
- * readonly numberKind: '0' | '-' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits'
179
+ * readonly numberKind: '0' | '-' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits' | 'bigint'
151
180
  * readonly value: string
152
181
  * readonly b: ParseNumberBuffer
153
182
  * }} ParseNumberState
@@ -252,8 +281,13 @@ const addFracDigit = digit => b => ({ ... b, m: b.m * 10n + digitToBigInt(digit)
252
281
  /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
253
282
  const addExpDigit = digit => b => ({ ... b, e: b.e * 10 + digit - digit0})
254
283
 
255
- /** @type {(s: ParseNumberState) => jsonTokenizer.NumberToken} */
256
- const bufferToNumberToken = ({value, b}) => ({ kind: 'number', value: value, bf: [b.s * b.m, b.f + b.es * b.e] })
284
+ /** @type {(s: ParseNumberState) => FjsonToken} */
285
+ const bufferToNumberToken = ({numberKind, value, b}) =>
286
+ {
287
+ if (numberKind === 'bigint')
288
+ return { kind: 'bigint', value: b.s * b.m }
289
+ return { kind: 'number', value: value, bf: [b.s * b.m, b.f + b.es * b.e] }
290
+ }
257
291
 
258
292
  /** @type {(state: InitialState) => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
259
293
  const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpected character' }], state])([
@@ -272,7 +306,11 @@ const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpe
272
306
  ])
273
307
 
274
308
  /** @type {() => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
275
- const invalidNumberToToken = () => input => tokenizeOp({ kind: 'invalidNumber' })(input)
309
+ const invalidNumberToToken = () => input =>
310
+ {
311
+ const next = tokenizeOp({ kind: 'initial' })(input)
312
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
313
+ }
276
314
 
277
315
  /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
278
316
  const fullStopToToken = state => input => {
@@ -358,6 +396,22 @@ const terminalToToken = state => input => {
358
396
  }
359
397
  }
360
398
 
399
+ /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
400
+ const bigintToToken = state => input => {
401
+ switch (state.numberKind) {
402
+ case '0':
403
+ case 'int':
404
+ {
405
+ return [empty, { kind: 'number', value: state.value, b: state.b, numberKind: 'bigint' }]
406
+ }
407
+ default:
408
+ {
409
+ const next = tokenizeOp({ kind: 'initial' })(input)
410
+ return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
411
+ }
412
+ }
413
+ }
414
+
361
415
  /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
362
416
  const parseNumberStateOp = create(invalidNumberToToken)([
363
417
  rangeFunc(one(fullStop))(fullStopToToken),
@@ -366,7 +420,8 @@ const parseNumberStateOp = create(invalidNumberToToken)([
366
420
  rangeSetFunc([one(latinSmallLetterE), one(latinCapitalLetterE)])(expToToken),
367
421
  rangeFunc(one(hyphenMinus))(hyphenMinusToToken),
368
422
  rangeFunc(one(plusSign))(plusSignToToken),
369
- rangeSetFunc(rangeSetTerminalForNumber)(terminalToToken)
423
+ rangeSetFunc(rangeSetTerminalForNumber)(terminalToToken),
424
+ rangeFunc(one(latinSmallLetterN))(bigintToToken),
370
425
  ])
371
426
 
372
427
  /** @type {(state: InvalidNumberState) => (input: number) => readonly[list.List<FjsonToken>, TokenizerState]} */
@@ -145,7 +145,7 @@ module.exports = {
145
145
  },
146
146
  () => {
147
147
  const result = stringify(tokenizeString('0abc,'))
148
- if (result !== '[{"kind":"error","message":"invalid number"},{"kind":","}]') { throw result }
148
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"abc"},{"kind":","}]') { throw result }
149
149
  },
150
150
  () => {
151
151
  const result = stringify(tokenizeString('123456789012345678901234567890'))
@@ -169,7 +169,7 @@ module.exports = {
169
169
  },
170
170
  () => {
171
171
  const result = stringify(tokenizeString('9a:'))
172
- if (result !== '[{"kind":"error","message":"invalid number"},{"kind":":"}]') { throw result }
172
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"a"},{"kind":":"}]') { throw result }
173
173
  },
174
174
  () => {
175
175
  const result = stringify(tokenizeString('-10'))
@@ -269,11 +269,39 @@ module.exports = {
269
269
  },
270
270
  () => {
271
271
  const result = stringify(tokenizeString('123_123'))
272
- if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
272
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"_123"}]') { throw result }
273
273
  },
274
- () => {
274
+ () => {
275
275
  const result = stringify(tokenizeString('123$123'))
276
- if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
276
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"$123"}]') { throw result }
277
+ },
278
+ () => {
279
+ const result = stringify(tokenizeString('1234567890n'))
280
+ if (result !== '[{"kind":"bigint","value":1234567890n}]') { throw result }
281
+ },
282
+ () => {
283
+ const result = stringify(tokenizeString('0n'))
284
+ if (result !== '[{"kind":"bigint","value":0n}]') { throw result }
285
+ },
286
+ () => {
287
+ const result = stringify(tokenizeString('[-1234567890n]'))
288
+ if (result !== '[{"kind":"["},{"kind":"bigint","value":-1234567890n},{"kind":"]"}]') { throw result }
289
+ },
290
+ () => {
291
+ const result = stringify(tokenizeString('123.456n'))
292
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"n"}]') { throw result }
293
+ },
294
+ () => {
295
+ const result = stringify(tokenizeString('123e456n'))
296
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"n"}]') { throw result }
297
+ },
298
+ () => {
299
+ const result = stringify(tokenizeString('1234567890na'))
300
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"a"}]') { throw result }
301
+ },
302
+ () => {
303
+ const result = stringify(tokenizeString('1234567890nn'))
304
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"n"}]') { throw result }
277
305
  },
278
306
  ]
279
307
  }
@@ -1,498 +1,38 @@
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
1
  const list = require('../../types/list/module.f.cjs')
5
- const _range = require('../../types/range/module.f.cjs')
6
- const { one } = _range
7
- const { empty, stateScan, flat, toArray, reduce: listReduce, scan } = list
8
- const bigfloat = require('../../types/bigfloat/module.f.cjs')
9
- const { fromCharCode } = String
10
- const {
11
- range,
12
- //
13
- backspace,
14
- ht,
15
- lf,
16
- ff,
17
- cr,
18
- //
19
- space,
20
- quotationMark,
21
- plusSign,
22
- comma,
23
- hyphenMinus,
24
- fullStop,
25
- solidus,
26
- //
27
- digitRange,
28
- digit0,
29
- colon,
30
- //
31
- latinCapitalLetterA,
32
- latinCapitalLetterE,
33
- //
34
- leftSquareBracket,
35
- reverseSolidus,
36
- rightSquareBracket,
37
- //
38
- latinSmallLetterRange,
39
- latinSmallLetterA,
40
- latinSmallLetterB,
41
- latinSmallLetterE,
42
- latinSmallLetterF,
43
- latinSmallLetterN,
44
- latinSmallLetterR,
45
- latinSmallLetterT,
46
- latinSmallLetterU,
47
- //
48
- leftCurlyBracket,
49
- rightCurlyBracket
50
- } = require('../../text/ascii/module.f.cjs')
51
-
52
- /**
53
- * @typedef {{
54
- * readonly kind: 'string'
55
- * readonly value: string
56
- * }} StringToken
57
- * */
58
-
59
- /**
60
- * @typedef {{
61
- * readonly kind: 'number'
62
- * readonly value: string
63
- * readonly bf: bigfloat.BigFloat
64
- * }} NumberToken
65
- * */
66
-
67
- /** @typedef {{readonly kind: 'error', message: ErrorMessage}} ErrorToken */
68
-
69
- /** @typedef {{readonly kind: '{' | '}' | ':' | ',' | '[' | ']' | 'true' | 'false' | 'null'}} SimpleToken */
70
-
71
- /**
72
- * @typedef {|
73
- * SimpleToken |
74
- * StringToken |
75
- * NumberToken |
76
- * ErrorToken
77
- * } JsonToken
78
- */
79
-
80
- const rangeOneNine = range('19')
81
-
82
- const rangeSetWhiteSpace = [
83
- one(ht),
84
- one(lf),
85
- one(cr),
86
- one(space)
87
- ]
88
-
89
- const rangeSetTerminalForNumber = [
90
- one(ht),
91
- one(lf),
92
- one(cr),
93
- one(space),
94
- one(quotationMark),
95
- one(comma),
96
- one(leftCurlyBracket),
97
- one(rightCurlyBracket),
98
- one(leftSquareBracket),
99
- one(rightSquareBracket),
100
- one(colon)
101
- ]
102
-
103
- const rangeSmallAF = range('af')
104
- const rangeCapitalAF = range('AF')
2
+ const fjsonTokenizer = require('../../fjson/tokenizer/module.f.cjs')
105
3
 
106
4
  /**
107
5
  * @typedef {|
108
- * InitialState |
109
- * ParseKeywordState |
110
- * ParseStringState |
111
- * ParseEscapeCharState |
112
- * ParseUnicodeCharState |
113
- * ParseNumberState |
114
- * InvalidNumberState |
115
- * EofState
116
- * } TokenizerState
117
- */
118
-
119
- /**
120
- * @typedef {|
121
- * 'invalid keyword' |
122
- * '" are missing' |
123
- * 'unescaped character' |
124
- * 'invalid hex value' |
125
- * 'unexpected character' |
126
- * 'invalid number' |
127
- * 'eof'
128
- * } ErrorMessage
129
- */
130
-
131
- /** @typedef {{ readonly kind: 'initial'}} InitialState */
132
-
133
- /** @typedef {{ readonly kind: 'keyword', readonly value: string}} ParseKeywordState */
134
-
135
- /** @typedef {{ readonly kind: 'string', readonly value: string}} ParseStringState */
136
-
137
- /** @typedef {{ readonly kind: 'escapeChar', readonly value: string}} ParseEscapeCharState */
138
-
139
- /**
140
- * @typedef {{
141
- * readonly kind: 'unicodeChar'
142
- * readonly value: string
143
- * readonly unicode: number
144
- * readonly hexIndex: number
145
- * }} ParseUnicodeCharState
146
- */
147
-
148
- /**
149
- * @typedef {{
150
- * readonly kind: 'number',
151
- * readonly numberKind: '0' | '-' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits'
152
- * readonly value: string
153
- * readonly b: ParseNumberBuffer
154
- * }} ParseNumberState
155
- */
156
-
157
- /**
158
- * @typedef {{
159
- * readonly s: -1n | 1n
160
- * readonly m: bigint
161
- * readonly f: number
162
- * readonly es: -1 | 1
163
- * readonly e: number
164
- * }} ParseNumberBuffer
6
+ * fjsonTokenizer.SimpleToken |
7
+ * fjsonTokenizer.StringToken |
8
+ * fjsonTokenizer.NumberToken |
9
+ * fjsonTokenizer.ErrorToken
10
+ * } JsonToken
165
11
  */
166
12
 
167
- /** @typedef {{ readonly kind: 'invalidNumber'}} InvalidNumberState */
168
-
169
- /** @typedef {{ readonly kind: 'eof'}} EofState */
170
-
171
- /** @typedef {number|null} CharCodeOrEof */
172
-
173
- /** @typedef {(input: number) => readonly[list.List<JsonToken>, TokenizerState]} ToToken */
174
-
175
- /**
176
- * @template T
177
- * @typedef {(state: T) => ToToken} CreateToToken<T>
178
- */
179
-
180
- /** @typedef {list.List<_range.Range>} RangeSet */
181
-
182
- /**
183
- * @template T
184
- * @typedef {(def: CreateToToken<T>) => (RangeMapToToken<T>)} RangeFunc<T>
185
- */
186
-
187
- /**
188
- * @template T
189
- * @typedef {range_map.RangeMapArray<CreateToToken<T>>} RangeMapToToken<T>
190
- */
191
-
192
- /** @type {(old: string) => (input: number) => string} */
193
- const appendChar = old => input => `${old}${fromCharCode(input)}`
194
-
195
- /** @type {<T>(def: CreateToToken<T>) => (a: CreateToToken<T>) => (b: CreateToToken<T>) => CreateToToken<T>} */
196
- const union = def => a => b => {
197
- if (a === def || a === b) { return b }
198
- if (b === def) { return a }
199
- throw [a, b]
200
- }
201
-
202
- /** @type {<T>(def: CreateToToken<T>) => range_map.RangeMerge<CreateToToken<T>>} */
203
- const rangeMapMerge = def => merge({
204
- union: union(def),
205
- equal: operator.strictEqual,
206
- })
207
-
208
- /** @type {<T>(r: _range.Range) => (f: CreateToToken<T>) => RangeFunc<T>} */
209
- const rangeFunc = r => f => def => fromRange(def)(r)(f)
210
-
211
- /** @type {<T>(def: CreateToToken<T>) => (operator.Scan<RangeFunc<T>, RangeMapToToken<T>>)} */
212
- const scanRangeOp = def => f => [f(def), scanRangeOp(def)]
213
-
214
- /** @type {<T>(def: CreateToToken<T>) => (a: list.List<RangeFunc<T>>) => RangeMapToToken<T>} */
215
- const reduceRangeMap = def => a => {
216
- const rm = scan(scanRangeOp(def))(a)
217
- return toArray(listReduce(rangeMapMerge(def))(empty)(rm))
218
- }
219
-
220
- /** @type {<T>(def: CreateToToken<T>) => (f: CreateToToken<T>) => (operator.Scan<_range.Range, RangeMapToToken<T>>)} */
221
- const scanRangeSetOp = def => f => r => [fromRange(def)(r)(f), scanRangeSetOp(def)(f)]
222
-
223
- /** @type {<T>(rs: list.List<_range.Range>) => (f: CreateToToken<T>) => RangeFunc<T>} */
224
- const rangeSetFunc = rs => f => def => {
225
- const rm = scan(scanRangeSetOp(def)(f))(rs)
226
- return toArray(listReduce(rangeMapMerge(def))(empty)(rm))
227
- }
228
-
229
- /** @type {<T>(def: CreateToToken<T>) => (a: list.List<RangeFunc<T>>) => CreateToToken<T>} */
230
- const create = def => a => {
231
- /** @typedef {typeof def extends CreateToToken<infer T> ? T : never} T */
232
- const i = reduceRangeMap(def)(a)
233
- /** @type {(v: number) => (i: RangeMapToToken<T>) => (v: T) => ToToken} */
234
- const x = get(def)
235
- return v => c => x(c)(i)(v)(c)
236
- }
237
-
238
- /** @type {(digit: number) => bigint} */
239
- const digitToBigInt = d => BigInt(d - digit0)
240
-
241
- /** @type {(digit: number) => ParseNumberBuffer} */
242
- const startNumber = digit => ({ s: 1n, m: digitToBigInt(digit), f: 0, es: 1, e: 0 })
243
-
244
- /** @type {ParseNumberBuffer} */
245
- const startNegativeNumber = { s: -1n, m: 0n, f: 0, es: 1, e: 0 }
246
-
247
- /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
248
- const addIntDigit = digit => b => ({ ... b, m: b.m * 10n + digitToBigInt(digit)})
249
-
250
- /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
251
- const addFracDigit = digit => b => ({ ... b, m: b.m * 10n + digitToBigInt(digit), f: b.f - 1})
252
-
253
- /** @type {(digit: number) => (b: ParseNumberBuffer) => ParseNumberBuffer} */
254
- const addExpDigit = digit => b => ({ ... b, e: b.e * 10 + digit - digit0})
255
-
256
- /** @type {(s: ParseNumberState) => NumberToken} */
257
- const bufferToNumberToken = ({value, b}) => ({ kind: 'number', value: value, bf: [b.s * b.m, b.f + b.es * b.e] })
258
-
259
- /** @type {(state: InitialState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
260
- const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpected character' }], state])([
261
- rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: 'int' }]),
262
- rangeFunc(latinSmallLetterRange)(() => input => [empty, { kind: 'keyword', value: fromCharCode(input) }]),
263
- rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
264
- rangeFunc(one(leftCurlyBracket))(state => () => [[{ kind: '{' }], state]),
265
- rangeFunc(one(rightCurlyBracket))(state => () => [[{ kind: '}' }], state]),
266
- rangeFunc(one(colon))(state => () => [[{ kind: ':' }], state]),
267
- rangeFunc(one(comma))(state => () => [[{ kind: ',' }], state]),
268
- rangeFunc(one(leftSquareBracket))(state => () => [[{ kind: '[' }], state]),
269
- rangeFunc(one(rightSquareBracket))(state => () => [[{ kind: ']' }], state]),
270
- rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
271
- rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: '0' }]),
272
- rangeFunc(one(hyphenMinus))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNegativeNumber, numberKind: '-' }])
273
- ])
274
-
275
- /** @type {() => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
276
- const invalidNumberToToken = () => input => tokenizeOp({ kind: 'invalidNumber' })(input)
277
-
278
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
279
- const fullStopToToken = state => input => {
280
- switch (state.numberKind) {
281
- case '0':
282
- case 'int': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: '.' }]
283
- default: return tokenizeOp({ kind: 'invalidNumber' })(input)
284
- }
285
- }
286
-
287
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
288
- const digit0ToToken = state => input => {
289
- switch (state.numberKind) {
290
- case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
291
- case '-': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: '0' }]
292
- case '.':
293
- case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addFracDigit(input)(state.b), numberKind: 'fractional' }]
294
- case 'e':
295
- case 'e+':
296
- case 'e-':
297
- case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addExpDigit(input)(state.b), numberKind: 'expDigits' }]
298
- default: return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addIntDigit(input)(state.b), numberKind: state.numberKind }]
299
- }
300
- }
301
-
302
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
303
- const digit19ToToken = state => input => {
304
- switch (state.numberKind) {
305
- case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
306
- case '.':
307
- case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addFracDigit(input)(state.b), numberKind: 'fractional' }]
308
- case 'e':
309
- case 'e+':
310
- case 'e-':
311
- case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addExpDigit(input)(state.b), numberKind: 'expDigits' }]
312
- default: return [empty, { kind: 'number', value: appendChar(state.value)(input), b: addIntDigit(input)(state.b), numberKind: 'int' }]
313
- }
314
- }
315
-
316
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
317
- const expToToken = state => input => {
318
- switch (state.numberKind) {
319
- case '0':
320
- case 'int':
321
- case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: 'e' }]
322
- default: return tokenizeOp({ kind: 'invalidNumber' })(input)
323
- }
324
- }
325
-
326
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
327
- const hyphenMinusToToken = state => input => {
328
- switch (state.numberKind) {
329
- case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: { ... state.b, es: -1}, numberKind: 'e-' }]
330
- default: return tokenizeOp({ kind: 'invalidNumber' })(input)
331
- }
332
- }
333
-
334
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
335
- const plusSignToToken = state => input => {
336
- switch (state.numberKind) {
337
- case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), b: state.b, numberKind: 'e+' }]
338
- default: return tokenizeOp({ kind: 'invalidNumber' })(input)
339
- }
340
- }
341
-
342
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
343
- const terminalToToken = state => input => {
344
- switch (state.numberKind) {
345
- case '-':
346
- case '.':
347
- case 'e':
348
- case 'e+':
349
- case 'e-':
350
- {
351
- const next = tokenizeOp({ kind: 'initial' })(input)
352
- return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
353
- }
354
- default:
355
- {
356
- const next = tokenizeOp({ kind: 'initial' })(input)
357
- return [{ first: bufferToNumberToken(state), tail: next[0] }, next[1]]
358
- }
359
- }
360
- }
361
-
362
- /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
363
- const parseNumberStateOp = create(invalidNumberToToken)([
364
- rangeFunc(one(fullStop))(fullStopToToken),
365
- rangeFunc(one(digit0))(digit0ToToken),
366
- rangeFunc(rangeOneNine)(digit19ToToken),
367
- rangeSetFunc([one(latinSmallLetterE), one(latinCapitalLetterE)])(expToToken),
368
- rangeFunc(one(hyphenMinus))(hyphenMinusToToken),
369
- rangeFunc(one(plusSign))(plusSignToToken),
370
- rangeSetFunc(rangeSetTerminalForNumber)(terminalToToken)
371
- ])
372
-
373
- /** @type {(state: InvalidNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
374
- const invalidNumberStateOp = create(() => () => [empty, { kind: 'invalidNumber' }])([
375
- rangeSetFunc(rangeSetTerminalForNumber)(() => input => {
376
- const next = tokenizeOp({ kind: 'initial' })(input)
377
- return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
378
- })
379
- ])
380
-
381
- /** @type {(state: ParseStringState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
382
- const parseStringStateOp = create(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }])([
383
- rangeFunc(one(quotationMark))(state => () => [[{ kind: 'string', value: state.value }], { kind: 'initial' }]),
384
- rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }])
385
- ])
386
-
387
- /** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
388
- const parseEscapeDefault = state => input => {
389
- const next = tokenizeOp({ kind: 'string', value: state.value })(input)
390
- return [{ first: { kind: 'error', message: 'unescaped character' }, tail: next[0] }, next[1]]
391
- }
392
-
393
- /** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
394
- const parseEscapeCharStateOp = create(parseEscapeDefault)([
395
- rangeSetFunc([one(quotationMark), one(reverseSolidus), one(solidus)])(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }]),
396
- rangeFunc(one(latinSmallLetterB))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(backspace) }]),
397
- rangeFunc(one(latinSmallLetterF))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ff) }]),
398
- rangeFunc(one(latinSmallLetterN))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(lf) }]),
399
- rangeFunc(one(latinSmallLetterR))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(cr) }]),
400
- rangeFunc(one(latinSmallLetterT))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ht) }]),
401
- rangeFunc(one(latinSmallLetterU))(state => () => [empty, { kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0 }]),
402
- ])
403
-
404
- /** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
405
- const parseUnicodeCharDefault = state => input => {
406
- const next = tokenizeOp({ kind: 'string', value: state.value })(input)
407
- return [{ first: { kind: 'error', message: 'invalid hex value' }, tail: next[0] }, next[1]]
408
- }
409
-
410
- /** @type {(offser: number) => (state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
411
- const parseUnicodeCharHex = offset => state => input => {
412
- const hexValue = input - offset
413
- const newUnicode = state.unicode | (hexValue << (3 - state.hexIndex) * 4)
414
- return [empty, state.hexIndex === 3 ?
415
- { kind: 'string', value: appendChar(state.value)(newUnicode) } :
416
- { kind: 'unicodeChar', value: state.value, unicode: newUnicode, hexIndex: state.hexIndex + 1 }]
417
- }
418
-
419
- /** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
420
- const parseUnicodeCharStateOp = create(parseUnicodeCharDefault)([
421
- rangeFunc(digitRange)(parseUnicodeCharHex(digit0)),
422
- rangeFunc(rangeSmallAF)(parseUnicodeCharHex(latinSmallLetterA - 10)),
423
- rangeFunc(rangeCapitalAF)(parseUnicodeCharHex(latinCapitalLetterA - 10))
424
- ])
425
-
426
- /** @type {(s: string) => JsonToken} */
427
- const stringToKeywordToken = s => {
428
- switch (s) {
429
- case 'true': return { kind: 'true' }
430
- case 'false': return { kind: 'false' }
431
- case 'null': return { kind: 'null' }
432
- default: return { kind: 'error', message: 'invalid keyword' }
13
+ /** @type {(input: fjsonTokenizer.FjsonToken) => JsonToken} */
14
+ const mapToken = input =>
15
+ {
16
+ switch(input.kind)
17
+ {
18
+ case "{":
19
+ case "}":
20
+ case ":":
21
+ case ",":
22
+ case "[":
23
+ case "]":
24
+ case "true":
25
+ case "false":
26
+ case "null":
27
+ case "string":
28
+ case "number":
29
+ case "error": return input
30
+ default: return { kind: "error", message: "invalid token" }
433
31
  }
434
32
  }
435
33
 
436
- /** @type {(state: ParseKeywordState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
437
- const parseKeyWordDefault = state => input => {
438
- const keyWordToken = stringToKeywordToken(state.value)
439
- const next = tokenizeOp({ kind: 'initial' })(input)
440
- return [{ first: keyWordToken, tail: next[0] }, next[1]]
441
- }
442
-
443
- /** @type {(state: ParseKeywordState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
444
- const parseKeyWordStateOp = create(parseKeyWordDefault)([
445
- rangeFunc(latinSmallLetterRange)(state => input => [empty, { kind: 'keyword', value: appendChar(state.value)(input) }])
446
- ])
447
-
448
- /** @type {(state: EofState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
449
- const eofStateOp = create(state => () => [[{ kind: 'error', message: 'eof' }], state])([])
450
-
451
- /** @type {operator.StateScan<number, TokenizerState, list.List<JsonToken>>} */
452
- const tokenizeCharCodeOp = state => {
453
- switch (state.kind) {
454
- case 'initial': return initialStateOp(state)
455
- case 'keyword': return parseKeyWordStateOp(state)
456
- case 'string': return parseStringStateOp(state)
457
- case 'escapeChar': return parseEscapeCharStateOp(state)
458
- case 'unicodeChar': return parseUnicodeCharStateOp(state)
459
- case 'invalidNumber': return invalidNumberStateOp(state)
460
- case 'number': return parseNumberStateOp(state)
461
- case 'eof': return eofStateOp(state)
462
- }
463
- }
464
-
465
- /** @type {(state: TokenizerState) => readonly[list.List<JsonToken>, TokenizerState]} */
466
- const tokenizeEofOp = state => {
467
- switch (state.kind) {
468
- case 'initial': return [empty, { kind: 'eof' }]
469
- case 'keyword': return [[stringToKeywordToken(state.value)], { kind: 'eof' }]
470
- case 'string':
471
- case 'escapeChar':
472
- case 'unicodeChar': return [[{ kind: 'error', message: '" are missing' }], { kind: 'eof' }]
473
- case 'invalidNumber': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof' }]
474
- case 'number':
475
- switch (state.numberKind) {
476
- case '-':
477
- case '.':
478
- case 'e':
479
- case 'e+':
480
- case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'invalidNumber', }]
481
- default: return [[bufferToNumberToken(state)], { kind: 'eof' }]
482
- }
483
- case 'eof': return [[{ kind: 'error', message: 'eof' }], state]
484
- }
485
- }
486
-
487
- /** @type {operator.StateScan<CharCodeOrEof, TokenizerState, list.List<JsonToken>>} */
488
- const tokenizeOp = state => input => input === null ? tokenizeEofOp(state) : tokenizeCharCodeOp(state)(input)
489
-
490
- const scanTokenize = stateScan(tokenizeOp)
491
-
492
- const initial = scanTokenize({ kind: 'initial' })
493
-
494
34
  /** @type {(input: list.List<number>) => list.List<JsonToken>} */
495
- const tokenize = input => flat(initial(flat([/** @type {list.List<CharCodeOrEof>} */(input), [null]])))
35
+ const tokenize = input => list.map(mapToken)(fjsonTokenizer.tokenize(input))
496
36
 
497
37
  module.exports = {
498
38
  /** @readonly */
@@ -45,11 +45,11 @@ module.exports = {
45
45
  },
46
46
  () => {
47
47
  const result = stringify(tokenizeString('err'))
48
- if (result !== '[{"kind":"error","message":"invalid keyword"}]') { throw result }
48
+ if (result !== '[{"kind":"error","message":"invalid token"}]') { throw result }
49
49
  },
50
50
  () => {
51
51
  const result = stringify(tokenizeString('{e}'))
52
- if (result !== '[{"kind":"{"},{"kind":"error","message":"invalid keyword"},{"kind":"}"}]') { throw result }
52
+ if (result !== '[{"kind":"{"},{"kind":"error","message":"invalid token"},{"kind":"}"}]') { throw result }
53
53
  },
54
54
  () => {
55
55
  const result = stringify(tokenizeString('{ \t\n\r}'))
@@ -61,7 +61,7 @@ module.exports = {
61
61
  },
62
62
  () => {
63
63
  const result = stringify(tokenizeString('tru'))
64
- if (result !== '[{"kind":"error","message":"invalid keyword"}]') { throw result }
64
+ if (result !== '[{"kind":"error","message":"invalid token"}]') { throw result }
65
65
  },
66
66
  () => {
67
67
  const result = stringify(tokenizeString('false'))
@@ -145,7 +145,7 @@ module.exports = {
145
145
  },
146
146
  () => {
147
147
  const result = stringify(tokenizeString('0abc,'))
148
- if (result !== '[{"kind":"error","message":"invalid number"},{"kind":","}]') { throw result }
148
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"error","message":"invalid token"},{"kind":","}]') { throw result }
149
149
  },
150
150
  () => {
151
151
  const result = stringify(tokenizeString('123456789012345678901234567890'))
@@ -169,7 +169,7 @@ module.exports = {
169
169
  },
170
170
  () => {
171
171
  const result = stringify(tokenizeString('9a:'))
172
- if (result !== '[{"kind":"error","message":"invalid number"},{"kind":":"}]') { throw result }
172
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"error","message":"invalid token"},{"kind":":"}]') { throw result }
173
173
  },
174
174
  () => {
175
175
  const result = stringify(tokenizeString('-10'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.522",
3
+ "version": "0.0.523",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {