functionalscript 0.2.4 → 0.2.5
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 +6 -0
- package/README.md +1 -1
- package/crypto/README.md +3 -0
- package/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
- package/{secp → crypto/secp}/module.f.mjs +2 -2
- package/{sha2 → crypto/sha2}/module.f.mjs +4 -4
- package/{sha2 → crypto/sha2}/test.f.mjs +2 -2
- package/djs/module.f.mjs +4 -1
- package/djs/parser/module.f.mjs +122 -45
- package/djs/parser/test.f.mjs +30 -4
- package/djs/tokenizer/module.f.mjs +6 -2
- package/djs/tokenizer/test.f.mjs +34 -0
- package/html/module.f.mjs +18 -33
- package/html/test.f.mjs +6 -6
- package/issues/05-publish.md +17 -22
- package/issues/README.md +10 -2
- package/js/tokenizer/module.f.mjs +75 -26
- package/js/tokenizer/test.f.mjs +42 -0
- package/json/parser/test.f.mjs +6 -0
- package/jsr.json +4 -4
- package/nanvm-lib/src/extension.rs +1 -1
- package/nanvm-lib/src/nanenum.rs +22 -20
- package/out/{prime_field → crypto/prime_field}/module.f.d.mts +1 -1
- package/out/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
- package/out/{secp → crypto/secp}/module.f.d.mts +1 -1
- package/out/{secp → crypto/secp}/module.f.mjs +2 -2
- package/out/{sha2 → crypto/sha2}/module.f.d.mts +3 -3
- package/out/{sha2 → crypto/sha2}/module.f.mjs +4 -4
- package/out/{sha2 → crypto/sha2}/test.f.mjs +2 -2
- package/out/djs/module.f.d.mts +1 -1
- package/out/djs/module.f.mjs +5 -1
- package/out/djs/parser/module.f.d.mts +1 -1
- package/out/djs/parser/module.f.mjs +105 -89
- package/out/djs/parser/test.f.d.mts +1 -0
- package/out/djs/parser/test.f.mjs +38 -4
- package/out/djs/tokenizer/module.f.d.mts +2 -2
- package/out/djs/tokenizer/module.f.mjs +6 -2
- package/out/djs/tokenizer/test.f.d.mts +1 -0
- package/out/djs/tokenizer/test.f.mjs +50 -0
- package/out/html/module.f.d.mts +8 -6
- package/out/html/module.f.mjs +17 -31
- package/out/html/test.f.mjs +5 -5
- package/out/js/tokenizer/module.f.d.mts +15 -3
- package/out/js/tokenizer/module.f.mjs +65 -22
- package/out/js/tokenizer/test.f.d.mts +1 -0
- package/out/js/tokenizer/test.f.mjs +62 -0
- package/out/json/parser/test.f.mjs +8 -0
- package/package.json +1 -1
- /package/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
- /package/{secp → crypto/secp}/test.f.mjs +0 -0
- /package/out/{prime_field → crypto/prime_field}/test.f.d.mts +0 -0
- /package/out/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
- /package/out/{secp → crypto/secp}/test.f.d.mts +0 -0
- /package/out/{secp → crypto/secp}/test.f.mjs +0 -0
- /package/out/{sha2 → crypto/sha2}/test.f.d.mts +0 -0
package/out/djs/module.f.d.mts
CHANGED
|
@@ -12,7 +12,7 @@ export const serialize: (mapEntries: MapEntries) => (value: Unknown) => list.Lis
|
|
|
12
12
|
export const stringify: (mapEntries: MapEntries) => (value: Unknown) => string;
|
|
13
13
|
export type Object = { readonly [k in string]: Unknown; };
|
|
14
14
|
export type Array = readonly Unknown[];
|
|
15
|
-
export type Unknown = Object | boolean | string | number | null | Array | bigint;
|
|
15
|
+
export type Unknown = Object | boolean | string | number | null | Array | bigint | undefined;
|
|
16
16
|
export type Entry = O.Entry<Unknown>;
|
|
17
17
|
export type Entries = (list.List<Entry>);
|
|
18
18
|
export type MapEntries = (entries: Entries) => Entries;
|
package/out/djs/module.f.mjs
CHANGED
|
@@ -17,8 +17,9 @@ const { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize,
|
|
|
17
17
|
* }} Object
|
|
18
18
|
*/
|
|
19
19
|
/** @typedef {readonly Unknown[]} Array */
|
|
20
|
-
/** @typedef {Object|boolean|string|number|null|Array|bigint} Unknown */
|
|
20
|
+
/** @typedef {Object|boolean|string|number|null|Array|bigint|undefined} Unknown */
|
|
21
21
|
const colon = [':'];
|
|
22
|
+
const undefinedSerialize = ['undefined'];
|
|
22
23
|
/** @typedef {O.Entry<Unknown>} Entry*/
|
|
23
24
|
/** @typedef {(list.List<Entry>)} Entries */
|
|
24
25
|
/** @typedef {(entries: Entries) => Entries} MapEntries */
|
|
@@ -56,6 +57,9 @@ export const serialize = sort => {
|
|
|
56
57
|
if (value === null) {
|
|
57
58
|
return nullSerialize;
|
|
58
59
|
}
|
|
60
|
+
if (value === undefined) {
|
|
61
|
+
return undefinedSerialize;
|
|
62
|
+
}
|
|
59
63
|
if (value instanceof Array) {
|
|
60
64
|
return arraySerialize(value);
|
|
61
65
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @type {(tokenList: list.List<tokenizerT.DjsToken>) => result.Result<DjsModule, string>} */
|
|
2
2
|
export const parse: (tokenList: list.List<tokenizerT.DjsToken>) => result.Result<DjsModule, string>;
|
|
3
3
|
export type DjsModule = [readonly string[], readonly DjsConst[]];
|
|
4
|
-
export type DjsConst = boolean | string | number | null | bigint | DjsModuleRef | DjsArray | DjsObject;
|
|
4
|
+
export type DjsConst = boolean | string | number | null | bigint | undefined | DjsModuleRef | DjsArray | DjsObject;
|
|
5
5
|
export type DjsModuleRef = ["aref" | "cref", number];
|
|
6
6
|
export type DjsArray = ["array", readonly DjsConst[]];
|
|
7
7
|
export type DjsObject = { readonly [k in string]: DjsConst; };
|
|
@@ -9,7 +9,7 @@ const { setReplace, at } = map;
|
|
|
9
9
|
import * as o from '../../types/object/module.f.mjs';
|
|
10
10
|
const { fromMap } = o;
|
|
11
11
|
/** @typedef {[readonly string[], readonly DjsConst[]] } DjsModule */
|
|
12
|
-
/** @typedef {boolean|string|number|null|bigint|DjsModuleRef|DjsArray|DjsObject} DjsConst */
|
|
12
|
+
/** @typedef {boolean|string|number|null|bigint|undefined|DjsModuleRef|DjsArray|DjsObject} DjsConst */
|
|
13
13
|
/** @typedef {['aref' | 'cref', number]} DjsModuleRef */
|
|
14
14
|
/** @typedef {['array', readonly DjsConst[]]} DjsArray */
|
|
15
15
|
/**
|
|
@@ -89,7 +89,9 @@ const { fromMap } = o;
|
|
|
89
89
|
const parseInitialOp = token => state => {
|
|
90
90
|
switch (token.kind) {
|
|
91
91
|
case 'ws':
|
|
92
|
-
case 'nl':
|
|
92
|
+
case 'nl':
|
|
93
|
+
case '//':
|
|
94
|
+
case '/*': return state;
|
|
93
95
|
case 'id': {
|
|
94
96
|
switch (token.value) {
|
|
95
97
|
case 'import': return { ...state, state: 'import' };
|
|
@@ -103,7 +105,9 @@ const parseInitialOp = token => state => {
|
|
|
103
105
|
/** @type {(token: tokenizerT.DjsToken) => (state: NewLineRequiredState) => ParserState}} */
|
|
104
106
|
const parseNewLineRequiredOp = token => state => {
|
|
105
107
|
switch (token.kind) {
|
|
106
|
-
case 'ws':
|
|
108
|
+
case 'ws':
|
|
109
|
+
case '//':
|
|
110
|
+
case '/*': return state;
|
|
107
111
|
case 'nl': return { ...state, state: '' };
|
|
108
112
|
default: return { state: 'error', message: 'unexpected token' };
|
|
109
113
|
}
|
|
@@ -112,7 +116,9 @@ const parseNewLineRequiredOp = token => state => {
|
|
|
112
116
|
const parseExportOp = token => state => {
|
|
113
117
|
switch (token.kind) {
|
|
114
118
|
case 'ws':
|
|
115
|
-
case 'nl':
|
|
119
|
+
case 'nl':
|
|
120
|
+
case '//':
|
|
121
|
+
case '/*': return state;
|
|
116
122
|
case 'id': {
|
|
117
123
|
if (token.value === 'default')
|
|
118
124
|
return { ...state, state: 'exportValue', valueState: '', top: null, stack: null };
|
|
@@ -120,11 +126,23 @@ const parseExportOp = token => state => {
|
|
|
120
126
|
}
|
|
121
127
|
return { state: 'error', message: 'unexpected token' };
|
|
122
128
|
};
|
|
129
|
+
/** @type {(token: tokenizerT.DjsToken) => (state: ResultState) => ParserState}} */
|
|
130
|
+
const parseResultOp = token => state => {
|
|
131
|
+
switch (token.kind) {
|
|
132
|
+
case 'ws':
|
|
133
|
+
case 'nl':
|
|
134
|
+
case '//':
|
|
135
|
+
case '/*': return state;
|
|
136
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
137
|
+
}
|
|
138
|
+
};
|
|
123
139
|
/** @type {(token: tokenizerT.DjsToken) => (state: ConstState) => ParserState}} */
|
|
124
140
|
const parseConstOp = token => state => {
|
|
125
141
|
switch (token.kind) {
|
|
126
142
|
case 'ws':
|
|
127
|
-
case 'nl':
|
|
143
|
+
case 'nl':
|
|
144
|
+
case '//':
|
|
145
|
+
case '/*': return state;
|
|
128
146
|
case 'id': {
|
|
129
147
|
if (map.at(token.value)(state.module.refs) !== null)
|
|
130
148
|
return { state: 'error', message: 'duplicate id' };
|
|
@@ -140,7 +158,9 @@ const parseConstOp = token => state => {
|
|
|
140
158
|
const parseConstNameOp = token => state => {
|
|
141
159
|
switch (token.kind) {
|
|
142
160
|
case 'ws':
|
|
143
|
-
case 'nl':
|
|
161
|
+
case 'nl':
|
|
162
|
+
case '//':
|
|
163
|
+
case '/*': return state;
|
|
144
164
|
case '=': return { ...state, state: 'constValue', valueState: '', top: null, stack: null };
|
|
145
165
|
default: return { state: 'error', message: 'unexpected token' };
|
|
146
166
|
}
|
|
@@ -149,7 +169,9 @@ const parseConstNameOp = token => state => {
|
|
|
149
169
|
const parseImportOp = token => state => {
|
|
150
170
|
switch (token.kind) {
|
|
151
171
|
case 'ws':
|
|
152
|
-
case 'nl':
|
|
172
|
+
case 'nl':
|
|
173
|
+
case '//':
|
|
174
|
+
case '/*': return state;
|
|
153
175
|
case 'id': {
|
|
154
176
|
if (map.at(token.value)(state.module.refs) !== null)
|
|
155
177
|
return { state: 'error', message: 'duplicate id' };
|
|
@@ -165,7 +187,9 @@ const parseImportOp = token => state => {
|
|
|
165
187
|
const parseImportNameOp = token => state => {
|
|
166
188
|
switch (token.kind) {
|
|
167
189
|
case 'ws':
|
|
168
|
-
case 'nl':
|
|
190
|
+
case 'nl':
|
|
191
|
+
case '//':
|
|
192
|
+
case '/*': return state;
|
|
169
193
|
case 'id': {
|
|
170
194
|
if (token.value === 'from')
|
|
171
195
|
return { ...state, state: 'import+from' };
|
|
@@ -177,7 +201,9 @@ const parseImportNameOp = token => state => {
|
|
|
177
201
|
const parseImportFromOp = token => state => {
|
|
178
202
|
switch (token.kind) {
|
|
179
203
|
case 'ws':
|
|
180
|
-
case 'nl':
|
|
204
|
+
case 'nl':
|
|
205
|
+
case '//':
|
|
206
|
+
case '/*': return state;
|
|
181
207
|
case 'string': {
|
|
182
208
|
const modules = list.concat(state.module.modules)([token.value]);
|
|
183
209
|
return { ...state, state: 'nl', module: { ...state.module, modules: modules } };
|
|
@@ -257,6 +283,7 @@ const tokenToValue = token => {
|
|
|
257
283
|
case 'number': return parseFloat(token.value);
|
|
258
284
|
case 'string': return token.value;
|
|
259
285
|
case 'bigint': return token.value;
|
|
286
|
+
case 'undefined': return undefined;
|
|
260
287
|
default: return null;
|
|
261
288
|
}
|
|
262
289
|
};
|
|
@@ -268,7 +295,8 @@ const isValueToken = token => {
|
|
|
268
295
|
case 'true':
|
|
269
296
|
case 'number':
|
|
270
297
|
case 'string':
|
|
271
|
-
case 'bigint':
|
|
298
|
+
case 'bigint':
|
|
299
|
+
case 'undefined': return true;
|
|
272
300
|
default: return false;
|
|
273
301
|
}
|
|
274
302
|
};
|
|
@@ -277,119 +305,107 @@ const parseValueOp = token => state => {
|
|
|
277
305
|
if (isValueToken(token)) {
|
|
278
306
|
return pushValue(state)(tokenToValue(token));
|
|
279
307
|
}
|
|
280
|
-
|
|
281
|
-
return pushRef(state)(token.value);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
if (token.kind === 'ws') {
|
|
290
|
-
return state;
|
|
308
|
+
switch (token.kind) {
|
|
309
|
+
case 'id': return pushRef(state)(token.value);
|
|
310
|
+
case '[': return startArray(state);
|
|
311
|
+
case '{': return startObject(state);
|
|
312
|
+
case 'ws':
|
|
313
|
+
case 'nl':
|
|
314
|
+
case '//':
|
|
315
|
+
case '/*': return state;
|
|
316
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
291
317
|
}
|
|
292
|
-
return { state: 'error', message: 'unexpected token' };
|
|
293
318
|
};
|
|
294
319
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
295
320
|
const parseArrayStartOp = token => state => {
|
|
296
321
|
if (isValueToken(token)) {
|
|
297
322
|
return pushValue(state)(tokenToValue(token));
|
|
298
323
|
}
|
|
299
|
-
|
|
300
|
-
return pushRef(state)(token.value);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return startObject(state);
|
|
310
|
-
}
|
|
311
|
-
if (token.kind === 'ws') {
|
|
312
|
-
return state;
|
|
324
|
+
switch (token.kind) {
|
|
325
|
+
case 'id': return pushRef(state)(token.value);
|
|
326
|
+
case '[': return startArray(state);
|
|
327
|
+
case ']': return endArray(state);
|
|
328
|
+
case '{': return startObject(state);
|
|
329
|
+
case 'ws':
|
|
330
|
+
case 'nl':
|
|
331
|
+
case '//':
|
|
332
|
+
case '/*': return state;
|
|
333
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
313
334
|
}
|
|
314
|
-
return { state: 'error', message: 'unexpected token' };
|
|
315
335
|
};
|
|
316
336
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
317
337
|
const parseArrayValueOp = token => state => {
|
|
318
|
-
|
|
319
|
-
return endArray(state);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return state;
|
|
338
|
+
switch (token.kind) {
|
|
339
|
+
case ']': return endArray(state);
|
|
340
|
+
case ',': return { ...state, valueState: '[,', top: state.top, stack: state.stack };
|
|
341
|
+
case 'ws':
|
|
342
|
+
case 'nl':
|
|
343
|
+
case '//':
|
|
344
|
+
case '/*': return state;
|
|
345
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
326
346
|
}
|
|
327
|
-
return { state: 'error', message: 'unexpected token' };
|
|
328
347
|
};
|
|
329
348
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
330
349
|
const parseObjectStartOp = token => state => {
|
|
331
|
-
|
|
332
|
-
return pushKey(state)(token.value);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
return state;
|
|
350
|
+
switch (token.kind) {
|
|
351
|
+
case 'string': return pushKey(state)(token.value);
|
|
352
|
+
case '}': return endObject(state);
|
|
353
|
+
case 'ws':
|
|
354
|
+
case 'nl':
|
|
355
|
+
case '//':
|
|
356
|
+
case '/*': return state;
|
|
357
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
339
358
|
}
|
|
340
|
-
return { state: 'error', message: 'unexpected token' };
|
|
341
359
|
};
|
|
342
360
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
343
361
|
const parseObjectKeyOp = token => state => {
|
|
344
|
-
|
|
345
|
-
return { ...state, valueState: '{:', top: state.top, stack: state.stack };
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
362
|
+
switch (token.kind) {
|
|
363
|
+
case ':': return { ...state, valueState: '{:', top: state.top, stack: state.stack };
|
|
364
|
+
case 'ws':
|
|
365
|
+
case 'nl':
|
|
366
|
+
case '//':
|
|
367
|
+
case '/*': return state;
|
|
368
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
349
369
|
}
|
|
350
|
-
return { state: 'error', message: 'unexpected token' };
|
|
351
370
|
};
|
|
352
371
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
353
372
|
const parseObjectColonOp = token => state => {
|
|
354
373
|
if (isValueToken(token)) {
|
|
355
374
|
return pushValue(state)(tokenToValue(token));
|
|
356
375
|
}
|
|
357
|
-
|
|
358
|
-
return pushRef(state)(token.value);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
return
|
|
365
|
-
|
|
366
|
-
if (token.kind === 'ws') {
|
|
367
|
-
return state;
|
|
376
|
+
switch (token.kind) {
|
|
377
|
+
case 'id': return pushRef(state)(token.value);
|
|
378
|
+
case '[': return startArray(state);
|
|
379
|
+
case '{': return startObject(state);
|
|
380
|
+
case 'ws':
|
|
381
|
+
case 'nl':
|
|
382
|
+
case '//':
|
|
383
|
+
case '/*': return state;
|
|
384
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
368
385
|
}
|
|
369
|
-
return { state: 'error', message: 'unexpected token' };
|
|
370
386
|
};
|
|
371
387
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
372
388
|
const parseObjectNextOp = token => state => {
|
|
373
|
-
|
|
374
|
-
return endObject(state);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return state;
|
|
389
|
+
switch (token.kind) {
|
|
390
|
+
case '}': return endObject(state);
|
|
391
|
+
case ',': return { ...state, valueState: '{,', top: state.top, stack: state.stack };
|
|
392
|
+
case 'ws':
|
|
393
|
+
case 'nl':
|
|
394
|
+
case '//':
|
|
395
|
+
case '/*': return state;
|
|
396
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
381
397
|
}
|
|
382
|
-
return { state: 'error', message: 'unexpected token' };
|
|
383
398
|
};
|
|
384
399
|
/** @type {(token: tokenizerT.DjsToken) => (state: ParseValueState) => ParserState}} */
|
|
385
400
|
const parseObjectCommaOp = token => state => {
|
|
386
|
-
|
|
387
|
-
return pushKey(state)(token.value);
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
401
|
+
switch (token.kind) {
|
|
402
|
+
case 'string': return pushKey(state)(token.value);
|
|
403
|
+
case 'ws':
|
|
404
|
+
case 'nl':
|
|
405
|
+
case '//':
|
|
406
|
+
case '/*': return state;
|
|
407
|
+
default: return { state: 'error', message: 'unexpected token' };
|
|
391
408
|
}
|
|
392
|
-
return { state: 'error', message: 'unexpected token' };
|
|
393
409
|
};
|
|
394
410
|
/** @type {Operator.Fold<tokenizerT.DjsToken, ParserState>} */
|
|
395
411
|
const foldOp = token => state => {
|
|
@@ -402,7 +418,7 @@ const foldOp = token => state => {
|
|
|
402
418
|
case 'const': return parseConstOp(token)(state);
|
|
403
419
|
case 'const+name': return parseConstNameOp(token)(state);
|
|
404
420
|
case 'export': return parseExportOp(token)(state);
|
|
405
|
-
case 'result': return
|
|
421
|
+
case 'result': return parseResultOp(token)(state);
|
|
406
422
|
case 'error': return { state: 'error', message: state.message };
|
|
407
423
|
case 'constValue':
|
|
408
424
|
case 'exportValue':
|
|
@@ -35,6 +35,14 @@ export default {
|
|
|
35
35
|
throw result;
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
+
() => {
|
|
39
|
+
const tokenList = tokenizeString('export default undefined');
|
|
40
|
+
const obj = parser.parse(tokenList);
|
|
41
|
+
const result = stringify(obj);
|
|
42
|
+
if (result !== '["ok",[[],[undefined]]]') {
|
|
43
|
+
throw result;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
38
46
|
() => {
|
|
39
47
|
const tokenList = tokenizeString('export default 0.1');
|
|
40
48
|
const obj = parser.parse(tokenList);
|
|
@@ -108,10 +116,10 @@ export default {
|
|
|
108
116
|
}
|
|
109
117
|
},
|
|
110
118
|
() => {
|
|
111
|
-
const tokenList = tokenizeString('export default {"a":true,"b":false,"c":null}');
|
|
119
|
+
const tokenList = tokenizeString('export default {"a":true,"b":false,"c":null,"d":undefined}');
|
|
112
120
|
const obj = parser.parse(tokenList);
|
|
113
121
|
const result = stringify(obj);
|
|
114
|
-
if (result !== '["ok",[[],[{"a":true,"b":false,"c":null}]]]') {
|
|
122
|
+
if (result !== '["ok",[[],[{"a":true,"b":false,"c":null,"d":undefined}]]]') {
|
|
115
123
|
throw result;
|
|
116
124
|
}
|
|
117
125
|
},
|
|
@@ -336,7 +344,7 @@ export default {
|
|
|
336
344
|
],
|
|
337
345
|
validWhiteSpaces: [
|
|
338
346
|
() => {
|
|
339
|
-
const tokenList = tokenizeString('export default [ 0 , 1 , 2 ]');
|
|
347
|
+
const tokenList = tokenizeString(' export default [ 0 , 1 , 2 ] ');
|
|
340
348
|
const obj = parser.parse(tokenList);
|
|
341
349
|
const result = stringify(obj);
|
|
342
350
|
if (result !== '["ok",[[],[["array",[0,1,2]]]]]') {
|
|
@@ -344,7 +352,23 @@ export default {
|
|
|
344
352
|
}
|
|
345
353
|
},
|
|
346
354
|
() => {
|
|
347
|
-
const tokenList = tokenizeString('export default { "a" : 0 , "b" : 1 }');
|
|
355
|
+
const tokenList = tokenizeString(' export default { "a" : 0 , "b" : 1 } ');
|
|
356
|
+
const obj = parser.parse(tokenList);
|
|
357
|
+
const result = stringify(obj);
|
|
358
|
+
if (result !== '["ok",[[],[{"a":0,"b":1}]]]') {
|
|
359
|
+
throw result;
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
() => {
|
|
363
|
+
const tokenList = tokenizeString('\nexport\ndefault\n[\n0\n,\n1\n,\n2\n]\n');
|
|
364
|
+
const obj = parser.parse(tokenList);
|
|
365
|
+
const result = stringify(obj);
|
|
366
|
+
if (result !== '["ok",[[],[["array",[0,1,2]]]]]') {
|
|
367
|
+
throw result;
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
() => {
|
|
371
|
+
const tokenList = tokenizeString('\rexport\rdefault\r{\r"a"\r:\r0\r,\r"b"\r:\r1\r}\r');
|
|
348
372
|
const obj = parser.parse(tokenList);
|
|
349
373
|
const result = stringify(obj);
|
|
350
374
|
if (result !== '["ok",[[],[{"a":0,"b":1}]]]') {
|
|
@@ -532,4 +556,14 @@ export default {
|
|
|
532
556
|
}
|
|
533
557
|
},
|
|
534
558
|
],
|
|
559
|
+
comments: [
|
|
560
|
+
() => {
|
|
561
|
+
const tokenList = tokenizeString('export //comment \n default /* comment */ null //comment');
|
|
562
|
+
const obj = parser.parse(tokenList);
|
|
563
|
+
const result = stringify(obj);
|
|
564
|
+
if (result !== '["ok",[[],[null]]]') {
|
|
565
|
+
throw result;
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
]
|
|
535
569
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** @type {(input: list.List<number>) => list.List<DjsToken>} */
|
|
2
2
|
export const tokenize: (input: list.List<number>) => list.List<DjsToken>;
|
|
3
3
|
export type DjsToken = {
|
|
4
|
-
readonly kind: "true" | "false" | "null";
|
|
4
|
+
readonly kind: "true" | "false" | "null" | "undefined";
|
|
5
5
|
} | {
|
|
6
6
|
readonly kind: "{" | "}" | ":" | "," | "[" | "]" | "." | "=";
|
|
7
|
-
} | jsTokenizer.StringToken | jsTokenizer.NumberToken | jsTokenizer.ErrorToken | jsTokenizer.IdToken | jsTokenizer.BigIntToken | jsTokenizer.WhitespaceToken | jsTokenizer.NewLineToken;
|
|
7
|
+
} | jsTokenizer.StringToken | jsTokenizer.NumberToken | jsTokenizer.ErrorToken | jsTokenizer.IdToken | jsTokenizer.BigIntToken | jsTokenizer.WhitespaceToken | jsTokenizer.NewLineToken | jsTokenizer.CommentToken;
|
|
8
8
|
export type ScanState = {
|
|
9
9
|
readonly kind: "def" | "-";
|
|
10
10
|
};
|
|
@@ -7,7 +7,7 @@ const { multiply } = bf;
|
|
|
7
7
|
import * as jsTokenizer from '../../js/tokenizer/module.f.mjs';
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {|
|
|
10
|
-
* {readonly kind: 'true' | 'false' | 'null'} |
|
|
10
|
+
* {readonly kind: 'true' | 'false' | 'null' | 'undefined'} |
|
|
11
11
|
* {readonly kind: '{' | '}' | ':' | ',' | '[' | ']' | '.' | '=' } |
|
|
12
12
|
* jsTokenizer.StringToken |
|
|
13
13
|
* jsTokenizer.NumberToken |
|
|
@@ -15,7 +15,8 @@ import * as jsTokenizer from '../../js/tokenizer/module.f.mjs';
|
|
|
15
15
|
* jsTokenizer.IdToken |
|
|
16
16
|
* jsTokenizer.BigIntToken |
|
|
17
17
|
* jsTokenizer.WhitespaceToken |
|
|
18
|
-
* jsTokenizer.NewLineToken
|
|
18
|
+
* jsTokenizer.NewLineToken |
|
|
19
|
+
* jsTokenizer.CommentToken
|
|
19
20
|
* } DjsToken
|
|
20
21
|
*/
|
|
21
22
|
/**
|
|
@@ -48,6 +49,9 @@ const mapToken = input => {
|
|
|
48
49
|
case 'number':
|
|
49
50
|
case 'ws':
|
|
50
51
|
case 'nl':
|
|
52
|
+
case 'undefined':
|
|
53
|
+
case '//':
|
|
54
|
+
case '/*':
|
|
51
55
|
case 'error': return [input];
|
|
52
56
|
default: return jsTokenizer.isKeywordToken(input) ? [{ kind: 'id', value: input.kind }] : [{ kind: 'error', message: 'invalid token' }];
|
|
53
57
|
}
|
|
@@ -470,11 +470,61 @@ export default {
|
|
|
470
470
|
throw result;
|
|
471
471
|
}
|
|
472
472
|
},
|
|
473
|
+
() => {
|
|
474
|
+
const result = stringify(tokenizeString('undefined'));
|
|
475
|
+
if (result !== '[{"kind":"undefined"}]') {
|
|
476
|
+
throw result;
|
|
477
|
+
}
|
|
478
|
+
},
|
|
473
479
|
() => {
|
|
474
480
|
const result = stringify(tokenizeString('[null]'));
|
|
475
481
|
if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') {
|
|
476
482
|
throw result;
|
|
477
483
|
}
|
|
478
484
|
},
|
|
485
|
+
],
|
|
486
|
+
comments: [
|
|
487
|
+
() => {
|
|
488
|
+
const result = stringify(tokenizeString('//singleline comment'));
|
|
489
|
+
if (result !== '[{"kind":"//","value":"singleline comment"}]') {
|
|
490
|
+
throw result;
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
() => {
|
|
494
|
+
const result = stringify(tokenizeString('true//singleline comment\nfalse'));
|
|
495
|
+
if (result !== '[{"kind":"true"},{"kind":"//","value":"singleline comment"},{"kind":"nl"},{"kind":"false"}]') {
|
|
496
|
+
throw result;
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
() => {
|
|
500
|
+
const result = stringify(tokenizeString('/* multiline comment */'));
|
|
501
|
+
if (result !== '[{"kind":"/*","value":" multiline comment "}]') {
|
|
502
|
+
throw result;
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
() => {
|
|
506
|
+
const result = stringify(tokenizeString('/* multiline comment *'));
|
|
507
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') {
|
|
508
|
+
throw result;
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
() => {
|
|
512
|
+
const result = stringify(tokenizeString('/* multiline comment '));
|
|
513
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') {
|
|
514
|
+
throw result;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
() => {
|
|
518
|
+
const result = stringify(tokenizeString('/* multiline comment \n * **/'));
|
|
519
|
+
if (result !== '[{"kind":"/*","value":" multiline comment \\n * *"},{"kind":"nl"}]') {
|
|
520
|
+
throw result;
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
() => {
|
|
524
|
+
const result = stringify(tokenizeString('/* multiline comment *\n * **/'));
|
|
525
|
+
if (result !== '[{"kind":"/*","value":" multiline comment *\\n * *"},{"kind":"nl"}]') {
|
|
526
|
+
throw result;
|
|
527
|
+
}
|
|
528
|
+
},
|
|
479
529
|
]
|
|
480
530
|
};
|
package/out/html/module.f.d.mts
CHANGED
|
@@ -3,13 +3,15 @@ export const element: (element: Element) => list.List<string>;
|
|
|
3
3
|
export const html: f.Func<Element, list.List<string>>;
|
|
4
4
|
export const htmlToString: f.Func<Element, string>;
|
|
5
5
|
export type Tag = string;
|
|
6
|
-
export type
|
|
7
|
-
export type
|
|
8
|
-
export type
|
|
9
|
-
export type
|
|
10
|
-
export type Element = Element1 |
|
|
6
|
+
export type VoidTagList = typeof voidTagList;
|
|
7
|
+
export type VoidTag = keyof readonly ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"];
|
|
8
|
+
export type Element1 = readonly [Tag, ...Node[]];
|
|
9
|
+
export type Element2 = readonly [Tag, Attributes, ...Node[]];
|
|
10
|
+
export type Element = Element1 | Element2;
|
|
11
11
|
export type Attributes = { readonly [k in string]: string; };
|
|
12
|
-
export type Nodes = list.List<Node>;
|
|
13
12
|
export type Node = Element | string;
|
|
14
13
|
import * as list from '../types/list/module.f.mjs';
|
|
15
14
|
import * as f from '../types/function/module.f.mjs';
|
|
15
|
+
/** @typedef {string} Tag */
|
|
16
|
+
declare const voidTagList: readonly ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"];
|
|
17
|
+
export {};
|