functionalscript 0.1.607 → 0.1.609
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/CHANGELOG.md +10 -0
- package/Cargo.lock +4 -0
- package/Cargo.toml +4 -2
- package/README.md +1 -1
- package/com/rust/nanocom/src/cobject.rs +1 -1
- package/com/test/rust/src/lib.rs +4 -4
- package/dev/module.mjs +10 -33
- package/dev/test/module.f.mjs +1 -1
- package/djs/parser/module.f.d.mts +51 -31
- package/djs/parser/module.f.mjs +275 -122
- package/djs/parser/test.f.d.mts +4 -0
- package/djs/parser/test.f.mjs +179 -63
- package/djs/tokenizer/module.f.d.mts +1 -1
- package/djs/tokenizer/module.f.mjs +3 -1
- package/djs/tokenizer/test.f.mjs +1 -1
- package/doc/LANGUAGE.md +17 -16
- package/doc/README.md +14 -50
- package/fsc/README.md +0 -3
- package/fsm/README.md +1 -1
- package/html/README.md +24 -0
- package/issues/01-test-debug.md +3 -0
- package/issues/{publish.md → 05-publish.md} +8 -8
- package/issues/17-djs-extension.md +6 -0
- package/issues/README.md +20 -13
- package/issues/lang/1000-json.md +38 -0
- package/issues/lang/2110-default-export.md +2 -2
- package/issues/lang/2310-undefined.md +1 -1
- package/issues/lang/2330-property-accessor.md +225 -0
- package/issues/lang/2360-built-in.md +54 -47
- package/issues/lang/3240-export.md +44 -0
- package/issues/lang/README.md +64 -22
- package/issues/test.f.d.mts +16 -0
- package/issues/test.f.mjs +57 -0
- package/js/tokenizer/module.f.d.mts +8 -2
- package/js/tokenizer/module.f.mjs +29 -3
- package/js/tokenizer/test.f.mjs +9 -6
- package/json/tokenizer/module.f.mjs +2 -1
- package/jsr.json +1 -1
- package/nanvm-lib/Cargo.toml +6 -0
- package/nanvm-lib/src/extension.rs +119 -0
- package/nanvm-lib/src/interface.rs +136 -0
- package/nanvm-lib/src/lib.rs +7 -0
- package/nanvm-lib/src/naive.rs +229 -0
- package/nanvm-lib/src/nanenum.rs +230 -0
- package/nanvm-lib/src/nullish.rs +7 -0
- package/nanvm-lib/src/sign.rs +5 -0
- package/nanvm-lib/src/simple.rs +32 -0
- package/nanvm-lib/tests/test.f.d.mts +36 -0
- package/nanvm-lib/tests/test.f.mjs +79 -0
- package/nanvm-lib/tests/test.rs +108 -0
- package/package.json +1 -2
- package/text/README.md +2 -2
- package/index.f.d.mts +0 -83
- package/index.f.mjs +0 -83
- package/issues/lang/2351-property-accessor.md +0 -44
- package/issues/lang/2352-property-call.md +0 -43
- package/issues/lang/2353-property-at.md +0 -19
- package/issues/test-debug.md +0 -12
- /package/issues/{esm.md → 02-esm.md} +0 -0
- /package/issues/{djs.md → 03-djs.md} +0 -0
- /package/issues/{fs-load.md → 11-fs-load.md} +0 -0
- /package/issues/lang/{2330-grouping.md → 2350-grouping.md} +0 -0
package/djs/parser/module.f.mjs
CHANGED
|
@@ -2,156 +2,291 @@
|
|
|
2
2
|
|
|
3
3
|
import result, * as Result from '../../types/result/module.f.mjs'
|
|
4
4
|
import list, * as List from '../../types/list/module.f.mjs'
|
|
5
|
-
const { fold, first, drop, toArray } = list
|
|
5
|
+
const { fold, first, drop, toArray, map: listMap, length } = list
|
|
6
6
|
import * as Operator from '../../types/function/operator/module.f.mjs'
|
|
7
7
|
import * as tokenizerT from '../tokenizer/module.f.mjs'
|
|
8
8
|
import map, * as Map from '../../types/map/module.f.mjs'
|
|
9
|
-
const { setReplace } = map
|
|
10
|
-
import * as
|
|
11
|
-
import o from '../../types/object/module.f.mjs'
|
|
9
|
+
const { setReplace, at } = map
|
|
10
|
+
import o, * as O from '../../types/object/module.f.mjs'
|
|
12
11
|
const { fromMap } = o
|
|
13
12
|
|
|
13
|
+
/** @typedef {[readonly string[], readonly DjsConst[]] } DjsModule */
|
|
14
|
+
|
|
15
|
+
/** @typedef {boolean|string|number|null|bigint|DjsModuleRef|DjsArray|DjsObject} DjsConst */
|
|
16
|
+
|
|
17
|
+
/** @typedef {['aref' | 'cref', number]} DjsModuleRef */
|
|
18
|
+
|
|
19
|
+
/** @typedef {['array', readonly DjsConst[]]} DjsArray */
|
|
20
|
+
|
|
14
21
|
/**
|
|
15
22
|
* @typedef {{
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
* readonly [k in string]: DjsConst
|
|
24
|
+
* }} DjsObject
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @typedef {['array', List.List<DjsConst>]} DjsStackArray */
|
|
28
|
+
|
|
29
|
+
/** @typedef {['object', Map.Map<DjsConst>, string]} DjsStackObject */
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {|
|
|
34
|
+
* DjsStackArray |
|
|
35
|
+
* DjsStackObject
|
|
36
|
+
* } DjsStackElement
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/** @typedef {List.List<DjsStackElement>} DjsStack */
|
|
40
|
+
|
|
41
|
+
/** @typedef {InitialState | NewLineRequiredState | ImportState | ConstState | ExportState | ParseValueState | ResultState | ErrorState} ParserState */
|
|
21
42
|
|
|
22
43
|
/**
|
|
23
44
|
* @typedef {{
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
45
|
+
* readonly refs: Map.Map<DjsModuleRef>
|
|
46
|
+
* readonly modules: List.List<string>
|
|
47
|
+
* readonly consts: List.List<DjsConst>
|
|
48
|
+
* }} ModuleState
|
|
49
|
+
*/
|
|
28
50
|
|
|
29
51
|
/**
|
|
30
|
-
* @typedef {
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* }
|
|
52
|
+
* @typedef {{
|
|
53
|
+
* readonly state: ''
|
|
54
|
+
* readonly module: ModuleState
|
|
55
|
+
* }} InitialState
|
|
34
56
|
*/
|
|
35
57
|
|
|
36
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {{
|
|
60
|
+
* readonly state: 'nl'
|
|
61
|
+
* readonly module: ModuleState
|
|
62
|
+
* }} NewLineRequiredState
|
|
63
|
+
*/
|
|
37
64
|
|
|
38
65
|
/**
|
|
39
66
|
* @typedef {{
|
|
40
|
-
* readonly
|
|
41
|
-
* readonly
|
|
42
|
-
* }}
|
|
67
|
+
* readonly state: 'import' | 'import+name' | 'import+from'
|
|
68
|
+
* readonly module: ModuleState
|
|
69
|
+
* }} ImportState
|
|
43
70
|
*/
|
|
44
71
|
|
|
45
72
|
/**
|
|
46
73
|
* @typedef {{
|
|
47
|
-
* readonly
|
|
48
|
-
* readonly
|
|
49
|
-
*
|
|
50
|
-
* }} StateParse
|
|
74
|
+
* readonly state: 'const' | 'const+name'
|
|
75
|
+
* readonly module: ModuleState
|
|
76
|
+
* }} ConstState
|
|
51
77
|
*/
|
|
52
78
|
|
|
53
79
|
/**
|
|
54
80
|
* @typedef {{
|
|
55
|
-
* readonly
|
|
56
|
-
* readonly
|
|
57
|
-
* }}
|
|
81
|
+
* readonly state: 'export'
|
|
82
|
+
* readonly module: ModuleState
|
|
83
|
+
* }} ExportState
|
|
58
84
|
*/
|
|
59
85
|
|
|
60
86
|
/**
|
|
61
87
|
* @typedef {{
|
|
62
|
-
* readonly
|
|
63
|
-
* readonly
|
|
64
|
-
*
|
|
88
|
+
* readonly state: 'constValue' | 'exportValue'
|
|
89
|
+
* readonly module: ModuleState
|
|
90
|
+
* readonly valueState: '' | '[' | '[v' | '[,' | '{' | '{k' | '{:' | '{v' | '{,'
|
|
91
|
+
* readonly top: DjsStackElement | null
|
|
92
|
+
* readonly stack: DjsStack
|
|
93
|
+
* }} ParseValueState
|
|
65
94
|
*/
|
|
66
95
|
|
|
67
96
|
/**
|
|
68
|
-
* @typedef {
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
* @typedef {{
|
|
98
|
+
* readonly state: 'result'
|
|
99
|
+
* readonly module: ModuleState
|
|
100
|
+
* }} ResultState
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @typedef {{
|
|
105
|
+
* readonly state: 'error'
|
|
106
|
+
* readonly message: string
|
|
107
|
+
* }} ErrorState
|
|
74
108
|
*/
|
|
75
109
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
110
|
+
|
|
111
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: InitialState) => ParserState}} */
|
|
112
|
+
const parseInitialOp = token => state => {
|
|
113
|
+
switch (token.kind)
|
|
79
114
|
{
|
|
80
|
-
case '
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
115
|
+
case 'ws':
|
|
116
|
+
case 'nl': return state
|
|
117
|
+
case 'id': {
|
|
118
|
+
switch (token.value) {
|
|
119
|
+
case 'import': return { ... state, state: 'import' }
|
|
120
|
+
case 'const': return { ... state, state: 'const' }
|
|
121
|
+
case 'export': return { ... state, state: 'export' }
|
|
122
|
+
}
|
|
84
123
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
124
|
+
}
|
|
125
|
+
return { state: 'error', message: 'unexpected token' }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: NewLineRequiredState) => ParserState}} */
|
|
129
|
+
const parseNewLineRequiredOp = token => state => {
|
|
130
|
+
switch (token.kind) {
|
|
131
|
+
case 'ws': return state
|
|
132
|
+
case 'nl': return { ... state, state: '' }
|
|
133
|
+
default: return { state: 'error', message: 'unexpected token' }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ExportState) => ParserState}} */
|
|
138
|
+
const parseExportOp = token => state => {
|
|
139
|
+
switch (token.kind) {
|
|
140
|
+
case 'ws':
|
|
141
|
+
case 'nl': return state
|
|
142
|
+
case 'id': {
|
|
143
|
+
if (token.value === 'default') return { ... state, state: 'exportValue', valueState: '', top: null, stack: null }
|
|
89
144
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
145
|
+
}
|
|
146
|
+
return { state: 'error', message: 'unexpected token' }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ConstState) => ParserState}} */
|
|
150
|
+
const parseConstOp = token => state => {
|
|
151
|
+
switch (token.kind) {
|
|
152
|
+
case 'ws':
|
|
153
|
+
case 'nl': return state
|
|
154
|
+
case 'id': {
|
|
155
|
+
if (map.at(token.value)(state.module.refs) !== null)
|
|
156
|
+
return { state: 'error', message: 'duplicate id' }
|
|
157
|
+
/** @type {DjsModuleRef} */
|
|
158
|
+
let cref = ['cref', length(state.module.consts)]
|
|
159
|
+
let refs = map.setReplace(token.value)(cref)(state.module.refs)
|
|
160
|
+
return { ... state, state: 'const+name', module: { ...state.module, refs: refs } }
|
|
94
161
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
162
|
+
default: return { state: 'error', message: 'unexpected token' }
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ConstState) => ParserState}} */
|
|
167
|
+
const parseConstNameOp = token => state => {
|
|
168
|
+
switch (token.kind) {
|
|
169
|
+
case 'ws':
|
|
170
|
+
case 'nl': return state
|
|
171
|
+
case '=': return { ... state, state: 'constValue', valueState: '', top: null, stack: null }
|
|
172
|
+
default: return { state: 'error', message: 'unexpected token' }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ImportState) => ParserState}} */
|
|
177
|
+
const parseImportOp = token => state => {
|
|
178
|
+
switch (token.kind) {
|
|
179
|
+
case 'ws':
|
|
180
|
+
case 'nl': return state
|
|
181
|
+
case 'id': {
|
|
182
|
+
if (map.at(token.value)(state.module.refs) !== null)
|
|
183
|
+
return { state: 'error', message: 'duplicate id' }
|
|
184
|
+
/** @type {DjsModuleRef} */
|
|
185
|
+
let aref = ['aref', length(state.module.modules)]
|
|
186
|
+
let refs = map.setReplace(token.value)(aref)(state.module.refs)
|
|
187
|
+
return { ... state, state: 'import+name', module: { ...state.module, refs: refs } }
|
|
188
|
+
}
|
|
189
|
+
default: return { state: 'error', message: 'unexpected token' }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ImportState) => ParserState}} */
|
|
194
|
+
const parseImportNameOp = token => state => {
|
|
195
|
+
switch (token.kind) {
|
|
196
|
+
case 'ws':
|
|
197
|
+
case 'nl': return state
|
|
198
|
+
case 'id': {
|
|
199
|
+
if (token.value === 'from') return { ... state, state: 'import+from' }
|
|
99
200
|
}
|
|
100
201
|
}
|
|
101
|
-
return {
|
|
202
|
+
return { state: 'error', message: 'unexpected token' }
|
|
102
203
|
}
|
|
103
204
|
|
|
104
|
-
/** @type {(
|
|
105
|
-
const
|
|
205
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ImportState) => ParserState}} */
|
|
206
|
+
const parseImportFromOp = token => state => {
|
|
207
|
+
switch (token.kind) {
|
|
208
|
+
case 'ws':
|
|
209
|
+
case 'nl': return state
|
|
210
|
+
case 'string': {
|
|
211
|
+
const modules = list.concat(state.module.modules)([token.value])
|
|
212
|
+
return { ... state, state: 'nl', module: { ...state.module, modules: modules } }
|
|
213
|
+
}
|
|
214
|
+
default: return { state: 'error', message: 'unexpected token' }
|
|
215
|
+
}
|
|
216
|
+
}
|
|
106
217
|
|
|
107
|
-
/** @type {(obj:
|
|
108
|
-
const
|
|
218
|
+
/** @type {(obj: DjsStackObject) => (key: string) => DjsStackObject} */
|
|
219
|
+
const addKeyToObject = obj => key => ([ 'object', obj[1], key])
|
|
109
220
|
|
|
110
|
-
/** @type {(
|
|
111
|
-
const
|
|
221
|
+
/** @type {(obj: DjsStackObject) => (value: DjsConst) => DjsStackObject} */
|
|
222
|
+
const addValueToObject = obj => value => ([ 'object', setReplace(obj[2])(value)(obj[1]), '' ])
|
|
112
223
|
|
|
113
|
-
/** @type {(
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
224
|
+
/** @type {(array: DjsStackArray) => (value: DjsConst) => DjsStackArray} */
|
|
225
|
+
const addToArray = array => value => ([ 'array', list.concat(array[1])([value]) ])
|
|
226
|
+
|
|
227
|
+
/** @type {(state: ParseValueState) => (key: string) => ParserState} */
|
|
228
|
+
const pushKey = state => key => {
|
|
229
|
+
if (state.top?.[0] === 'object') { return { ... state, valueState: '{k', top: addKeyToObject(state.top)(key), stack: state.stack } }
|
|
230
|
+
return { state: 'error', message: 'error' }
|
|
117
231
|
}
|
|
118
232
|
|
|
119
|
-
/** @type {(state:
|
|
233
|
+
/** @type {(state: ParseValueState) => (value: DjsConst) => ParserState} */
|
|
120
234
|
const pushValue = state => value => {
|
|
121
|
-
if (state.top === null) {
|
|
122
|
-
|
|
123
|
-
|
|
235
|
+
if (state.top === null) {
|
|
236
|
+
let consts = list.concat(state.module.consts)([value])
|
|
237
|
+
switch(state.state)
|
|
238
|
+
{
|
|
239
|
+
case 'exportValue': return { ... state, state: 'result', module: { ...state.module, consts: consts }}
|
|
240
|
+
case 'constValue': return { ... state, state: 'nl', module: { ...state.module, consts: consts }}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (state.top?.[0] === 'array') { return { ... state, valueState: '[v', top: addToArray(state.top)(value), stack: state.stack } }
|
|
244
|
+
return { ... state, valueState: '{v', top: addValueToObject(state.top)(value), stack: state.stack }
|
|
124
245
|
}
|
|
125
246
|
|
|
126
|
-
/** @type {(state:
|
|
247
|
+
/** @type {(state: ParseValueState) => (name: string) => ParserState} */
|
|
248
|
+
const pushRef = state => name => {
|
|
249
|
+
const ref = at(name)(state.module.refs)
|
|
250
|
+
if (ref === null)
|
|
251
|
+
return { state: 'error', message: 'const not found' }
|
|
252
|
+
return pushValue(state)(ref)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** @type {(state: ParseValueState) => ParserState} */
|
|
127
256
|
const startArray = state => {
|
|
128
257
|
const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
|
|
129
|
-
return {
|
|
258
|
+
return { ... state, valueState: '[', top: ['array', null ], stack: newStack }
|
|
130
259
|
}
|
|
131
260
|
|
|
132
|
-
/** @type {(state:
|
|
261
|
+
/** @type {(state: ParseValueState) => ParserState} */
|
|
133
262
|
const endArray = state => {
|
|
134
|
-
const
|
|
135
|
-
/** @type {
|
|
136
|
-
const newState = {
|
|
137
|
-
|
|
263
|
+
const top = state.top;
|
|
264
|
+
/** @type {ParseValueState} */
|
|
265
|
+
const newState = { ... state, valueState: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
|
|
266
|
+
if (top !== null && top[0] === 'array')
|
|
267
|
+
{
|
|
268
|
+
/** @type {DjsArray} */
|
|
269
|
+
const array = ['array', toArray(top[1])];
|
|
270
|
+
return pushValue(newState)(array)
|
|
271
|
+
}
|
|
272
|
+
return pushValue(newState)(null)
|
|
138
273
|
}
|
|
139
274
|
|
|
140
|
-
/** @type {(state:
|
|
275
|
+
/** @type {(state: ParseValueState) => ParserState} */
|
|
141
276
|
const startObject = state => {
|
|
142
277
|
const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
|
|
143
|
-
return {
|
|
278
|
+
return { ... state, valueState: '{', top: ['object', null, ''], stack: newStack }
|
|
144
279
|
}
|
|
145
280
|
|
|
146
|
-
/** @type {(state:
|
|
281
|
+
/** @type {(state: ParseValueState) => ParserState} */
|
|
147
282
|
const endObject = state => {
|
|
148
|
-
const obj = state
|
|
149
|
-
/** @type {
|
|
150
|
-
const newState = {
|
|
283
|
+
const obj = state?.top !== null && state?.top[0] === 'object' ? fromMap(state.top[1]) : null;
|
|
284
|
+
/** @type {ParseValueState} */
|
|
285
|
+
const newState = { ... state, valueState: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
|
|
151
286
|
return pushValue(newState)(obj)
|
|
152
287
|
}
|
|
153
288
|
|
|
154
|
-
/** @type {(token: tokenizerT.DjsToken) =>
|
|
289
|
+
/** @type {(token: tokenizerT.DjsToken) => DjsConst} */
|
|
155
290
|
const tokenToValue = token => {
|
|
156
291
|
switch (token.kind) {
|
|
157
292
|
case 'null': return null
|
|
@@ -177,100 +312,118 @@ const isValueToken = token => {
|
|
|
177
312
|
}
|
|
178
313
|
}
|
|
179
314
|
|
|
180
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
315
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
181
316
|
const parseValueOp = token => state => {
|
|
182
317
|
if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
|
|
318
|
+
if (token.kind === 'id') { return pushRef(state)(token.value) }
|
|
183
319
|
if (token.kind === '[') { return startArray(state) }
|
|
184
320
|
if (token.kind === '{') { return startObject(state) }
|
|
185
321
|
if (token.kind === 'ws') { return state }
|
|
186
|
-
return {
|
|
322
|
+
return { state: 'error', message: 'unexpected token' }
|
|
187
323
|
}
|
|
188
324
|
|
|
189
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
325
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
190
326
|
const parseArrayStartOp = token => state => {
|
|
191
327
|
if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
|
|
328
|
+
if (token.kind === 'id') { return pushRef(state)(token.value) }
|
|
192
329
|
if (token.kind === '[') { return startArray(state) }
|
|
193
330
|
if (token.kind === ']') { return endArray(state) }
|
|
194
331
|
if (token.kind === '{') { return startObject(state) }
|
|
195
332
|
if (token.kind === 'ws') { return state }
|
|
196
|
-
return {
|
|
333
|
+
return { state: 'error', message: 'unexpected token' }
|
|
197
334
|
}
|
|
198
335
|
|
|
199
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
336
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
200
337
|
const parseArrayValueOp = token => state => {
|
|
201
338
|
if (token.kind === ']') { return endArray(state) }
|
|
202
|
-
if (token.kind === ',') { return {
|
|
339
|
+
if (token.kind === ',') { return { ... state, valueState: '[,', top: state.top, stack: state.stack } }
|
|
203
340
|
if (token.kind === 'ws') { return state }
|
|
204
|
-
return {
|
|
341
|
+
return { state: 'error', message: 'unexpected token' }
|
|
205
342
|
}
|
|
206
343
|
|
|
207
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
344
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
208
345
|
const parseObjectStartOp = token => state => {
|
|
209
346
|
if (token.kind === 'string') { return pushKey(state)(token.value) }
|
|
210
347
|
if (token.kind === '}') { return endObject(state) }
|
|
211
348
|
if (token.kind === 'ws') { return state }
|
|
212
|
-
return {
|
|
349
|
+
return { state: 'error', message: 'unexpected token' }
|
|
213
350
|
}
|
|
214
351
|
|
|
215
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
352
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
216
353
|
const parseObjectKeyOp = token => state => {
|
|
217
|
-
if (token.kind === ':') { return {
|
|
354
|
+
if (token.kind === ':') { return { ... state, valueState: '{:', top: state.top, stack: state.stack } }
|
|
218
355
|
if (token.kind === 'ws') { return state }
|
|
219
|
-
return {
|
|
356
|
+
return { state: 'error', message: 'unexpected token' }
|
|
220
357
|
}
|
|
221
358
|
|
|
222
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
359
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
223
360
|
const parseObjectColonOp = token => state => {
|
|
224
361
|
if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
|
|
362
|
+
if (token.kind === 'id') { return pushRef(state)(token.value) }
|
|
225
363
|
if (token.kind === '[') { return startArray(state) }
|
|
226
364
|
if (token.kind === '{') { return startObject(state) }
|
|
227
365
|
if (token.kind === 'ws') { return state }
|
|
228
|
-
return {
|
|
366
|
+
return { state: 'error', message: 'unexpected token' }
|
|
229
367
|
}
|
|
230
368
|
|
|
231
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
369
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
232
370
|
const parseObjectNextOp = token => state => {
|
|
233
371
|
if (token.kind === '}') { return endObject(state) }
|
|
234
|
-
if (token.kind === ',') { return {
|
|
372
|
+
if (token.kind === ',') { return { ... state, valueState: '{,', top: state.top, stack: state.stack } }
|
|
235
373
|
if (token.kind === 'ws') { return state }
|
|
236
|
-
return {
|
|
374
|
+
return { state: 'error', message: 'unexpected token' }
|
|
237
375
|
}
|
|
238
376
|
|
|
239
|
-
/** @type {(token: tokenizerT.DjsToken) => (state:
|
|
377
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
240
378
|
const parseObjectCommaOp = token => state => {
|
|
241
379
|
if (token.kind === 'string') { return pushKey(state)(token.value) }
|
|
242
380
|
if (token.kind === 'ws') { return state }
|
|
243
|
-
return {
|
|
381
|
+
return { state: 'error', message: 'unexpected token' }
|
|
244
382
|
}
|
|
245
383
|
|
|
246
|
-
/** @type {Operator.Fold<tokenizerT.DjsToken,
|
|
384
|
+
/** @type {Operator.Fold<tokenizerT.DjsToken, ParserState>} */
|
|
247
385
|
const foldOp = token => state => {
|
|
248
|
-
switch (state.
|
|
249
|
-
case '
|
|
250
|
-
case '
|
|
251
|
-
case '
|
|
252
|
-
case '': return
|
|
253
|
-
case '
|
|
254
|
-
case '
|
|
255
|
-
case '
|
|
256
|
-
case '
|
|
257
|
-
case '
|
|
258
|
-
case '{:':
|
|
259
|
-
case '
|
|
260
|
-
case '
|
|
386
|
+
switch (state.state) {
|
|
387
|
+
case '': return parseInitialOp(token)(state)
|
|
388
|
+
case 'nl': return parseNewLineRequiredOp(token)(state)
|
|
389
|
+
case 'import': return parseImportOp(token)(state)
|
|
390
|
+
case 'import+name': return parseImportNameOp(token)(state)
|
|
391
|
+
case 'import+from': return parseImportFromOp(token)(state)
|
|
392
|
+
case 'const': return parseConstOp(token)(state)
|
|
393
|
+
case 'const+name': return parseConstNameOp(token)(state)
|
|
394
|
+
case 'export': return parseExportOp(token)(state)
|
|
395
|
+
case 'result': return { state: 'error', message: 'unexpected token' }
|
|
396
|
+
case 'error': return { state: 'error', message: state.message }
|
|
397
|
+
case 'constValue':
|
|
398
|
+
case 'exportValue':
|
|
399
|
+
{
|
|
400
|
+
switch (state.valueState)
|
|
401
|
+
{
|
|
402
|
+
case '': return parseValueOp(token)(state)
|
|
403
|
+
case '[': return parseArrayStartOp(token)(state)
|
|
404
|
+
case '[v': return parseArrayValueOp(token)(state)
|
|
405
|
+
case '[,': return parseValueOp(token)(state)
|
|
406
|
+
case '{': return parseObjectStartOp(token)(state)
|
|
407
|
+
case '{k': return parseObjectKeyOp(token)(state)
|
|
408
|
+
case '{:': return parseObjectColonOp(token)(state)
|
|
409
|
+
case '{v': return parseObjectNextOp(token)(state)
|
|
410
|
+
case '{,': return parseObjectCommaOp(token)(state)
|
|
411
|
+
}
|
|
412
|
+
}
|
|
261
413
|
}
|
|
262
414
|
}
|
|
263
415
|
|
|
264
|
-
/** @type {(tokenList: List.List<tokenizerT.DjsToken>) => Result.Result<
|
|
416
|
+
/** @type {(tokenList: List.List<tokenizerT.DjsToken>) => Result.Result<DjsModule, string>} */
|
|
265
417
|
const parse = tokenList => {
|
|
266
|
-
const state = fold(foldOp)({
|
|
267
|
-
switch (state.
|
|
268
|
-
case 'result': return result.ok(state.
|
|
418
|
+
const state = fold(foldOp)({ state: '', module: { refs: null, modules: null, consts: null }})(tokenList)
|
|
419
|
+
switch (state.state) {
|
|
420
|
+
case 'result': return result.ok([ toArray(state.module.modules), toArray(state.module.consts) ])
|
|
269
421
|
case 'error': return result.error(state.message)
|
|
270
422
|
default: return result.error('unexpected end')
|
|
271
423
|
}
|
|
272
424
|
}
|
|
273
425
|
|
|
426
|
+
|
|
274
427
|
export default {
|
|
275
428
|
/** @readonly */
|
|
276
429
|
parse
|
package/djs/parser/test.f.d.mts
CHANGED
|
@@ -4,5 +4,9 @@ declare namespace _default {
|
|
|
4
4
|
let validWhiteSpaces: (() => void)[];
|
|
5
5
|
let validModule: (() => void)[];
|
|
6
6
|
let invalidModule: (() => void)[];
|
|
7
|
+
let validWithConst: (() => void)[];
|
|
8
|
+
let invalidWithConst: (() => void)[];
|
|
9
|
+
let validWithArgs: (() => void)[];
|
|
10
|
+
let invalidWithArgs: (() => void)[];
|
|
7
11
|
}
|
|
8
12
|
export default _default;
|