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/html/module.f.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const { fromCharCode } = String;
|
|
|
12
12
|
const { entries } = Object;
|
|
13
13
|
/** @typedef {string} Tag */
|
|
14
14
|
// https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
|
15
|
-
const voidTagList = [
|
|
15
|
+
const voidTagList = /** @type {const} */ ([
|
|
16
16
|
'area',
|
|
17
17
|
'base',
|
|
18
18
|
'br',
|
|
@@ -27,20 +27,20 @@ const voidTagList = [
|
|
|
27
27
|
'source',
|
|
28
28
|
'track',
|
|
29
29
|
'wbr',
|
|
30
|
-
];
|
|
30
|
+
]);
|
|
31
|
+
/** @typedef {typeof voidTagList} VoidTagList */
|
|
32
|
+
/** @typedef {keyof voidTagList} VoidTag */
|
|
31
33
|
/** @type {(tag: string) => boolean} */
|
|
32
|
-
const isVoid = tag => voidTagList.includes(tag);
|
|
33
|
-
/** @typedef {readonly[Tag]} Element1*/
|
|
34
|
-
/** @typedef {readonly[Tag, Attributes]}
|
|
35
|
-
/** @typedef {
|
|
36
|
-
/** @typedef {readonly[Tag, Attributes, Nodes]} Element3*/
|
|
37
|
-
/** @typedef {Element1 | Element2A | Element2N | Element3} Element */
|
|
34
|
+
const isVoid = tag => voidTagList.includes(/** @type {any} */ (tag));
|
|
35
|
+
/** @typedef {readonly[Tag, ...Node[]]} Element1*/
|
|
36
|
+
/** @typedef {readonly[Tag, Attributes, ...Node[]]} Element2 */
|
|
37
|
+
/** @typedef {Element1 | Element2 } Element */
|
|
38
38
|
/**
|
|
39
39
|
* @typedef {{
|
|
40
40
|
* readonly[k in string]: string
|
|
41
41
|
* }} Attributes
|
|
42
42
|
*/
|
|
43
|
-
/** @typedef {list.List<Node>} Nodes */
|
|
43
|
+
// /** @typedef {list.List<Node>} Nodes */
|
|
44
44
|
/** @typedef {Element | string} Node */
|
|
45
45
|
/**
|
|
46
46
|
* https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html
|
|
@@ -64,31 +64,17 @@ const nodes = flatMap(node);
|
|
|
64
64
|
const attribute = ([name, value]) => flat([[' ', name, '="'], escape(value), ['"']]);
|
|
65
65
|
/** @type {(a: Attributes) => list.List<string>} */
|
|
66
66
|
const attributes = compose(entries)(flatMap(attribute));
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
/** @type {(
|
|
70
|
-
const element3 =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const [tag] = e;
|
|
74
|
-
return flat([open(e), isVoid(tag) ? [] : close(tag)]);
|
|
67
|
+
/** @type {(t: string) => (a: Attributes) => list.List<string>} */
|
|
68
|
+
const open = t => a => flat([[`<`, t], attributes(a), [`>`]]);
|
|
69
|
+
/** @type {(t: string) => (an: readonly[Attributes, readonly Node[]]) => list.List<string>} */
|
|
70
|
+
const element3 = t => ([a, n]) => {
|
|
71
|
+
const o = flat([[`<`, t], attributes(a), [`>`]]);
|
|
72
|
+
return isVoid(t) ? o : flat([o, nodes(n), ['</', t, '>']]);
|
|
75
73
|
};
|
|
76
74
|
/** @type {(element: Element) => list.List<string>} */
|
|
77
75
|
export const element = e => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return element2a([e[0], {}]);
|
|
81
|
-
}
|
|
82
|
-
case 2: {
|
|
83
|
-
const [tag, a] = e;
|
|
84
|
-
return a instanceof Array ?
|
|
85
|
-
element3([tag, {}, a]) :
|
|
86
|
-
element2a([tag, a]);
|
|
87
|
-
}
|
|
88
|
-
default: {
|
|
89
|
-
return element3(e);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
76
|
+
const [t, a, ...n] = e;
|
|
77
|
+
return element3(t)(a === undefined ? [{}, []] : typeof a === 'object' && !(a instanceof Array) ? [a, n] : [{}, [a, ...n]]);
|
|
92
78
|
};
|
|
93
79
|
export const html = compose(element)(listConcat(['<!DOCTYPE html>']));
|
|
94
80
|
export const htmlToString = compose(html)(stringConcat);
|
package/out/html/test.f.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as _ from './module.f.mjs';
|
|
2
2
|
export default {
|
|
3
3
|
empty: () => {
|
|
4
|
-
const r = _.htmlToString(['html'
|
|
4
|
+
const r = _.htmlToString(['html']);
|
|
5
5
|
if (r !== '<!DOCTYPE html><html></html>') {
|
|
6
|
-
throw r
|
|
6
|
+
throw `empty: ${r}`;
|
|
7
7
|
}
|
|
8
8
|
},
|
|
9
9
|
empty2: () => {
|
|
@@ -20,7 +20,7 @@ export default {
|
|
|
20
20
|
},
|
|
21
21
|
some: () => {
|
|
22
22
|
/** @type {_.Element} */
|
|
23
|
-
const x = ['div', {},
|
|
23
|
+
const x = ['div', {}, '<div>&</div>', ['a', { href: 'hello"' }]];
|
|
24
24
|
const s = _.htmlToString(x);
|
|
25
25
|
if (s !== '<!DOCTYPE html><div><div>&amp;</div><a href="hello""></a></div>') {
|
|
26
26
|
throw s;
|
|
@@ -28,7 +28,7 @@ export default {
|
|
|
28
28
|
},
|
|
29
29
|
some2: () => {
|
|
30
30
|
/** @type {_.Element} */
|
|
31
|
-
const x = ['div',
|
|
31
|
+
const x = ['div', '<div>&</div>', ['a', { href: 'hello"' }]];
|
|
32
32
|
const s = _.htmlToString(x);
|
|
33
33
|
if (s !== '<!DOCTYPE html><div><div>&amp;</div><a href="hello""></a></div>') {
|
|
34
34
|
throw s;
|
|
@@ -36,7 +36,7 @@ export default {
|
|
|
36
36
|
},
|
|
37
37
|
someVoid: () => {
|
|
38
38
|
/** @type {_.Element} */
|
|
39
|
-
const x = ['div', [
|
|
39
|
+
const x = ['div', ['br', { id: '5' }], '<div>&</div>', ['a', { href: 'hello"' }]];
|
|
40
40
|
const s = _.htmlToString(x);
|
|
41
41
|
if (s !== '<!DOCTYPE html><div><br id="5"><div>&amp;</div><a href="hello""></a></div>') {
|
|
42
42
|
throw s;
|
|
@@ -34,6 +34,9 @@ export type FalseToken = {
|
|
|
34
34
|
export type NullToken = {
|
|
35
35
|
readonly kind: "null";
|
|
36
36
|
};
|
|
37
|
+
export type UndefinedToken = {
|
|
38
|
+
readonly kind: "undefined";
|
|
39
|
+
};
|
|
37
40
|
export type KeywordToken = {
|
|
38
41
|
readonly kind: "arguments" | "await" | "break" | "case" | "catch" | "class" | "const" | "continue";
|
|
39
42
|
} | {
|
|
@@ -74,9 +77,13 @@ export type OperatorToken = {
|
|
|
74
77
|
} | {
|
|
75
78
|
readonly kind: "?" | "?." | "=>";
|
|
76
79
|
};
|
|
77
|
-
export type
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
export type CommentToken = {
|
|
81
|
+
readonly kind: "//" | "/*";
|
|
82
|
+
readonly value: string;
|
|
83
|
+
};
|
|
84
|
+
export type JsToken = KeywordToken | TrueToken | FalseToken | NullToken | WhitespaceToken | NewLineToken | StringToken | NumberToken | ErrorToken | IdToken | BigIntToken | UndefinedToken | OperatorToken | CommentToken;
|
|
85
|
+
export type TokenizerState = InitialState | ParseIdState | ParseStringState | ParseEscapeCharState | ParseUnicodeCharState | ParseNumberState | InvalidNumberState | ParseOperatorState | ParseWhitespaceState | ParseNewLineState | ParseCommentState | EofState;
|
|
86
|
+
export type ErrorMessage = "\" are missing" | "unescaped character" | "invalid hex value" | "unexpected character" | "invalid number" | "invalid token" | "*/ expected" | "unterminated string literal" | "eof";
|
|
80
87
|
export type InitialState = {
|
|
81
88
|
readonly kind: "initial";
|
|
82
89
|
};
|
|
@@ -105,6 +112,11 @@ export type ParseOperatorState = {
|
|
|
105
112
|
export type ParseMinusState = {
|
|
106
113
|
readonly kind: "-";
|
|
107
114
|
};
|
|
115
|
+
export type ParseCommentState = {
|
|
116
|
+
readonly kind: "//" | "/*" | "/**";
|
|
117
|
+
readonly value: string;
|
|
118
|
+
readonly newLine: boolean;
|
|
119
|
+
};
|
|
108
120
|
export type ParseUnicodeCharState = {
|
|
109
121
|
readonly kind: "unicodeChar";
|
|
110
122
|
readonly value: string;
|
|
@@ -54,6 +54,7 @@ leftCurlyBracket, rightCurlyBracket, dollarSign } = ascii.ascii;
|
|
|
54
54
|
/** @typedef {{readonly kind: 'true'}} TrueToken */
|
|
55
55
|
/** @typedef {{readonly kind: 'false'}} FalseToken */
|
|
56
56
|
/** @typedef {{readonly kind: 'null'}} NullToken */
|
|
57
|
+
/** @typedef {{readonly kind: 'undefined'}} UndefinedToken */
|
|
57
58
|
/**
|
|
58
59
|
* @typedef {|
|
|
59
60
|
* {readonly kind: 'arguments' | 'await' | 'break' | 'case' | 'catch' | 'class' | 'const' | 'continue' } |
|
|
@@ -85,6 +86,12 @@ leftCurlyBracket, rightCurlyBracket, dollarSign } = ascii.ascii;
|
|
|
85
86
|
* {readonly kind: '?' | '?.' | '=>'}
|
|
86
87
|
* } OperatorToken
|
|
87
88
|
*/
|
|
89
|
+
/**
|
|
90
|
+
* @typedef {{
|
|
91
|
+
* readonly kind: '//' | '/*'
|
|
92
|
+
* readonly value: string
|
|
93
|
+
* }} CommentToken
|
|
94
|
+
* */
|
|
88
95
|
/**
|
|
89
96
|
* @typedef {|
|
|
90
97
|
* KeywordToken |
|
|
@@ -98,7 +105,9 @@ leftCurlyBracket, rightCurlyBracket, dollarSign } = ascii.ascii;
|
|
|
98
105
|
* ErrorToken |
|
|
99
106
|
* IdToken |
|
|
100
107
|
* BigIntToken |
|
|
101
|
-
*
|
|
108
|
+
* UndefinedToken |
|
|
109
|
+
* OperatorToken |
|
|
110
|
+
* CommentToken
|
|
102
111
|
* } JsToken
|
|
103
112
|
*/
|
|
104
113
|
const rangeOneNine = range('19');
|
|
@@ -178,20 +187,22 @@ const rangeId = [digitRange, ...rangeIdStart];
|
|
|
178
187
|
* ParseNumberState |
|
|
179
188
|
* InvalidNumberState |
|
|
180
189
|
* ParseOperatorState |
|
|
181
|
-
* ParseMinusState |
|
|
182
190
|
* ParseWhitespaceState |
|
|
183
191
|
* ParseNewLineState |
|
|
192
|
+
* ParseCommentState |
|
|
184
193
|
* EofState
|
|
185
194
|
* } TokenizerState
|
|
186
195
|
*/
|
|
187
196
|
/**
|
|
188
197
|
* @typedef {|
|
|
189
|
-
|
|
198
|
+
* '" are missing' |
|
|
190
199
|
* 'unescaped character' |
|
|
191
200
|
* 'invalid hex value' |
|
|
192
201
|
* 'unexpected character' |
|
|
193
202
|
* 'invalid number' |
|
|
194
203
|
* 'invalid token' |
|
|
204
|
+
* '*\/ expected' |
|
|
205
|
+
* 'unterminated string literal' |
|
|
195
206
|
* 'eof'
|
|
196
207
|
* } ErrorMessage
|
|
197
208
|
*/
|
|
@@ -203,6 +214,13 @@ const rangeId = [digitRange, ...rangeIdStart];
|
|
|
203
214
|
/** @typedef {{ readonly kind: 'escapeChar', readonly value: string}} ParseEscapeCharState */
|
|
204
215
|
/** @typedef {{ readonly kind: 'op', readonly value: string}} ParseOperatorState */
|
|
205
216
|
/** @typedef {{ readonly kind: '-'}} ParseMinusState */
|
|
217
|
+
/**
|
|
218
|
+
* @typedef {{
|
|
219
|
+
* readonly kind: '//' | '/*' | '/**'
|
|
220
|
+
* readonly value: string
|
|
221
|
+
* readonly newLine: boolean
|
|
222
|
+
* }} ParseCommentState
|
|
223
|
+
*/
|
|
206
224
|
/**
|
|
207
225
|
* @typedef {{
|
|
208
226
|
* readonly kind: 'unicodeChar'
|
|
@@ -213,7 +231,7 @@ const rangeId = [digitRange, ...rangeIdStart];
|
|
|
213
231
|
*/
|
|
214
232
|
/**
|
|
215
233
|
* @typedef {{
|
|
216
|
-
* readonly kind: 'number'
|
|
234
|
+
* readonly kind: 'number'
|
|
217
235
|
* readonly numberKind: '0' | 'int' | '.' | 'fractional' | 'e' | 'e+' | 'e-' | 'expDigits' | 'bigint'
|
|
218
236
|
* readonly value: string
|
|
219
237
|
* readonly b: ParseNumberBuffer
|
|
@@ -352,6 +370,7 @@ const keywordEntries = [
|
|
|
352
370
|
['true', { kind: 'true' }],
|
|
353
371
|
['try', { kind: 'try' }],
|
|
354
372
|
['typeof', { kind: 'typeof' }],
|
|
373
|
+
['undefined', { kind: 'undefined' }],
|
|
355
374
|
['var', { kind: 'var' }],
|
|
356
375
|
['void', { kind: 'void' }],
|
|
357
376
|
['while', { kind: 'while' }],
|
|
@@ -431,8 +450,8 @@ const hasOperatorToken = op => at(op)(operatorMap) !== null;
|
|
|
431
450
|
const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpected character' }], state])([
|
|
432
451
|
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: 'int' }]),
|
|
433
452
|
rangeSetFunc(rangeIdStart)(() => input => [empty, { kind: 'id', value: fromCharCode(input) }]),
|
|
434
|
-
rangeSetFunc(rangeSetWhiteSpace)(
|
|
435
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
453
|
+
rangeSetFunc(rangeSetWhiteSpace)(() => () => [empty, { kind: 'ws' }]),
|
|
454
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }]),
|
|
436
455
|
rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
|
|
437
456
|
rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), b: startNumber(input), numberKind: '0' }]),
|
|
438
457
|
rangeSetFunc(rangeOpStart)(() => input => [empty, { kind: 'op', value: fromCharCode(input) }])
|
|
@@ -550,16 +569,11 @@ const invalidNumberStateOp = create(() => () => [empty, { kind: 'invalidNumber'
|
|
|
550
569
|
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]];
|
|
551
570
|
})
|
|
552
571
|
]);
|
|
553
|
-
/** @type {(state: ParseMinusState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
554
|
-
const parseMinusStateOp = create(() => input => tokenizeOp({ kind: 'op', value: '-' })(input))([
|
|
555
|
-
rangeFunc(one(fullStop))(() => input => tokenizeOp({ kind: 'invalidNumber' })(input)),
|
|
556
|
-
rangeFunc(one(digit0))(() => () => [empty, { kind: 'number', value: '-0', b: startNegativeNumber, numberKind: '0' }]),
|
|
557
|
-
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: appendChar('-')(input), b: addIntDigit(input)(startNegativeNumber), numberKind: 'int' }]),
|
|
558
|
-
]);
|
|
559
572
|
/** @type {(state: ParseStringState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
560
573
|
const parseStringStateOp = create(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }])([
|
|
561
574
|
rangeFunc(one(quotationMark))(state => () => [[{ kind: 'string', value: state.value }], { kind: 'initial' }]),
|
|
562
|
-
rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }])
|
|
575
|
+
rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }]),
|
|
576
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [[{ kind: 'error', message: 'unterminated string literal' }], { kind: 'nl' }])
|
|
563
577
|
]);
|
|
564
578
|
/** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
565
579
|
const parseEscapeDefault = state => input => {
|
|
@@ -610,20 +624,45 @@ const parseIdStateOp = create(parseIdDefault)([
|
|
|
610
624
|
/** @type {(state: ParseOperatorState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
611
625
|
const parseOperatorStateOp = state => input => {
|
|
612
626
|
const nextStateValue = appendChar(state.value)(input);
|
|
613
|
-
|
|
614
|
-
return [empty, { kind: '
|
|
615
|
-
|
|
616
|
-
|
|
627
|
+
switch (nextStateValue) {
|
|
628
|
+
case '//': return [empty, { kind: '//', value: '', newLine: false }];
|
|
629
|
+
case '/*': return [empty, { kind: '/*', value: '', newLine: false }];
|
|
630
|
+
default: {
|
|
631
|
+
if (hasOperatorToken(nextStateValue))
|
|
632
|
+
return [empty, { kind: 'op', value: nextStateValue }];
|
|
633
|
+
const next = tokenizeOp({ kind: 'initial' })(input);
|
|
634
|
+
return [{ first: getOperatorToken(state.value), tail: next[0] }, next[1]];
|
|
635
|
+
}
|
|
636
|
+
}
|
|
617
637
|
};
|
|
638
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
639
|
+
const parseSinglelineCommentStateOp = create(state => input => [empty, { ...state, value: appendChar(state.value)(input) }])([
|
|
640
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [[{ kind: '//', value: state.value }], { kind: 'nl' }])
|
|
641
|
+
]);
|
|
642
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
643
|
+
const parseMultilineCommentStateOp = create(state => input => [empty, { ...state, value: appendChar(state.value)(input) }])([
|
|
644
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, kind: '/**' }]),
|
|
645
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { ...state, value: appendChar(state.value)(input), newLine: true }]),
|
|
646
|
+
]);
|
|
647
|
+
/** @type {(state: ParseCommentState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
648
|
+
const parseMultilineCommentAsteriskStateOp = create(state => input => [empty, { ...state, kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input) }])([
|
|
649
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, value: appendChar(state.value)(asterisk) }]),
|
|
650
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input), newLine: true }]),
|
|
651
|
+
rangeFunc(one(solidus))(state => () => {
|
|
652
|
+
/** @type {list.List<JsToken>} */
|
|
653
|
+
const tokens = state.newLine ? [{ kind: '/*', value: state.value }, { kind: 'nl' }] : [{ kind: '/*', value: state.value }];
|
|
654
|
+
return [tokens, { kind: 'initial' }];
|
|
655
|
+
})
|
|
656
|
+
]);
|
|
618
657
|
/** @type {(state: ParseWhitespaceState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
619
|
-
const parseWhitespaceDefault =
|
|
658
|
+
const parseWhitespaceDefault = () => input => {
|
|
620
659
|
const next = tokenizeOp({ kind: 'initial' })(input);
|
|
621
660
|
return [{ first: { kind: 'ws' }, tail: next[0] }, next[1]];
|
|
622
661
|
};
|
|
623
662
|
/** @type {(state: ParseWhitespaceState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
624
663
|
const parseWhitespaceStateOp = create(parseWhitespaceDefault)([
|
|
625
664
|
rangeSetFunc(rangeSetWhiteSpace)(state => () => [empty, state]),
|
|
626
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
665
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }])
|
|
627
666
|
]);
|
|
628
667
|
/** @type {(state: ParseNewLineState) => (input: number) => readonly[list.List<JsToken>, TokenizerState]} */
|
|
629
668
|
const parseNewLineDefault = state => input => {
|
|
@@ -648,7 +687,9 @@ const tokenizeCharCodeOp = state => {
|
|
|
648
687
|
case 'invalidNumber': return invalidNumberStateOp(state);
|
|
649
688
|
case 'number': return parseNumberStateOp(state);
|
|
650
689
|
case 'op': return parseOperatorStateOp(state);
|
|
651
|
-
case '
|
|
690
|
+
case '//': return parseSinglelineCommentStateOp(state);
|
|
691
|
+
case '/*': return parseMultilineCommentStateOp(state);
|
|
692
|
+
case '/**': return parseMultilineCommentAsteriskStateOp(state);
|
|
652
693
|
case 'ws': return parseWhitespaceStateOp(state);
|
|
653
694
|
case 'nl': return parseNewLineStateOp(state);
|
|
654
695
|
case 'eof': return eofStateOp(state);
|
|
@@ -668,11 +709,13 @@ const tokenizeEofOp = state => {
|
|
|
668
709
|
case '.':
|
|
669
710
|
case 'e':
|
|
670
711
|
case 'e+':
|
|
671
|
-
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: '
|
|
712
|
+
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof', }];
|
|
672
713
|
default: return [[bufferToNumberToken(state)], { kind: 'eof' }];
|
|
673
714
|
}
|
|
674
715
|
case 'op': return [[getOperatorToken(state.value)], { kind: 'eof' }];
|
|
675
|
-
case '
|
|
716
|
+
case '//': return [[{ kind: '//', value: state.value }], { kind: 'eof' }];
|
|
717
|
+
case '/*':
|
|
718
|
+
case '/**': return [[{ kind: 'error', message: '*/ expected' }], { kind: 'eof', }];
|
|
676
719
|
case 'ws': return [[{ kind: 'ws' }], { kind: 'eof' }];
|
|
677
720
|
case 'nl': return [[{ kind: 'nl' }], { kind: 'eof' }];
|
|
678
721
|
case 'eof': return [[{ kind: 'error', message: 'eof' }], state];
|
|
@@ -124,6 +124,18 @@ export default {
|
|
|
124
124
|
throw result;
|
|
125
125
|
}
|
|
126
126
|
},
|
|
127
|
+
() => {
|
|
128
|
+
const result = stringify(tokenizeString('"\r"'));
|
|
129
|
+
if (result !== '[{"kind":"error","message":"unterminated string literal"},{"kind":"nl"},{"kind":"error","message":"\\" are missing"}]') {
|
|
130
|
+
throw result;
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
() => {
|
|
134
|
+
const result = stringify(tokenizeString('"\n null'));
|
|
135
|
+
if (result !== '[{"kind":"error","message":"unterminated string literal"},{"kind":"nl"},{"kind":"null"}]') {
|
|
136
|
+
throw result;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
127
139
|
() => {
|
|
128
140
|
const result = stringify(tokenizeString('"\\b\\f\\n\\r\\t"'));
|
|
129
141
|
if (result !== '[{"kind":"string","value":"\\b\\f\\n\\r\\t"}]') {
|
|
@@ -564,6 +576,12 @@ export default {
|
|
|
564
576
|
throw result;
|
|
565
577
|
}
|
|
566
578
|
},
|
|
579
|
+
() => {
|
|
580
|
+
const result = stringify(tokenizeString('undefined'));
|
|
581
|
+
if (result !== '[{"kind":"undefined"}]') {
|
|
582
|
+
throw result;
|
|
583
|
+
}
|
|
584
|
+
},
|
|
567
585
|
() => {
|
|
568
586
|
const result = stringify(tokenizeString('[null]'));
|
|
569
587
|
if (result !== '[{"kind":"["},{"kind":"null"},{"kind":"]"}]') {
|
|
@@ -840,5 +858,49 @@ export default {
|
|
|
840
858
|
throw result;
|
|
841
859
|
}
|
|
842
860
|
},
|
|
861
|
+
],
|
|
862
|
+
comments: [
|
|
863
|
+
() => {
|
|
864
|
+
const result = stringify(tokenizeString('//singleline comment'));
|
|
865
|
+
if (result !== '[{"kind":"//","value":"singleline comment"}]') {
|
|
866
|
+
throw result;
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
() => {
|
|
870
|
+
const result = stringify(tokenizeString('true//singleline comment\nfalse'));
|
|
871
|
+
if (result !== '[{"kind":"true"},{"kind":"//","value":"singleline comment"},{"kind":"nl"},{"kind":"false"}]') {
|
|
872
|
+
throw result;
|
|
873
|
+
}
|
|
874
|
+
},
|
|
875
|
+
() => {
|
|
876
|
+
const result = stringify(tokenizeString('/* multiline comment */'));
|
|
877
|
+
if (result !== '[{"kind":"/*","value":" multiline comment "}]') {
|
|
878
|
+
throw result;
|
|
879
|
+
}
|
|
880
|
+
},
|
|
881
|
+
() => {
|
|
882
|
+
const result = stringify(tokenizeString('/* multiline comment *'));
|
|
883
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') {
|
|
884
|
+
throw result;
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
() => {
|
|
888
|
+
const result = stringify(tokenizeString('/* multiline comment '));
|
|
889
|
+
if (result !== '[{"kind":"error","message":"*/ expected"}]') {
|
|
890
|
+
throw result;
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
() => {
|
|
894
|
+
const result = stringify(tokenizeString('/* multiline comment \n * **/'));
|
|
895
|
+
if (result !== '[{"kind":"/*","value":" multiline comment \\n * *"},{"kind":"nl"}]') {
|
|
896
|
+
throw result;
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
() => {
|
|
900
|
+
const result = stringify(tokenizeString('/* multiline comment *\n * **/'));
|
|
901
|
+
if (result !== '[{"kind":"/*","value":" multiline comment *\\n * *"},{"kind":"nl"}]') {
|
|
902
|
+
throw result;
|
|
903
|
+
}
|
|
904
|
+
},
|
|
843
905
|
]
|
|
844
906
|
};
|
|
@@ -317,5 +317,13 @@ export default {
|
|
|
317
317
|
throw result;
|
|
318
318
|
}
|
|
319
319
|
},
|
|
320
|
+
() => {
|
|
321
|
+
const tokenList = tokenizeString('undefined');
|
|
322
|
+
const obj = parser.parse(tokenList);
|
|
323
|
+
const result = stringify(obj);
|
|
324
|
+
if (result !== '["error","unexpected token"]') {
|
|
325
|
+
throw result;
|
|
326
|
+
}
|
|
327
|
+
},
|
|
320
328
|
]
|
|
321
329
|
};
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|