functionalscript 0.0.325 → 0.0.329

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,405 @@
1
+ const { todo } = require('../../dev')
2
+ const operator = require('../../types/function/operator')
3
+ const { concat } = require('../../types/list')
4
+ const list = require('../../types/list')
5
+
6
+ /**
7
+ * @typedef {{
8
+ * readonly kind: 'string'
9
+ * readonly value: string
10
+ * }} StringToken
11
+ * */
12
+
13
+ /**
14
+ * @typedef {{
15
+ * readonly kind: 'number'
16
+ * readonly value: string
17
+ * }} NumberToken
18
+ * */
19
+
20
+ /** @typedef {{readonly kind: 'error', message: ErrorMessage}} ErrorToken */
21
+
22
+ /** @typedef {{readonly kind: '{' | '}' | ':' | ',' | '[' | ']' | 'true' | 'false' | 'null'}} SimpleToken */
23
+
24
+ /**
25
+ * @typedef {|
26
+ * SimpleToken |
27
+ * StringToken |
28
+ * NumberToken |
29
+ * ErrorToken
30
+ * } JsonToken
31
+ */
32
+
33
+ const leftBrace = 0x7b
34
+ const rightBrace = 0x7d
35
+ const colon = 0x3a
36
+ const comma = 0x2c
37
+ const leftBracket = 0x5b
38
+ const rightBracket = 0x5d
39
+
40
+ const quotationMark = 0x22
41
+ const digit0 = 0x30
42
+ const digit1 = 0x31
43
+ const digit9 = 0x39
44
+ const signPlus = 0x2b
45
+ const signMinus = 0x2d
46
+ const decimalPoint = 0x2e
47
+
48
+ const horizontalTab = 0x09
49
+ const newLine = 0x0a
50
+ const carriageReturn = 0x0d
51
+ const space = 0x20
52
+
53
+ const backslach = 0x5c
54
+ const slash = 0x2f
55
+ const backspace = 0x08
56
+ const formfeed = 0x0c
57
+
58
+ const capitalLetterA = 0x41
59
+ const capitalLetterE = 0x45
60
+ const capitalLetterF = 0x46
61
+
62
+ const letterA = 0x61
63
+ const letterB = 0x62
64
+ const letterE = 0x65
65
+ const letterF = 0x66
66
+ const letterN = 0x6e
67
+ const letterR = 0x72
68
+ const letterT = 0x74
69
+ const letterU = 0x75
70
+ const letterZ = 0x7a
71
+
72
+ /**
73
+ * @typedef {|
74
+ * InitialState |
75
+ * ParseKeywordState |
76
+ * ParseStringState |
77
+ * ParseEscapeCharState |
78
+ * ParseUnicodeCharState |
79
+ * ParseNumberState |
80
+ * InvalidNumberState |
81
+ * EofState
82
+ * } TokenizerState
83
+ */
84
+
85
+ /**
86
+ * @typedef {|
87
+ * 'invalid keyword' |
88
+ * '" are missing' |
89
+ * 'unescaped character' |
90
+ * 'invalid hex value' |
91
+ * 'unexpected character' |
92
+ * 'invalid number' |
93
+ * 'eof'
94
+ * } ErrorMessage
95
+ */
96
+
97
+ /** @typedef {{ readonly kind: 'initial'}} InitialState */
98
+
99
+ /** @typedef {{ readonly kind: 'keyword', readonly value: string}} ParseKeywordState */
100
+
101
+ /** @typedef {{ readonly kind: 'string', readonly value: string}} ParseStringState */
102
+
103
+ /** @typedef {{ readonly kind: 'escapeChar', readonly value: string}} ParseEscapeCharState */
104
+
105
+ /** @typedef {{ readonly kind: 'unicodeChar', readonly value: string, readonly unicode: number, readonly hexIndex: number}} ParseUnicodeCharState */
106
+
107
+ /**
108
+ * @typedef {{
109
+ * readonly kind: 'number',
110
+ * readonly numberKind: '0' | '-' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits'
111
+ * readonly value: string
112
+ * }} ParseNumberState
113
+ * */
114
+
115
+ /** @typedef {{ readonly kind: 'invalidNumber'}} InvalidNumberState */
116
+
117
+ /** @typedef {{ readonly kind: 'eof'}} EofState */
118
+
119
+ /** @typedef {number|undefined} JsonCharacter */
120
+
121
+ /** @type {(old: string) => (input: JsonCharacter) => string} */
122
+ const appendChar = old => input => input === undefined ? old : operator.concat(charToString(input))(old)
123
+
124
+ /** @type {(input: JsonCharacter) => string} */
125
+ const charToString = input => input === undefined ? '' : String.fromCharCode(input)
126
+
127
+ /** @type {(state: InitialState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
128
+ const initialStateOp = initialState => input =>
129
+ {
130
+ if (input === undefined)
131
+ {
132
+ return[undefined, {kind: 'eof'}]
133
+ }
134
+ if (input >= digit1 && input <= digit9)
135
+ {
136
+ return [undefined, { kind: 'number', value: charToString(input), numberKind: 'int'}]
137
+ }
138
+ if (input >= letterA && input <= letterZ)
139
+ {
140
+ return [undefined, { kind: 'keyword', value: charToString(input)}]
141
+ }
142
+ switch(input)
143
+ {
144
+ case leftBrace: return [[{kind: '{'}], initialState]
145
+ case rightBrace: return [[{kind: '}'}], initialState]
146
+ case colon: return [[{kind: ':'}], initialState]
147
+ case comma: return [[{kind: ','}], initialState]
148
+ case leftBracket: return [[{kind: '['}], initialState]
149
+ case rightBracket: return [[{kind: ']'}], initialState]
150
+ case quotationMark: return[undefined, {kind: 'string', value: ''}]
151
+ case digit0: return [undefined, { kind: 'number', value: charToString(input), numberKind: '0'}]
152
+ case signMinus: return [undefined, { kind: 'number', value: charToString(input), numberKind: '-'}]
153
+ case horizontalTab:
154
+ case newLine:
155
+ case carriageReturn:
156
+ case space: return[undefined, initialState]
157
+ default: return [[{kind: 'error', message: 'unexpected character'}], initialState]
158
+ }
159
+ }
160
+
161
+ /** @type {(state: ParseNumberState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
162
+ const parseNumberStateOp = state => input =>
163
+ {
164
+ if (input === undefined)
165
+ {
166
+ switch (state.numberKind)
167
+ {
168
+ case '-':
169
+ case '.':
170
+ case 'e':
171
+ case 'e+':
172
+ case 'e-': return [[{kind: 'error', message: 'invalid number'}], {kind: 'invalidNumber', }]
173
+ default: return [[{kind: 'number', value: state.value}], {kind: 'eof'}]
174
+ }
175
+ }
176
+ if (input === decimalPoint)
177
+ {
178
+ switch (state.numberKind)
179
+ {
180
+ case '0':
181
+ case 'int': return [undefined, {kind: 'number', value: appendChar(state.value)(input), numberKind: '.'}]
182
+ default: return tokenizeOp({kind: 'invalidNumber'})(input)
183
+ }
184
+ }
185
+ if (input === digit0)
186
+ {
187
+ switch (state.numberKind)
188
+ {
189
+ case '0': return tokenizeOp({kind: 'invalidNumber'})(input)
190
+ case '-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: '0'}]
191
+ case '.': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'fractional'}]
192
+ case 'e':
193
+ case 'e+':
194
+ case 'e-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'expDigits'}]
195
+ default: return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: state.numberKind}]
196
+ }
197
+ }
198
+ if (input >= digit1 && input <= digit9)
199
+ {
200
+ switch (state.numberKind)
201
+ {
202
+ case '0': return tokenizeOp({kind: 'invalidNumber'})(input)
203
+ case '-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'int'}]
204
+ case '.': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'fractional'}]
205
+ case 'e':
206
+ case 'e+':
207
+ case 'e-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'expDigits'}]
208
+ default: return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: state.numberKind}]
209
+ }
210
+ }
211
+ if (input === letterE || input === capitalLetterE)
212
+ {
213
+ switch (state.numberKind)
214
+ {
215
+ case '0':
216
+ case 'int':
217
+ case 'fractional': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e'}]
218
+ default: return tokenizeOp({kind: 'invalidNumber'})(input)
219
+ }
220
+ }
221
+ if (input === signMinus)
222
+ {
223
+ switch (state.numberKind)
224
+ {
225
+ case 'e': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e-'}]
226
+ default: return tokenizeOp({kind: 'invalidNumber'})(input)
227
+ }
228
+ }
229
+ if (input === signPlus)
230
+ {
231
+ switch (state.numberKind)
232
+ {
233
+ case 'e': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e+'}]
234
+ default: return tokenizeOp({kind: 'invalidNumber'})(input)
235
+ }
236
+ }
237
+ if (isTerminalForNumber(input))
238
+ {
239
+ switch (state.numberKind)
240
+ {
241
+ case '-':
242
+ case '.':
243
+ case 'e':
244
+ case 'e+':
245
+ case 'e-':
246
+ {
247
+ const next = tokenizeOp({kind: 'initial'})(input)
248
+ return [{first: {kind: 'error', message: 'invalid number'}, tail: next[0]}, next[1]]
249
+ }
250
+ default:
251
+ {
252
+ const next = tokenizeOp({kind: 'initial'})(input)
253
+ return [{first: {kind: 'number', value: state.value}, tail: next[0]}, next[1]]
254
+ }
255
+ }
256
+ }
257
+ return tokenizeOp({kind: 'invalidNumber'})(input)
258
+ }
259
+
260
+ /** @type {(char: number) => boolean} */
261
+ const isTerminalForNumber = char =>
262
+ {
263
+ switch (char)
264
+ {
265
+ case quotationMark:
266
+ case comma:
267
+ case leftBrace:
268
+ case rightBrace:
269
+ case leftBracket:
270
+ case rightBracket:
271
+ case colon: return true
272
+ default: return false
273
+ }
274
+ }
275
+
276
+ /** @type {(state: InvalidNumberState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
277
+ const invalidNumberStateOp = state => input =>
278
+ {
279
+ if (input === undefined)
280
+ {
281
+ return [[{kind: 'error', message: 'invalid number'}], {kind: 'eof'}]
282
+ }
283
+ if (isTerminalForNumber(input))
284
+ {
285
+ const next = tokenizeOp({kind: 'initial'})(input)
286
+ return [{first: {kind: 'error', message: 'invalid number'}, tail: next[0]}, next[1]]
287
+ }
288
+ return [undefined, {kind: 'invalidNumber'}]
289
+ }
290
+
291
+ /** @type {(state: ParseStringState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
292
+ const parseStringStateOp = state => input =>
293
+ {
294
+ switch(input)
295
+ {
296
+ case quotationMark: return[[{kind: 'string', value: state.value}], {kind: 'initial'}]
297
+ case backslach: return [undefined, {kind:'escapeChar', value: state.value}]
298
+ case undefined: return [[{kind: 'error', message: '" are missing'}], {kind: 'eof'}]
299
+ default: return [undefined, {kind:'string', value: appendChar(state.value)(input)}]
300
+ }
301
+ }
302
+
303
+ /** @type {(state: ParseEscapeCharState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
304
+ const parseEscapeCharStateOp = state => input =>
305
+ {
306
+ switch(input)
307
+ {
308
+ case quotationMark:
309
+ case backslach:
310
+ case slash: return [undefined, {kind: 'string', value: appendChar(state.value)(input)}]
311
+ case letterB: return [undefined, {kind: 'string', value: appendChar(state.value)(backspace)}]
312
+ case letterF: return [undefined, {kind: 'string', value: appendChar(state.value)(formfeed)}]
313
+ case letterN: return [undefined, {kind: 'string', value: appendChar(state.value)(newLine)}]
314
+ case letterR: return [undefined, {kind: 'string', value: appendChar(state.value)(carriageReturn)}]
315
+ case letterT: return [undefined, {kind: 'string', value: appendChar(state.value)(horizontalTab)}]
316
+ case letterU: return [undefined, {kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0}]
317
+ case undefined: return [[{kind: 'error', message: '" are missing'}], {kind: 'eof'}]
318
+ default: {
319
+ const next = tokenizeOp({kind: 'string', value: state.value})(input)
320
+ return [{first: {kind: 'error', message: 'unescaped character'}, tail: next[0]}, next[1]]
321
+ }
322
+ }
323
+ }
324
+
325
+ /** @type {(hex: number) => number|undefined} */
326
+ const hexDigitToNumber = hex =>
327
+ {
328
+ if (hex >= digit0 && hex <= digit9) { return hex - digit0 }
329
+ if (hex >= capitalLetterA && hex <= capitalLetterF) { return hex - capitalLetterA + 10 }
330
+ if (hex >= letterA && hex <= letterF) { return hex - letterA + 10 }
331
+ }
332
+
333
+ /** @type {(state: ParseUnicodeCharState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
334
+ const parseUnicodeCharStateOp = state => input =>
335
+ {
336
+ if (input === undefined)
337
+ {
338
+ return [[{kind: 'error', message: '" are missing'}], {kind: 'eof'}]
339
+ }
340
+ const hexValue = hexDigitToNumber(input)
341
+ if (hexValue === undefined)
342
+ {
343
+ const next = tokenizeOp({kind: 'string', value: state.value})(input)
344
+ return [{first: {kind: 'error', message: 'invalid hex value'}, tail: next[0]}, next[1]]
345
+ }
346
+ const newUnicode = state.unicode | (hexValue << (3 - state.hexIndex) * 4)
347
+ return [undefined, state.hexIndex === 3 ?
348
+ {kind: 'string', value: appendChar(state.value)(newUnicode)} :
349
+ {kind: 'unicodeChar', value: state.value, unicode: newUnicode, hexIndex: state.hexIndex + 1}]
350
+ }
351
+
352
+ /** @type {(s: string) => JsonToken} */
353
+ const stringToKeywordToken = s =>
354
+ {
355
+ switch(s)
356
+ {
357
+ case 'true': return {kind: 'true'}
358
+ case 'false': return {kind: 'false'}
359
+ case 'null': return {kind: 'null'}
360
+ default: return {kind: 'error', message: 'invalid keyword'}
361
+ }
362
+ }
363
+
364
+ /** @type {(state: ParseKeywordState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
365
+ const parseKeyWordStateOp = state => input =>
366
+ {
367
+ if (input === undefined)
368
+ {
369
+ const keyWordToken = stringToKeywordToken(state.value)
370
+ return [[keyWordToken], {kind: 'eof'}]
371
+ }
372
+ if (input >= letterA && input <= letterZ)
373
+ {
374
+ return [undefined, {kind: 'keyword', value: appendChar(state.value)(input)}]
375
+ }
376
+ const keyWordToken = stringToKeywordToken(state.value)
377
+ const next = tokenizeOp({kind: 'initial'})(input)
378
+ return [{first: keyWordToken, tail: next[0]}, next[1]]
379
+ }
380
+
381
+ /** @type {(state: EofState) => (input: JsonCharacter) => readonly[list.List<JsonToken>, TokenizerState]} */
382
+ const eofStateOp = state => input => [[{kind: 'error', message: 'eof'}], state]
383
+
384
+ /** @type {operator.StateScan<JsonCharacter, TokenizerState, list.List<JsonToken>>} */
385
+ const tokenizeOp = state => {
386
+ switch(state.kind)
387
+ {
388
+ case 'initial': return initialStateOp(state)
389
+ case 'keyword': return parseKeyWordStateOp(state)
390
+ case 'string': return parseStringStateOp(state)
391
+ case 'escapeChar': return parseEscapeCharStateOp(state)
392
+ case 'unicodeChar': return parseUnicodeCharStateOp(state)
393
+ case 'invalidNumber': return invalidNumberStateOp(state)
394
+ case 'number': return parseNumberStateOp(state)
395
+ case 'eof': return eofStateOp(state)
396
+ }
397
+ }
398
+
399
+ /** @type {(input: list.List<JsonCharacter>) => list.List<JsonToken>} */
400
+ const tokenize = input => list.flat(list.stateScan(tokenizeOp)({kind: 'initial'})(input))
401
+
402
+ module.exports = {
403
+ /** @readonly */
404
+ tokenize,
405
+ }
@@ -0,0 +1,307 @@
1
+ const tokenizer = require('.')
2
+ const list = require('../../types/list')
3
+ const json = require('..')
4
+ const { sort } = require('../../types/object')
5
+
6
+ /** @type {(s: string) => list.List<tokenizer.JsonCharacter>} */
7
+ const toCharacters = s =>
8
+ {
9
+ /** @type {list.List<tokenizer.JsonCharacter>} */
10
+ const charCodes = list.toCharCodes(s)
11
+ return list.concat(charCodes)([undefined])
12
+ }
13
+
14
+ /** @type {(s: string) => readonly tokenizer.JsonToken[]} */
15
+ const tokenizeString = s =>
16
+ {
17
+ const characters = toCharacters(s)
18
+ return list.toArray(tokenizer.tokenize(characters))
19
+ }
20
+
21
+ /** @type {(a: readonly tokenizer.JsonToken[]) => string} */
22
+ const stringify = a => json.stringify(sort)(a)
23
+
24
+ {
25
+ const result = tokenizeString('')
26
+ if (result.length !== 0) { throw result }
27
+ }
28
+
29
+ {
30
+ const result = stringify(tokenizeString('{'))
31
+ if (result !== '[{"kind":"{"}]') { throw result }
32
+ }
33
+
34
+ {
35
+ const result = stringify(tokenizeString('}'))
36
+ if (result !== '[{"kind":"}"}]') { throw result }
37
+ }
38
+
39
+ {
40
+ const result = stringify(tokenizeString(':'))
41
+ if (result !== '[{"kind":":"}]') { throw result }
42
+ }
43
+
44
+ {
45
+ const result = stringify(tokenizeString(','))
46
+ if (result !== '[{"kind":","}]') { throw result }
47
+ }
48
+
49
+ {
50
+ const result = stringify(tokenizeString('['))
51
+ if (result !== '[{"kind":"["}]') { throw result }
52
+ }
53
+
54
+ {
55
+ const result = stringify(tokenizeString(']'))
56
+ if (result !== '[{"kind":"]"}]') { throw result }
57
+ }
58
+
59
+ {
60
+ const result = stringify(tokenizeString('ᄑ'))
61
+ if (result !== '[{"kind":"error","message":"unexpected character"}]') { throw result }
62
+ }
63
+
64
+ {
65
+ const result = stringify(tokenizeString('err'))
66
+ if (result !== '[{"kind":"error","message":"invalid keyword"}]') { throw result }
67
+ }
68
+
69
+ {
70
+ const result = stringify(tokenizeString('{e}'))
71
+ if (result !== '[{"kind":"{"},{"kind":"error","message":"invalid keyword"},{"kind":"}"}]') { throw result }
72
+ }
73
+
74
+ {
75
+ const result = stringify(tokenizeString('{ \t\n\r}'))
76
+ if (result !== '[{"kind":"{"},{"kind":"}"}]') { throw result }
77
+ }
78
+
79
+ {
80
+ const result = stringify(tokenizeString('true'))
81
+ if (result !== '[{"kind":"true"}]') { throw result }
82
+ }
83
+
84
+ {
85
+ const result = stringify(tokenizeString('tru'))
86
+ if (result !== '[{"kind":"error","message":"invalid keyword"}]') { throw result }
87
+ }
88
+
89
+ {
90
+ const result = stringify(tokenizeString('false'))
91
+ if (result !== '[{"kind":"false"}]') { throw result }
92
+ }
93
+
94
+ {
95
+ const result = stringify(tokenizeString('null'))
96
+ if (result !== '[{"kind":"null"}]') { throw result }
97
+ }
98
+
99
+ {
100
+ const result = stringify(tokenizeString('[null]'))
101
+ if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') { throw result }
102
+ }
103
+
104
+ {
105
+ const result = stringify(tokenizeString('""'))
106
+ if (result !== '[{"kind":"string","value":""}]') { throw result }
107
+ }
108
+
109
+ {
110
+ const result = stringify(tokenizeString('"value"'))
111
+ if (result !== '[{"kind":"string","value":"value"}]') { throw result }
112
+ }
113
+
114
+ {
115
+ const result = stringify(tokenizeString('"value'))
116
+ if (result !== '[{"kind":"error","message":"\\" are missing"}]') { throw result }
117
+ }
118
+
119
+ {
120
+ const result = stringify(tokenizeString('"value1" "value2"'))
121
+ if (result !== '[{"kind":"string","value":"value1"},{"kind":"string","value":"value2"}]') { throw result }
122
+ }
123
+
124
+ {
125
+ const result = stringify(tokenizeString('"'))
126
+ if (result !== '[{"kind":"error","message":"\\" are missing"}]') { throw result }
127
+ }
128
+
129
+ {
130
+ const result = stringify(tokenizeString('"\\\\"'))
131
+ if (result !== '[{"kind":"string","value":"\\\\"}]') { throw result }
132
+ }
133
+
134
+ {
135
+ const result = stringify(tokenizeString('"\\""'))
136
+ if (result !== '[{"kind":"string","value":"\\""}]') { throw result }
137
+ }
138
+
139
+ {
140
+ const result = stringify(tokenizeString('"\\/"'))
141
+ if (result !== '[{"kind":"string","value":"/"}]') { throw result }
142
+ }
143
+
144
+ {
145
+ const result = stringify(tokenizeString('"\\x"'))
146
+ if (result !== '[{"kind":"error","message":"unescaped character"},{"kind":"string","value":"x"}]') { throw result }
147
+ }
148
+
149
+ {
150
+ const result = stringify(tokenizeString('"\\'))
151
+ if (result !== '[{"kind":"error","message":"\\" are missing"}]') { throw result }
152
+ }
153
+
154
+ {
155
+ const result = stringify(tokenizeString('"\\b\\f\\n\\r\\t"'))
156
+ if (result !== '[{"kind":"string","value":"\\b\\f\\n\\r\\t"}]') { throw result }
157
+ }
158
+
159
+ {
160
+ const result = stringify(tokenizeString('"\\u1234"'))
161
+ if (result !== '[{"kind":"string","value":"ሴ"}]') { throw result }
162
+ }
163
+
164
+ {
165
+ const result = stringify(tokenizeString('"\\uaBcDEeFf"'))
166
+ if (result !== '[{"kind":"string","value":"ꯍEeFf"}]') { throw result }
167
+ }
168
+
169
+ {
170
+ const result = stringify(tokenizeString('"\\uEeFg"'))
171
+ if (result !== '[{"kind":"error","message":"invalid hex value"},{"kind":"string","value":"g"}]') { throw result }
172
+ }
173
+
174
+ {
175
+ const result = stringify(tokenizeString('0'))
176
+ if (result !== '[{"kind":"number","value":"0"}]') { throw result }
177
+ }
178
+
179
+ {
180
+ const result = stringify(tokenizeString('[0]'))
181
+ if (result !== '[{"kind":"["},{"kind":"number","value":"0"},{"kind":"]"}]') { throw result }
182
+ }
183
+
184
+ {
185
+ const result = stringify(tokenizeString('00'))
186
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
187
+ }
188
+
189
+ {
190
+ const result = stringify(tokenizeString('0abc,'))
191
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":","}]') { throw result }
192
+ }
193
+
194
+ {
195
+ const result = stringify(tokenizeString('1234567890'))
196
+ if (result !== '[{"kind":"number","value":"1234567890"}]') { throw result }
197
+ }
198
+
199
+ {
200
+ const result = stringify(tokenizeString('{90}'))
201
+ if (result !== '[{"kind":"{"},{"kind":"number","value":"90"},{"kind":"}"}]') { throw result }
202
+ }
203
+
204
+ {
205
+ const result = stringify(tokenizeString('10-0'))
206
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
207
+ }
208
+
209
+ {
210
+ const result = stringify(tokenizeString('9a:'))
211
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":":"}]') { throw result }
212
+ }
213
+
214
+ {
215
+ const result = stringify(tokenizeString('-10'))
216
+ if (result !== '[{"kind":"number","value":"-10"}]') { throw result }
217
+ }
218
+
219
+ {
220
+ const result = stringify(tokenizeString('-0'))
221
+ if (result !== '[{"kind":"number","value":"-0"}]') { throw result }
222
+ }
223
+
224
+ {
225
+ const result = stringify(tokenizeString('-00'))
226
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
227
+ }
228
+
229
+ {
230
+ const result = stringify(tokenizeString('-.123'))
231
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
232
+ }
233
+
234
+ {
235
+ const result = stringify(tokenizeString('0.01'))
236
+ if (result !== '[{"kind":"number","value":"0.01"}]') { throw result }
237
+ }
238
+
239
+ {
240
+ const result = stringify(tokenizeString('-0.9'))
241
+ if (result !== '[{"kind":"number","value":"-0.9"}]') { throw result }
242
+ }
243
+
244
+ {
245
+ const result = stringify(tokenizeString('-0.'))
246
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
247
+ }
248
+
249
+ {
250
+ const result = stringify(tokenizeString('-0.]'))
251
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"]"}]') { throw result }
252
+ }
253
+
254
+ {
255
+ const result = stringify(tokenizeString('12.34'))
256
+ if (result !== '[{"kind":"number","value":"12.34"}]') { throw result }
257
+ }
258
+
259
+ {
260
+ const result = stringify(tokenizeString('-12.00'))
261
+ if (result !== '[{"kind":"number","value":"-12.00"}]') { throw result }
262
+ }
263
+
264
+ {
265
+ const result = stringify(tokenizeString('-12.'))
266
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
267
+ }
268
+
269
+ {
270
+ const result = stringify(tokenizeString('12.]'))
271
+ if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"]"}]') { throw result }
272
+ }
273
+
274
+ {
275
+ const result = stringify(tokenizeString('0e1'))
276
+ if (result !== '[{"kind":"number","value":"0e1"}]') { throw result }
277
+ }
278
+
279
+ {
280
+ const result = stringify(tokenizeString('0e+2'))
281
+ if (result !== '[{"kind":"number","value":"0e+2"}]') { throw result }
282
+ }
283
+
284
+ {
285
+ const result = stringify(tokenizeString('0e-0'))
286
+ if (result !== '[{"kind":"number","value":"0e-0"}]') { throw result }
287
+ }
288
+
289
+ {
290
+ const result = stringify(tokenizeString('12e0000'))
291
+ if (result !== '[{"kind":"number","value":"12e0000"}]') { throw result }
292
+ }
293
+
294
+ {
295
+ const result = stringify(tokenizeString('-12e-0001'))
296
+ if (result !== '[{"kind":"number","value":"-12e-0001"}]') { throw result }
297
+ }
298
+
299
+ {
300
+ const result = stringify(tokenizeString('0e'))
301
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
302
+ }
303
+
304
+ {
305
+ const result = stringify(tokenizeString('0e-'))
306
+ if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
307
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.325",
3
+ "version": "0.0.329",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -5,6 +5,7 @@ require('./types/array/test')
5
5
  require('./types/btree/test')
6
6
  require('./sha2/test')
7
7
  require('./json/test')
8
+ require('./json/tokenizer/test')
8
9
  require('./types/object/test')
9
10
  require('./io/commonjs/test')
10
11
  require('./commonjs/package/dependencies/test')