functionalscript 0.0.525 → 0.0.527
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/fjson/README.md +18 -0
- package/fjson/tokenizer/module.f.cjs +73 -18
- package/fjson/tokenizer/test.f.cjs +54 -34
- package/js/tokenizer/module.f.cjs +213 -100
- package/js/tokenizer/test.f.cjs +270 -55
- package/json/parser/test.f.cjs +7 -1
- package/json/tokenizer/module.f.cjs +70 -16
- package/json/tokenizer/test.f.cjs +66 -34
- package/package.json +1 -1
- package/types/bigfloat/module.f.cjs +2 -0
package/fjson/README.md
CHANGED
|
@@ -6,3 +6,21 @@
|
|
|
6
6
|
|
|
7
7
|
- can serialize/deserialize without reading source code
|
|
8
8
|
- no function serialization/deserialization
|
|
9
|
+
|
|
10
|
+
## Next steps
|
|
11
|
+
|
|
12
|
+
- [x] identifiers
|
|
13
|
+
- [x] big int
|
|
14
|
+
- [ ] `module.exports = ...`
|
|
15
|
+
- [ ] constants `const a = [3];module.exports = { a: a, b: a }`. Serialization `const _0=[3];module.exports={a:_0,b:_0}`
|
|
16
|
+
- [ ] import `const a = require('c.fon.js');module.exports = { a: a, b: a}`
|
|
17
|
+
|
|
18
|
+
Optional, for fun, syntax sugar:
|
|
19
|
+
|
|
20
|
+
- [ ] comments. Ignore them. Not an error.
|
|
21
|
+
- [ ] double/single quote strings
|
|
22
|
+
|
|
23
|
+
## Decidable Language
|
|
24
|
+
|
|
25
|
+
- [ ] using operator and functions `const a = 2+2+Math.abs(5); module.exports = { a: a };`
|
|
26
|
+
- [ ] decidable functions `const f = a => b => a + b; module.exports = f(1)(2)`?
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
const operator = require('../../types/function/operator/module.f.cjs')
|
|
1
2
|
const list = require('../../types/list/module.f.cjs')
|
|
3
|
+
const { empty, flat, stateScan } = list
|
|
4
|
+
const { multiply } = require('../../types/bigfloat/module.f.cjs')
|
|
2
5
|
const jsTokenizer = require('../../js/tokenizer/module.f.cjs')
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* @typedef {|
|
|
6
|
-
*
|
|
9
|
+
* {readonly kind: 'true' | 'false' | 'null'} |
|
|
10
|
+
* {readonly kind: '{' | '}' | ':' | ',' | '[' | ']' } |
|
|
7
11
|
* jsTokenizer.StringToken |
|
|
8
12
|
* jsTokenizer.NumberToken |
|
|
9
13
|
* jsTokenizer.ErrorToken |
|
|
@@ -12,31 +16,82 @@ const jsTokenizer = require('../../js/tokenizer/module.f.cjs')
|
|
|
12
16
|
* } FjsonToken
|
|
13
17
|
*/
|
|
14
18
|
|
|
15
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {|
|
|
21
|
+
* {readonly kind: 'def' | '-' }
|
|
22
|
+
* } ScanState
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {|
|
|
27
|
+
* jsTokenizer.JsToken | null
|
|
28
|
+
* } ScanInput
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** @type {(input: jsTokenizer.JsToken) => list.List<FjsonToken>} */
|
|
16
32
|
const mapToken = input =>
|
|
17
33
|
{
|
|
18
34
|
switch(input.kind)
|
|
19
35
|
{
|
|
20
|
-
case
|
|
21
|
-
case
|
|
22
|
-
case
|
|
23
|
-
case
|
|
24
|
-
case
|
|
25
|
-
case
|
|
26
|
-
case
|
|
27
|
-
case
|
|
28
|
-
case
|
|
29
|
-
case
|
|
30
|
-
case
|
|
31
|
-
case
|
|
32
|
-
case
|
|
33
|
-
case
|
|
34
|
-
|
|
36
|
+
case 'id':
|
|
37
|
+
case 'bigint':
|
|
38
|
+
case '{':
|
|
39
|
+
case '}':
|
|
40
|
+
case ':':
|
|
41
|
+
case ',':
|
|
42
|
+
case '[':
|
|
43
|
+
case ']':
|
|
44
|
+
case 'true':
|
|
45
|
+
case 'false':
|
|
46
|
+
case 'null':
|
|
47
|
+
case 'string':
|
|
48
|
+
case 'number':
|
|
49
|
+
case 'error': return [input]
|
|
50
|
+
case 'ws': return empty
|
|
51
|
+
default: return jsTokenizer.isKeywordToken(input) ? [{ kind: 'id', value: input.kind }] : [{ kind: 'error', message: 'invalid token' }]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** @type {(input: ScanInput) => readonly [list.List<FjsonToken>, ScanState]} */
|
|
56
|
+
const parseDefaultState = input =>
|
|
57
|
+
{
|
|
58
|
+
if (input === null) return [empty, { kind: 'def'}]
|
|
59
|
+
switch(input.kind)
|
|
60
|
+
{
|
|
61
|
+
case '-': return [empty, { kind: '-'}]
|
|
62
|
+
default: return [mapToken(input), { kind: 'def'}]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @type {(input: ScanInput) => readonly [list.List<FjsonToken>, ScanState]} */
|
|
67
|
+
const parseMinusState = input =>
|
|
68
|
+
{
|
|
69
|
+
if (input === null) return [[{ kind: 'error', message: 'invalid token' }], { kind: 'def'}]
|
|
70
|
+
switch(input.kind)
|
|
71
|
+
{
|
|
72
|
+
case '-': return [[{ kind: 'error', message: 'invalid token' }], { kind: '-'}]
|
|
73
|
+
case 'bigint': return [[{ kind: 'bigint', value: -1n * input.value }], { kind: 'def'}]
|
|
74
|
+
case 'number': return [[{ kind: 'number', bf: multiply(input.bf)(-1n), value: `-${input.value}` }], { kind: 'def'}]
|
|
75
|
+
default: return [{ first: { kind: 'error', message: 'invalid token' }, tail: mapToken(input)}, { kind: 'def'}]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @type {operator.StateScan<ScanInput, ScanState, list.List<FjsonToken>>} */
|
|
80
|
+
const scanToken = state => input => {
|
|
81
|
+
switch(state.kind)
|
|
82
|
+
{
|
|
83
|
+
case '-': return parseMinusState(input)
|
|
84
|
+
default: return parseDefaultState(input)
|
|
35
85
|
}
|
|
36
86
|
}
|
|
37
87
|
|
|
38
88
|
/** @type {(input: list.List<number>) => list.List<FjsonToken>} */
|
|
39
|
-
const tokenize = input =>
|
|
89
|
+
const tokenize = input =>
|
|
90
|
+
{
|
|
91
|
+
/** @type {list.List<ScanInput>} */
|
|
92
|
+
const jsTokens = jsTokenizer.tokenize(input)
|
|
93
|
+
return flat(stateScan(scanToken)({ kind: 'def' })(list.concat(jsTokens)([null])))
|
|
94
|
+
}
|
|
40
95
|
|
|
41
96
|
module.exports = {
|
|
42
97
|
/** @readonly */
|
|
@@ -43,38 +43,10 @@ module.exports = {
|
|
|
43
43
|
const result = stringify(tokenizeString('ᄑ'))
|
|
44
44
|
if (result !== '[{"kind":"error","message":"unexpected character"}]') { throw result }
|
|
45
45
|
},
|
|
46
|
-
() => {
|
|
47
|
-
const result = stringify(tokenizeString('err'))
|
|
48
|
-
if (result !== '[{"kind":"id","value":"err"}]') { throw result }
|
|
49
|
-
},
|
|
50
|
-
() => {
|
|
51
|
-
const result = stringify(tokenizeString('{e}'))
|
|
52
|
-
if (result !== '[{"kind":"{"},{"kind":"id","value":"e"},{"kind":"}"}]') { throw result }
|
|
53
|
-
},
|
|
54
46
|
() => {
|
|
55
47
|
const result = stringify(tokenizeString('{ \t\n\r}'))
|
|
56
48
|
if (result !== '[{"kind":"{"},{"kind":"}"}]') { throw result }
|
|
57
49
|
},
|
|
58
|
-
() => {
|
|
59
|
-
const result = stringify(tokenizeString('true'))
|
|
60
|
-
if (result !== '[{"kind":"true"}]') { throw result }
|
|
61
|
-
},
|
|
62
|
-
() => {
|
|
63
|
-
const result = stringify(tokenizeString('tru'))
|
|
64
|
-
if (result !== '[{"kind":"id","value":"tru"}]') { throw result }
|
|
65
|
-
},
|
|
66
|
-
() => {
|
|
67
|
-
const result = stringify(tokenizeString('false'))
|
|
68
|
-
if (result !== '[{"kind":"false"}]') { throw result }
|
|
69
|
-
},
|
|
70
|
-
() => {
|
|
71
|
-
const result = stringify(tokenizeString('null'))
|
|
72
|
-
if (result !== '[{"kind":"null"}]') { throw result }
|
|
73
|
-
},
|
|
74
|
-
() => {
|
|
75
|
-
const result = stringify(tokenizeString('[null]'))
|
|
76
|
-
if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') { throw result }
|
|
77
|
-
},
|
|
78
50
|
() => {
|
|
79
51
|
const result = stringify(tokenizeString('""'))
|
|
80
52
|
if (result !== '[{"kind":"string","value":""}]') { throw result }
|
|
@@ -165,7 +137,7 @@ module.exports = {
|
|
|
165
137
|
},
|
|
166
138
|
() => {
|
|
167
139
|
const result = stringify(tokenizeString('10-0'))
|
|
168
|
-
if (result !== '[{"kind":"
|
|
140
|
+
if (result !== '[{"bf":[10n,0],"kind":"number","value":"10"},{"bf":[0n,0],"kind":"number","value":"-0"}]') { throw result }
|
|
169
141
|
},
|
|
170
142
|
() => {
|
|
171
143
|
const result = stringify(tokenizeString('9a:'))
|
|
@@ -175,17 +147,29 @@ module.exports = {
|
|
|
175
147
|
const result = stringify(tokenizeString('-10'))
|
|
176
148
|
if (result !== '[{"bf":[-10n,0],"kind":"number","value":"-10"}]') { throw result }
|
|
177
149
|
},
|
|
150
|
+
() => {
|
|
151
|
+
const result = stringify(tokenizeString('-'))
|
|
152
|
+
if (result !== '[{"kind":"error","message":"invalid token"}]') { throw result }
|
|
153
|
+
},
|
|
154
|
+
() => {
|
|
155
|
+
const result = stringify(tokenizeString('--'))
|
|
156
|
+
if (result !== '[{"kind":"error","message":"invalid token"}]') { throw result }
|
|
157
|
+
},
|
|
158
|
+
() => {
|
|
159
|
+
const result = stringify(tokenizeString('---'))
|
|
160
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid token"}]') { throw result }
|
|
161
|
+
},
|
|
178
162
|
() => {
|
|
179
163
|
const result = stringify(tokenizeString('-0'))
|
|
180
164
|
if (result !== '[{"bf":[0n,0],"kind":"number","value":"-0"}]') { throw result }
|
|
181
165
|
},
|
|
182
166
|
() => {
|
|
183
167
|
const result = stringify(tokenizeString('-00'))
|
|
184
|
-
if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
|
|
168
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid number"}]') { throw result }
|
|
185
169
|
},
|
|
186
170
|
() => {
|
|
187
171
|
const result = stringify(tokenizeString('-.123'))
|
|
188
|
-
if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
|
|
172
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid token"},{"bf":[123n,0],"kind":"number","value":"123"}]') { throw result }
|
|
189
173
|
},
|
|
190
174
|
() => {
|
|
191
175
|
const result = stringify(tokenizeString('0.01'))
|
|
@@ -197,11 +181,11 @@ module.exports = {
|
|
|
197
181
|
},
|
|
198
182
|
() => {
|
|
199
183
|
const result = stringify(tokenizeString('-0.'))
|
|
200
|
-
if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
|
|
184
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid number"}]') { throw result }
|
|
201
185
|
},
|
|
202
186
|
() => {
|
|
203
187
|
const result = stringify(tokenizeString('-0.]'))
|
|
204
|
-
if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"]"}]') { throw result }
|
|
188
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid number"},{"kind":"]"}]') { throw result }
|
|
205
189
|
},
|
|
206
190
|
() => {
|
|
207
191
|
const result = stringify(tokenizeString('12.34'))
|
|
@@ -213,7 +197,7 @@ module.exports = {
|
|
|
213
197
|
},
|
|
214
198
|
() => {
|
|
215
199
|
const result = stringify(tokenizeString('-12.'))
|
|
216
|
-
if (result !== '[{"kind":"error","message":"invalid number"}]') { throw result }
|
|
200
|
+
if (result !== '[{"kind":"error","message":"invalid token"},{"kind":"error","message":"invalid number"}]') { throw result }
|
|
217
201
|
},
|
|
218
202
|
() => {
|
|
219
203
|
const result = stringify(tokenizeString('12.]'))
|
|
@@ -303,5 +287,41 @@ module.exports = {
|
|
|
303
287
|
const result = stringify(tokenizeString('1234567890nn'))
|
|
304
288
|
if (result !== '[{"kind":"error","message":"invalid number"},{"kind":"id","value":"n"}]') { throw result }
|
|
305
289
|
},
|
|
290
|
+
],
|
|
291
|
+
id: [
|
|
292
|
+
() => {
|
|
293
|
+
const result = stringify(tokenizeString('err'))
|
|
294
|
+
if (result !== '[{"kind":"id","value":"err"}]') { throw result }
|
|
295
|
+
},
|
|
296
|
+
() => {
|
|
297
|
+
const result = stringify(tokenizeString('{e}'))
|
|
298
|
+
if (result !== '[{"kind":"{"},{"kind":"id","value":"e"},{"kind":"}"}]') { throw result }
|
|
299
|
+
},
|
|
300
|
+
() => {
|
|
301
|
+
const result = stringify(tokenizeString('tru'))
|
|
302
|
+
if (result !== '[{"kind":"id","value":"tru"}]') { throw result }
|
|
303
|
+
},
|
|
304
|
+
() => {
|
|
305
|
+
const result = stringify(tokenizeString('break'))
|
|
306
|
+
if (result !== '[{"kind":"id","value":"break"}]') { throw result }
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
keywords: [
|
|
310
|
+
() => {
|
|
311
|
+
const result = stringify(tokenizeString('true'))
|
|
312
|
+
if (result !== '[{"kind":"true"}]') { throw result }
|
|
313
|
+
},
|
|
314
|
+
() => {
|
|
315
|
+
const result = stringify(tokenizeString('false'))
|
|
316
|
+
if (result !== '[{"kind":"false"}]') { throw result }
|
|
317
|
+
},
|
|
318
|
+
() => {
|
|
319
|
+
const result = stringify(tokenizeString('null'))
|
|
320
|
+
if (result !== '[{"kind":"null"}]') { throw result }
|
|
321
|
+
},
|
|
322
|
+
() => {
|
|
323
|
+
const result = stringify(tokenizeString('[null]'))
|
|
324
|
+
if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') { throw result }
|
|
325
|
+
},
|
|
306
326
|
]
|
|
307
327
|
}
|