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.
Files changed (55) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/crypto/README.md +3 -0
  4. package/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
  5. package/{secp → crypto/secp}/module.f.mjs +2 -2
  6. package/{sha2 → crypto/sha2}/module.f.mjs +4 -4
  7. package/{sha2 → crypto/sha2}/test.f.mjs +2 -2
  8. package/djs/module.f.mjs +4 -1
  9. package/djs/parser/module.f.mjs +122 -45
  10. package/djs/parser/test.f.mjs +30 -4
  11. package/djs/tokenizer/module.f.mjs +6 -2
  12. package/djs/tokenizer/test.f.mjs +34 -0
  13. package/html/module.f.mjs +18 -33
  14. package/html/test.f.mjs +6 -6
  15. package/issues/05-publish.md +17 -22
  16. package/issues/README.md +10 -2
  17. package/js/tokenizer/module.f.mjs +75 -26
  18. package/js/tokenizer/test.f.mjs +42 -0
  19. package/json/parser/test.f.mjs +6 -0
  20. package/jsr.json +4 -4
  21. package/nanvm-lib/src/extension.rs +1 -1
  22. package/nanvm-lib/src/nanenum.rs +22 -20
  23. package/out/{prime_field → crypto/prime_field}/module.f.d.mts +1 -1
  24. package/out/{prime_field → crypto/prime_field}/module.f.mjs +2 -2
  25. package/out/{secp → crypto/secp}/module.f.d.mts +1 -1
  26. package/out/{secp → crypto/secp}/module.f.mjs +2 -2
  27. package/out/{sha2 → crypto/sha2}/module.f.d.mts +3 -3
  28. package/out/{sha2 → crypto/sha2}/module.f.mjs +4 -4
  29. package/out/{sha2 → crypto/sha2}/test.f.mjs +2 -2
  30. package/out/djs/module.f.d.mts +1 -1
  31. package/out/djs/module.f.mjs +5 -1
  32. package/out/djs/parser/module.f.d.mts +1 -1
  33. package/out/djs/parser/module.f.mjs +105 -89
  34. package/out/djs/parser/test.f.d.mts +1 -0
  35. package/out/djs/parser/test.f.mjs +38 -4
  36. package/out/djs/tokenizer/module.f.d.mts +2 -2
  37. package/out/djs/tokenizer/module.f.mjs +6 -2
  38. package/out/djs/tokenizer/test.f.d.mts +1 -0
  39. package/out/djs/tokenizer/test.f.mjs +50 -0
  40. package/out/html/module.f.d.mts +8 -6
  41. package/out/html/module.f.mjs +17 -31
  42. package/out/html/test.f.mjs +5 -5
  43. package/out/js/tokenizer/module.f.d.mts +15 -3
  44. package/out/js/tokenizer/module.f.mjs +65 -22
  45. package/out/js/tokenizer/test.f.d.mts +1 -0
  46. package/out/js/tokenizer/test.f.mjs +62 -0
  47. package/out/json/parser/test.f.mjs +8 -0
  48. package/package.json +1 -1
  49. /package/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
  50. /package/{secp → crypto/secp}/test.f.mjs +0 -0
  51. /package/out/{prime_field → crypto/prime_field}/test.f.d.mts +0 -0
  52. /package/out/{prime_field → crypto/prime_field}/test.f.mjs +0 -0
  53. /package/out/{secp → crypto/secp}/test.f.d.mts +0 -0
  54. /package/out/{secp → crypto/secp}/test.f.mjs +0 -0
  55. /package/out/{sha2 → crypto/sha2}/test.f.d.mts +0 -0
@@ -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;
@@ -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': return state;
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': return state;
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': return state;
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': return state;
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': return state;
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': return state;
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': return state;
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': return state;
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': return true;
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
- if (token.kind === 'id') {
281
- return pushRef(state)(token.value);
282
- }
283
- if (token.kind === '[') {
284
- return startArray(state);
285
- }
286
- if (token.kind === '{') {
287
- return startObject(state);
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
- if (token.kind === 'id') {
300
- return pushRef(state)(token.value);
301
- }
302
- if (token.kind === '[') {
303
- return startArray(state);
304
- }
305
- if (token.kind === ']') {
306
- return endArray(state);
307
- }
308
- if (token.kind === '{') {
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
- if (token.kind === ']') {
319
- return endArray(state);
320
- }
321
- if (token.kind === ',') {
322
- return { ...state, valueState: '[,', top: state.top, stack: state.stack };
323
- }
324
- if (token.kind === 'ws') {
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
- if (token.kind === 'string') {
332
- return pushKey(state)(token.value);
333
- }
334
- if (token.kind === '}') {
335
- return endObject(state);
336
- }
337
- if (token.kind === 'ws') {
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
- if (token.kind === ':') {
345
- return { ...state, valueState: '{:', top: state.top, stack: state.stack };
346
- }
347
- if (token.kind === 'ws') {
348
- return state;
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
- if (token.kind === 'id') {
358
- return pushRef(state)(token.value);
359
- }
360
- if (token.kind === '[') {
361
- return startArray(state);
362
- }
363
- if (token.kind === '{') {
364
- return startObject(state);
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
- if (token.kind === '}') {
374
- return endObject(state);
375
- }
376
- if (token.kind === ',') {
377
- return { ...state, valueState: '{,', top: state.top, stack: state.stack };
378
- }
379
- if (token.kind === 'ws') {
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
- if (token.kind === 'string') {
387
- return pushKey(state)(token.value);
388
- }
389
- if (token.kind === 'ws') {
390
- return state;
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 { state: 'error', message: 'unexpected token' };
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':
@@ -8,5 +8,6 @@ declare namespace _default {
8
8
  let invalidWithConst: (() => void)[];
9
9
  let validWithArgs: (() => void)[];
10
10
  let invalidWithArgs: (() => void)[];
11
+ let comments: (() => void)[];
11
12
  }
12
13
  export default _default;
@@ -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
  }
@@ -2,5 +2,6 @@ declare namespace _default {
2
2
  let djs: (() => void)[];
3
3
  let id: (() => void)[];
4
4
  let keywords: (() => void)[];
5
+ let comments: (() => void)[];
5
6
  }
6
7
  export default _default;
@@ -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
  };
@@ -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 Element1 = readonly [Tag];
7
- export type Element2A = readonly [Tag, Attributes];
8
- export type Element2N = readonly [Tag, readonly Node[]];
9
- export type Element3 = readonly [Tag, Attributes, Nodes];
10
- export type Element = Element1 | Element2A | Element2N | Element3;
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 {};