functionalscript 0.45.0 → 0.46.0
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/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +10 -0
- package/fjs/asn.1/proof.f.mjs +16 -0
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -3
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +28 -14
- package/fjs/bnf/descent/module.f.mjs +122 -77
- package/fjs/bnf/descent/proof.f.d.mts +2 -0
- package/fjs/bnf/descent/proof.f.mjs +117 -31
- package/fjs/bnf/descent/types.d.ts +12 -14
- package/fjs/bnf/ll1/module.f.d.mts +64 -22
- package/fjs/bnf/ll1/module.f.mjs +214 -154
- package/fjs/bnf/ll1/proof.f.d.mts +15 -2
- package/fjs/bnf/ll1/proof.f.mjs +323 -149
- package/fjs/bnf/ll1/types.d.ts +16 -24
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +1 -3
- package/fjs/cas/cli/proof.f.mjs +44 -33
- package/fjs/cas/evo/module.f.d.mts +64 -18
- package/fjs/cas/evo/module.f.mjs +148 -70
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +305 -223
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +129 -128
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/config/module.f.d.mts +2 -2
- package/fjs/ci/config/module.f.mjs +2 -2
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.mjs +2 -2
- package/fjs/ci/proof.f.mjs +9 -5
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.mjs +17 -16
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/types.d.ts +1 -1
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +1 -0
- package/fjs/crypto/sha2/proof.f.mjs +24 -0
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/dev/module.f.d.mts +13 -4
- package/fjs/dev/module.f.mjs +56 -27
- package/fjs/dev/update/module.f.d.mts +9 -4
- package/fjs/dev/update/module.f.mjs +14 -10
- package/fjs/dev/update/proof.f.d.mts +1 -3
- package/fjs/dev/update/proof.f.mjs +10 -5
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +13 -3
- package/fjs/djs/parser/module.f.mjs +117 -16
- package/fjs/djs/parser/proof.f.d.mts +5 -1
- package/fjs/djs/parser/proof.f.mjs +274 -12
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +18 -2
- package/fjs/djs/proof.f.mjs +187 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +61 -15
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +99 -60
- package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
- package/fjs/djs/tokenizer/proof.f.mjs +74 -67
- package/fjs/djs/transpiler/module.f.d.mts +12 -7
- package/fjs/djs/transpiler/module.f.mjs +82 -56
- package/fjs/djs/transpiler/types.d.ts +7 -3
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +14 -11
- package/fjs/effects/list/module.f.mjs +13 -11
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +2 -1
- package/fjs/effects/memory/module.f.mjs +3 -4
- package/fjs/effects/memory/proof.f.mjs +13 -7
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +20 -4
- package/fjs/effects/mock/module.f.mjs +37 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +4 -2
- package/fjs/effects/module.f.d.mts +466 -280
- package/fjs/effects/module.f.mjs +537 -299
- package/fjs/effects/module.mjs +2 -1
- package/fjs/effects/node/memory/module.d.mts +4 -2
- package/fjs/effects/node/memory/module.mjs +6 -3
- package/fjs/effects/node/memory/proof.mjs +10 -4
- package/fjs/effects/node/module.d.mts +4 -3
- package/fjs/effects/node/module.f.d.mts +168 -33
- package/fjs/effects/node/module.f.mjs +256 -52
- package/fjs/effects/node/module.mjs +57 -34
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +18 -4
- package/fjs/effects/node/virtual/module.f.mjs +110 -68
- package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
- package/fjs/effects/node/virtual/proof.f.mjs +190 -9
- package/fjs/effects/proof.f.d.mts +69 -37
- package/fjs/effects/proof.f.mjs +410 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/module.f.d.mts +19 -12
- package/fjs/emergent_testing/module.f.mjs +93 -33
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +166 -32
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +2 -0
- package/fjs/fsm/proof.f.mjs +83 -114
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/js/keywords/proof.f.d.mts +3 -0
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +26 -6
- package/fjs/js/tokenizer/module.f.mjs +145 -159
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +4 -4
- package/fjs/mcp/module.f.mjs +6 -6
- package/fjs/mcp/proof.f.d.mts +5 -3
- package/fjs/mcp/proof.f.mjs +112 -46
- package/fjs/media/html/module.f.mjs +1 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +114 -70
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +33 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.mjs +9 -9
- package/fjs/media/json/schema/module.f.mjs +3 -13
- package/fjs/media/json/schema/proof.f.d.mts +0 -1
- package/fjs/media/json/schema/proof.f.mjs +1 -2
- package/fjs/media/json/serializer/module.f.d.mts +32 -1
- package/fjs/media/json/serializer/module.f.mjs +64 -2
- package/fjs/media/json/tokenizer/module.f.mjs +7 -3
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +78 -7
- package/fjs/media/revision/module.f.mjs +119 -12
- package/fjs/media/revision/proof.f.d.mts +10 -0
- package/fjs/media/revision/proof.f.mjs +88 -0
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +33 -15
- package/fjs/media/type/module.f.mjs +35 -29
- package/fjs/media/type/proof.f.d.mts +2 -1
- package/fjs/media/type/proof.f.mjs +30 -10
- package/fjs/module.f.mjs +29 -8
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/proof.f.d.mts +3 -3
- package/fjs/proof.f.mjs +36 -10
- package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
- package/fjs/protocol/json_rpc/module.f.mjs +3 -3
- package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +13 -4
- package/fjs/protocol/mcp/proof.f.mjs +193 -61
- package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
- package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
- package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +0 -1
- package/fjs/sul/id/module.f.mjs +2 -3
- package/fjs/sul/level/hash/module.f.mjs +2 -1
- package/fjs/sul/level/hash/proof.f.mjs +2 -2
- package/fjs/sul/module.f.mjs +18 -13
- package/fjs/text/code_point/module.f.d.mts +8 -0
- package/fjs/text/code_point/module.f.mjs +8 -1
- package/fjs/text/code_point/proof.f.d.mts +1 -0
- package/fjs/text/code_point/proof.f.mjs +11 -0
- package/fjs/text/sgr/module.f.d.mts +4 -6
- package/fjs/text/sgr/module.f.mjs +6 -7
- package/fjs/text/utf16/module.f.mjs +7 -2
- package/fjs/text/utf16/proof.f.mjs +3 -3
- package/fjs/text/utf8/module.f.mjs +4 -2
- package/fjs/types/array/module.f.mjs +14 -2
- package/fjs/types/bit_vec/module.f.d.mts +0 -2
- package/fjs/types/bit_vec/module.f.mjs +46 -32
- package/fjs/types/bit_vec/proof.f.mjs +2 -2
- package/fjs/types/btree/remove/module.f.mjs +1 -1
- package/fjs/types/btree/set/module.f.mjs +9 -11
- package/fjs/types/btree/set/proof.f.mjs +12 -0
- package/fjs/types/byte_set/module.f.d.mts +11 -4
- package/fjs/types/byte_set/module.f.mjs +14 -6
- package/fjs/types/byte_set/proof.f.mjs +7 -7
- package/fjs/types/function/compare/module.f.mjs +10 -3
- package/fjs/types/list/module.f.d.mts +1 -1
- package/fjs/types/list/module.f.mjs +1 -1
- package/fjs/types/nullable/module.f.d.mts +18 -4
- package/fjs/types/nullable/module.f.mjs +21 -4
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/object/module.f.d.mts +12 -2
- package/fjs/types/object/module.f.mjs +11 -1
- package/fjs/types/patricia_trie/module.f.mjs +26 -11
- package/fjs/types/result/module.f.d.mts +3 -3
- package/fjs/types/result/module.f.mjs +3 -3
- package/fjs/types/rtti/common/module.f.d.mts +25 -28
- package/fjs/types/rtti/common/module.f.mjs +36 -32
- package/fjs/types/rtti/common/proof.f.mjs +5 -5
- package/fjs/types/rtti/data/module.f.d.mts +14 -0
- package/fjs/types/rtti/data/module.f.mjs +25 -2
- package/fjs/types/rtti/data/proof.f.d.mts +1 -0
- package/fjs/types/rtti/data/proof.f.mjs +25 -2
- package/fjs/types/rtti/parse/module.f.d.mts +24 -14
- package/fjs/types/rtti/parse/module.f.mjs +37 -28
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +33 -14
- package/fjs/types/rtti/proof.f.mjs +3 -1
- package/fjs/types/rtti/ts/module.f.mjs +13 -17
- package/fjs/types/rtti/ts/types.d.ts +14 -1
- package/fjs/types/sorted_set/module.f.d.mts +18 -0
- package/fjs/types/sorted_set/module.f.mjs +22 -0
- package/fjs/types/sorted_set/proof.f.d.mts +1 -0
- package/fjs/types/sorted_set/proof.f.mjs +16 -1
- package/fjs/types/uint8array/module.f.d.mts +1 -1
- package/fjs/types/uint8array/module.f.mjs +1 -1
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +4 -7
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +2 -2
- package/fjs/dev/package_json/module.f.d.mts +0 -39
- package/fjs/dev/package_json/module.f.mjs +0 -40
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/effects/eff/module.f.d.mts +0 -20
- package/fjs/effects/eff/module.f.mjs +0 -70
- package/fjs/effects/eff/proof.f.d.mts +0 -15
- package/fjs/effects/eff/proof.f.mjs +0 -69
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/types/rtti/validate/module.f.d.mts +0 -41
- package/fjs/types/rtti/validate/module.f.mjs +0 -171
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JavaScript tokenizer built as a range-map state machine over code points,
|
|
3
3
|
* producing tokens for keywords, identifiers, punctuators, comments, strings,
|
|
4
|
-
* and numeric literals
|
|
4
|
+
* and numeric literals.
|
|
5
|
+
*
|
|
6
|
+
* Numeric scanning is lexeme-first: a `number` token carries the exact source
|
|
7
|
+
* text and no derived numeric value, so tokenization stays bounded by the
|
|
8
|
+
* input and never fails because a coefficient or exponent is too large for a
|
|
9
|
+
* runtime numeric type.
|
|
5
10
|
*
|
|
6
11
|
* @module
|
|
7
12
|
*
|
|
8
|
-
* @import { Scan, StateScan } from '../../types/function/operator/types.ts'
|
|
9
|
-
* @import {
|
|
13
|
+
* @import { Reduce, Scan, StateScan } from '../../types/function/operator/types.ts'
|
|
14
|
+
* @import { RangeMerge } from '../../types/range_map/types.ts'
|
|
10
15
|
* @import { List } from '../../types/list/types.ts'
|
|
11
16
|
* @import { Entry } from '../../types/ordered_map/types.ts'
|
|
12
17
|
* @import { Range as NumberRange } from '../../types/range/types.ts'
|
|
13
|
-
* @import {
|
|
18
|
+
* @import { JsToken, TokenMetadata, JsTokenWithMetadata, _TokenizerStateWithMetadata, _TokenizerState, _ErrorMessage, _InitialState, _ParseIdState, _ParseWhitespaceState, _ParseNewLineState, _ParseStringState, _ParseEscapeCharState, _ParseOperatorState, _ParseCommentState, _ParseUnicodeCharState, _ParseNumberState, _InvalidNumberState, _EofState, _CharCodeOrEof, _ToToken, _CreateToToken, _RangeFunc, _RangeMapToToken, TriviaKind, } from './types.ts'
|
|
14
19
|
*/
|
|
15
20
|
|
|
16
21
|
import { strictEqual } from '../../types/function/operator/module.f.mjs'
|
|
17
22
|
import { merge, fromRange, get } from '../../types/range_map/module.f.mjs'
|
|
18
23
|
import { empty, stateScan, flat, toArray, reduce as listReduce, scan, map as listMap } from '../../types/list/module.f.mjs'
|
|
24
|
+
import { keywords } from '../keywords/module.f.mjs'
|
|
19
25
|
import { at, fromEntries } from '../../types/ordered_map/module.f.mjs'
|
|
20
26
|
import { one } from '../../types/range/module.f.mjs'
|
|
21
27
|
import {
|
|
@@ -76,7 +82,7 @@ import {
|
|
|
76
82
|
rightCurlyBracket,
|
|
77
83
|
dollarSign
|
|
78
84
|
} from '../../text/ascii/module.f.mjs'
|
|
79
|
-
import { todo, assertEq } from '../../asserts/module.f.mjs'
|
|
85
|
+
import { todo, assertEq, assertStructurallySame } from '../../asserts/module.f.mjs'
|
|
80
86
|
|
|
81
87
|
const { fromCharCode } = String
|
|
82
88
|
|
|
@@ -156,16 +162,19 @@ const rangeId = [digitRange, ...rangeIdStart]
|
|
|
156
162
|
const appendChar = old => input => `${old}${fromCharCode(input)}`
|
|
157
163
|
|
|
158
164
|
/**
|
|
159
|
-
* @
|
|
160
|
-
* @param {_CreateToToken<T>} def
|
|
161
|
-
* @returns {(a: _CreateToToken<T>) => (b: _CreateToToken<T>) => _CreateToToken<T>}
|
|
165
|
+
* @type {<T>(a: T) => Reduce<T>}
|
|
162
166
|
*/
|
|
163
|
-
const
|
|
167
|
+
const unionX = def => a => b => {
|
|
164
168
|
if (a === def || a === b) { return b }
|
|
165
169
|
if (b === def) { return a }
|
|
166
170
|
throw [a, b]
|
|
167
171
|
}
|
|
168
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @type {<T>(a: _CreateToToken<T>) => Reduce<_CreateToToken<T>>}
|
|
175
|
+
*/
|
|
176
|
+
const union = unionX
|
|
177
|
+
|
|
169
178
|
/**
|
|
170
179
|
* @template T
|
|
171
180
|
* @param {_CreateToToken<T>} def
|
|
@@ -228,83 +237,32 @@ const create = def => a => {
|
|
|
228
237
|
return v => c => x(c)(v)(c)
|
|
229
238
|
}
|
|
230
239
|
|
|
231
|
-
/**
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
/** @type {(s: _ParseNumberState) => JsToken} */
|
|
247
|
-
const bufferToNumberToken = ({ numberKind, value, b }) => {
|
|
248
|
-
if (numberKind === 'bigint')
|
|
249
|
-
return { kind: 'bigint', value: b.s * b.m }
|
|
250
|
-
return { kind: 'number', value: value, bf: [b.s * b.m, b.f + b.es * b.e] }
|
|
251
|
-
}
|
|
240
|
+
/**
|
|
241
|
+
* Turns a completed numeric scanning state into its token.
|
|
242
|
+
*
|
|
243
|
+
* A `number` token carries the lexeme and nothing else — deriving a numeric
|
|
244
|
+
* value is each consumer's own policy, so no valid literal can fail to
|
|
245
|
+
* tokenize because its coefficient or exponent exceeds a runtime numeric
|
|
246
|
+
* limit. A `bigint` literal is the one case where the value *is* the token:
|
|
247
|
+
* `123n` means that bigint, so it is constructed here from the same lexeme.
|
|
248
|
+
*
|
|
249
|
+
* @type {(s: _ParseNumberState) => JsToken}
|
|
250
|
+
*/
|
|
251
|
+
const stateToNumberToken = ({ numberKind, value }) =>
|
|
252
|
+
numberKind === 'bigint'
|
|
253
|
+
? { kind: 'bigint', value: BigInt(value) }
|
|
254
|
+
: { kind: 'number', value }
|
|
252
255
|
|
|
253
256
|
/**
|
|
254
|
-
*
|
|
257
|
+
* Derived from the one source of truth for JavaScript keywords,
|
|
258
|
+
* `fjs/js/keywords` — FunctionalScript is a strict subset of JavaScript, so
|
|
259
|
+
* the tokenizer recognizes exactly that module's `keywords`.
|
|
255
260
|
*/
|
|
256
261
|
/** @type {List<Entry<JsToken>>} */
|
|
257
|
-
const keywordEntries =
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
[
|
|
261
|
-
['case', { kind: 'case' }],
|
|
262
|
-
['catch', { kind: 'catch' }],
|
|
263
|
-
['class', { kind: 'class' }],
|
|
264
|
-
['const', { kind: 'const' }],
|
|
265
|
-
['continue', { kind: 'continue' }],
|
|
266
|
-
['debugger', { kind: 'debugger' }],
|
|
267
|
-
['default', { kind: 'default' }],
|
|
268
|
-
['delete', { kind: 'delete' }],
|
|
269
|
-
['do', { kind: 'do' }],
|
|
270
|
-
['else', { kind: 'else' }],
|
|
271
|
-
['enum', { kind: 'enum' }],
|
|
272
|
-
['eval', { kind: 'eval' }],
|
|
273
|
-
['export', { kind: 'export' }],
|
|
274
|
-
['extends', { kind: 'extends' }],
|
|
275
|
-
['false', { kind: 'false' }],
|
|
276
|
-
['finally', { kind: 'finally' }],
|
|
277
|
-
['for', { kind: 'for' }],
|
|
278
|
-
['function', { kind: 'function' }],
|
|
279
|
-
['if', { kind: 'if' }],
|
|
280
|
-
['implements', { kind: 'implements' }],
|
|
281
|
-
['import', { kind: 'import' }],
|
|
282
|
-
['in', { kind: 'in' }],
|
|
283
|
-
['instanceof', { kind: 'instanceof' }],
|
|
284
|
-
['interface', { kind: 'interface' }],
|
|
285
|
-
['let', { kind: 'let' }],
|
|
286
|
-
['new', { kind: 'new' }],
|
|
287
|
-
['null', { kind: 'null' }],
|
|
288
|
-
['package', { kind: 'package' }],
|
|
289
|
-
['private', { kind: 'private' }],
|
|
290
|
-
['protected', { kind: 'protected' }],
|
|
291
|
-
['public', { kind: 'public' }],
|
|
292
|
-
['return', { kind: 'return' }],
|
|
293
|
-
['static', { kind: 'static' }],
|
|
294
|
-
['super', { kind: 'super' }],
|
|
295
|
-
['switch', { kind: 'switch' }],
|
|
296
|
-
['this', { kind: 'this' }],
|
|
297
|
-
['throw', { kind: 'throw' }],
|
|
298
|
-
['true', { kind: 'true' }],
|
|
299
|
-
['try', { kind: 'try' }],
|
|
300
|
-
['typeof', { kind: 'typeof' }],
|
|
301
|
-
['undefined', { kind: 'undefined' }],
|
|
302
|
-
['var', { kind: 'var' }],
|
|
303
|
-
['void', { kind: 'void' }],
|
|
304
|
-
['while', { kind: 'while' }],
|
|
305
|
-
['with', { kind: 'with' }],
|
|
306
|
-
['yield', { kind: 'yield' }],
|
|
307
|
-
]
|
|
262
|
+
const keywordEntries = keywords.map(kind =>
|
|
263
|
+
// every keyword kind is a `JsToken` kind by construction: `_KeywordToken`
|
|
264
|
+
// derives its kinds from this same `keywords` list
|
|
265
|
+
[kind, /** @type {JsToken} */ ({ kind })])
|
|
308
266
|
|
|
309
267
|
const keywordMap = fromEntries(keywordEntries)
|
|
310
268
|
|
|
@@ -383,20 +341,20 @@ const hasOperatorToken = op => at(op)(operatorMap) !== null
|
|
|
383
341
|
|
|
384
342
|
/** @type {(state: _InitialState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
385
343
|
const initialStateOp = create(
|
|
386
|
-
|
|
344
|
+
state => () => [[{ kind: 'error', message: 'unexpected character' }], state]
|
|
387
345
|
)([
|
|
388
|
-
rangeFunc(rangeOneNine)(
|
|
389
|
-
rangeSetFunc(rangeIdStart)(
|
|
390
|
-
rangeSetFunc(rangeSetWhiteSpace)(
|
|
391
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
392
|
-
rangeFunc(one(quotationMark))(
|
|
393
|
-
rangeFunc(one(digit0))(
|
|
394
|
-
rangeSetFunc(rangeOpStart)(
|
|
346
|
+
rangeFunc(rangeOneNine)(() => input => [empty, { kind: 'number', value: fromCharCode(input), numberKind: 'int' }]),
|
|
347
|
+
rangeSetFunc(rangeIdStart)(() => input => [empty, { kind: 'id', value: fromCharCode(input) }]),
|
|
348
|
+
rangeSetFunc(rangeSetWhiteSpace)(() => () => [empty, { kind: 'ws' }]),
|
|
349
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [empty, { kind: 'nl' }]),
|
|
350
|
+
rangeFunc(one(quotationMark))(() => () => [empty, { kind: 'string', value: '' }]),
|
|
351
|
+
rangeFunc(one(digit0))(() => input => [empty, { kind: 'number', value: fromCharCode(input), numberKind: '0' }]),
|
|
352
|
+
rangeSetFunc(rangeOpStart)(() => input => [empty, { kind: 'op', value: fromCharCode(input) }])
|
|
395
353
|
])
|
|
396
354
|
|
|
397
355
|
/** @type {_CreateToToken<_ParseNumberState>} */
|
|
398
356
|
const invalidNumberToToken = () => input => {
|
|
399
|
-
const next =
|
|
357
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
400
358
|
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
401
359
|
}
|
|
402
360
|
|
|
@@ -404,36 +362,36 @@ const invalidNumberToToken = () => input => {
|
|
|
404
362
|
const fullStopToToken = state => input => {
|
|
405
363
|
switch (state.numberKind) {
|
|
406
364
|
case '0':
|
|
407
|
-
case 'int': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
408
|
-
default: return
|
|
365
|
+
case 'int': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: '.' }]
|
|
366
|
+
default: return tokenizeCharCodeOp(input, { kind: 'invalidNumber' })
|
|
409
367
|
}
|
|
410
368
|
}
|
|
411
369
|
|
|
412
370
|
/** @type {_CreateToToken<_ParseNumberState>} */
|
|
413
371
|
const digit0ToToken = state => input => {
|
|
414
372
|
switch (state.numberKind) {
|
|
415
|
-
case '0': return
|
|
373
|
+
case '0': return tokenizeCharCodeOp(input, { kind: 'invalidNumber' })
|
|
416
374
|
case '.':
|
|
417
|
-
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
375
|
+
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'fractional' }]
|
|
418
376
|
case 'e':
|
|
419
377
|
case 'e+':
|
|
420
378
|
case 'e-':
|
|
421
|
-
case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
422
|
-
default: return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
379
|
+
case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'expDigits' }]
|
|
380
|
+
default: return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: state.numberKind }]
|
|
423
381
|
}
|
|
424
382
|
}
|
|
425
383
|
|
|
426
384
|
/** @type {_CreateToToken<_ParseNumberState>} */
|
|
427
385
|
const digit19ToToken = state => input => {
|
|
428
386
|
switch (state.numberKind) {
|
|
429
|
-
case '0': return
|
|
387
|
+
case '0': return tokenizeCharCodeOp(input, { kind: 'invalidNumber' })
|
|
430
388
|
case '.':
|
|
431
|
-
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
389
|
+
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'fractional' }]
|
|
432
390
|
case 'e':
|
|
433
391
|
case 'e+':
|
|
434
392
|
case 'e-':
|
|
435
|
-
case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
436
|
-
default: return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
393
|
+
case 'expDigits': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'expDigits' }]
|
|
394
|
+
default: return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'int' }]
|
|
437
395
|
}
|
|
438
396
|
}
|
|
439
397
|
|
|
@@ -442,15 +400,15 @@ const expToToken = state => input => {
|
|
|
442
400
|
switch (state.numberKind) {
|
|
443
401
|
case '0':
|
|
444
402
|
case 'int':
|
|
445
|
-
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
446
|
-
default: return
|
|
403
|
+
case 'fractional': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e' }]
|
|
404
|
+
default: return tokenizeCharCodeOp(input, { kind: 'invalidNumber' })
|
|
447
405
|
}
|
|
448
406
|
}
|
|
449
407
|
|
|
450
408
|
/** @type {_CreateToToken<_ParseNumberState>} */
|
|
451
409
|
const hyphenMinusToToken = state => input => {
|
|
452
410
|
switch (state.numberKind) {
|
|
453
|
-
case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
411
|
+
case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e-' }]
|
|
454
412
|
default: return terminalToToken(state)(input)
|
|
455
413
|
}
|
|
456
414
|
}
|
|
@@ -458,8 +416,8 @@ const hyphenMinusToToken = state => input => {
|
|
|
458
416
|
/** @type {_CreateToToken<_ParseNumberState>} */
|
|
459
417
|
const plusSignToToken = state => input => {
|
|
460
418
|
switch (state.numberKind) {
|
|
461
|
-
case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input),
|
|
462
|
-
default: return
|
|
419
|
+
case 'e': return [empty, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e+' }]
|
|
420
|
+
default: return tokenizeCharCodeOp(input, { kind: 'invalidNumber' })
|
|
463
421
|
}
|
|
464
422
|
}
|
|
465
423
|
|
|
@@ -471,13 +429,13 @@ const terminalToToken = state => input => {
|
|
|
471
429
|
case 'e+':
|
|
472
430
|
case 'e-':
|
|
473
431
|
{
|
|
474
|
-
const next =
|
|
432
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
475
433
|
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
476
434
|
}
|
|
477
435
|
default:
|
|
478
436
|
{
|
|
479
|
-
const next =
|
|
480
|
-
return [{ first:
|
|
437
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
438
|
+
return [{ first: stateToNumberToken(state), tail: next[0] }, next[1]]
|
|
481
439
|
}
|
|
482
440
|
}
|
|
483
441
|
}
|
|
@@ -488,11 +446,11 @@ const bigintToToken = state => input => {
|
|
|
488
446
|
case '0':
|
|
489
447
|
case 'int':
|
|
490
448
|
{
|
|
491
|
-
return [empty, { kind: 'number', value: state.value,
|
|
449
|
+
return [empty, { kind: 'number', value: state.value, numberKind: 'bigint' }]
|
|
492
450
|
}
|
|
493
451
|
default:
|
|
494
452
|
{
|
|
495
|
-
const next =
|
|
453
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
496
454
|
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
497
455
|
}
|
|
498
456
|
}
|
|
@@ -512,12 +470,12 @@ const parseNumberStateOp = create(invalidNumberToToken)([
|
|
|
512
470
|
|
|
513
471
|
/** @type {(state: _InvalidNumberState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
514
472
|
const invalidNumberStateOp = create(
|
|
515
|
-
|
|
473
|
+
() => () => [empty, { kind: 'invalidNumber' }]
|
|
516
474
|
)([
|
|
517
|
-
rangeSetFunc(rangeSetTerminalForNumber)(
|
|
518
|
-
const next =
|
|
475
|
+
rangeSetFunc(rangeSetTerminalForNumber)(() => input => {
|
|
476
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
519
477
|
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
520
|
-
})
|
|
478
|
+
})
|
|
521
479
|
])
|
|
522
480
|
|
|
523
481
|
/** @type {readonly NumberRange[]} */
|
|
@@ -529,34 +487,34 @@ const rangeSetStringControl = [
|
|
|
529
487
|
|
|
530
488
|
/** @type {(state: _ParseStringState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
531
489
|
const parseStringStateOp = create(
|
|
532
|
-
|
|
490
|
+
state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }]
|
|
533
491
|
)([
|
|
534
|
-
rangeFunc(one(quotationMark))(
|
|
535
|
-
rangeFunc(one(reverseSolidus))(
|
|
536
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
537
|
-
rangeSetFunc(rangeSetStringControl)(
|
|
492
|
+
rangeFunc(one(quotationMark))(state => () => [[{ kind: 'string', value: state.value }], { kind: 'initial' }]),
|
|
493
|
+
rangeFunc(one(reverseSolidus))(state => () => [empty, { kind: 'escapeChar', value: state.value }]),
|
|
494
|
+
rangeSetFunc(rangeSetNewLine)(() => () => [[{ kind: 'error', message: 'unterminated string literal' }], { kind: 'nl' }]),
|
|
495
|
+
rangeSetFunc(rangeSetStringControl)(state => () => [[{ kind: 'error', message: 'unescaped control character in string' }], { kind: 'string', value: state.value }])
|
|
538
496
|
])
|
|
539
497
|
|
|
540
498
|
/** @type {_CreateToToken<_ParseEscapeCharState>} */
|
|
541
499
|
const parseEscapeDefault = state => input => {
|
|
542
|
-
const next =
|
|
500
|
+
const next = tokenizeCharCodeOp(input, { kind: 'string', value: state.value })
|
|
543
501
|
return [{ first: { kind: 'error', message: 'unescaped character' }, tail: next[0] }, next[1]]
|
|
544
502
|
}
|
|
545
503
|
|
|
546
504
|
/** @type {(state: _ParseEscapeCharState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
547
505
|
const parseEscapeCharStateOp = create(parseEscapeDefault)([
|
|
548
|
-
rangeSetFunc([one(quotationMark), one(reverseSolidus), one(solidus)])(
|
|
549
|
-
rangeFunc(one(latinSmallLetterB))(
|
|
550
|
-
rangeFunc(one(latinSmallLetterF))(
|
|
551
|
-
rangeFunc(one(latinSmallLetterN))(
|
|
552
|
-
rangeFunc(one(latinSmallLetterR))(
|
|
553
|
-
rangeFunc(one(latinSmallLetterT))(
|
|
554
|
-
rangeFunc(one(latinSmallLetterU))(
|
|
506
|
+
rangeSetFunc([one(quotationMark), one(reverseSolidus), one(solidus)])(state => input => [empty, { kind: 'string', value: appendChar(state.value)(input) }]),
|
|
507
|
+
rangeFunc(one(latinSmallLetterB))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(backspace) }]),
|
|
508
|
+
rangeFunc(one(latinSmallLetterF))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ff) }]),
|
|
509
|
+
rangeFunc(one(latinSmallLetterN))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(lf) }]),
|
|
510
|
+
rangeFunc(one(latinSmallLetterR))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(cr) }]),
|
|
511
|
+
rangeFunc(one(latinSmallLetterT))(state => () => [empty, { kind: 'string', value: appendChar(state.value)(ht) }]),
|
|
512
|
+
rangeFunc(one(latinSmallLetterU))(state => () => [empty, { kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0 }]),
|
|
555
513
|
])
|
|
556
514
|
|
|
557
515
|
/** @type {_CreateToToken<_ParseUnicodeCharState>} */
|
|
558
516
|
const parseUnicodeCharDefault = state => input => {
|
|
559
|
-
const next =
|
|
517
|
+
const next = tokenizeCharCodeOp(input, { kind: 'string', value: state.value })
|
|
560
518
|
return [{ first: { kind: 'error', message: 'invalid hex value' }, tail: next[0] }, next[1]]
|
|
561
519
|
}
|
|
562
520
|
|
|
@@ -582,13 +540,13 @@ const idToToken = s => at(s)(keywordMap) ?? { kind: 'id', value: s }
|
|
|
582
540
|
/** @type {_CreateToToken<_ParseIdState>} */
|
|
583
541
|
const parseIdDefault = state => input => {
|
|
584
542
|
const keyWordToken = idToToken(state.value)
|
|
585
|
-
const next =
|
|
543
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
586
544
|
return [{ first: keyWordToken, tail: next[0] }, next[1]]
|
|
587
545
|
}
|
|
588
546
|
|
|
589
547
|
/** @type {(state: _ParseIdState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
590
548
|
const parseIdStateOp = create(parseIdDefault)([
|
|
591
|
-
rangeSetFunc(rangeId)(
|
|
549
|
+
rangeSetFunc(rangeId)(state => input => [empty, { kind: 'id', value: appendChar(state.value)(input) }])
|
|
592
550
|
])
|
|
593
551
|
|
|
594
552
|
/** @type {(state: _ParseOperatorState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
@@ -600,7 +558,7 @@ const parseOperatorStateOp = state => input => {
|
|
|
600
558
|
default: {
|
|
601
559
|
if (hasOperatorToken(nextStateValue))
|
|
602
560
|
return [empty, { kind: 'op', value: nextStateValue }]
|
|
603
|
-
const next =
|
|
561
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
604
562
|
return [{ first: getOperatorToken(state.value), tail: next[0] }, next[1]]
|
|
605
563
|
}
|
|
606
564
|
}
|
|
@@ -608,59 +566,81 @@ const parseOperatorStateOp = state => input => {
|
|
|
608
566
|
|
|
609
567
|
/** @type {(state: _ParseCommentState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
610
568
|
const parseSinglelineCommentStateOp = create(
|
|
611
|
-
|
|
569
|
+
state => input => [empty, { ...state, value: appendChar(state.value)(input) }]
|
|
612
570
|
)([
|
|
613
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
571
|
+
rangeSetFunc(rangeSetNewLine)(state => () => [[{ kind: '//', value: state.value }], { kind: 'nl' }])
|
|
614
572
|
])
|
|
615
573
|
|
|
616
574
|
/** @type {(state: _ParseCommentState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
617
575
|
const parseMultilineCommentStateOp = create(
|
|
618
|
-
|
|
576
|
+
state => input => [empty, { ...state, value: appendChar(state.value)(input) }]
|
|
619
577
|
)([
|
|
620
|
-
rangeFunc(one(asterisk))(
|
|
621
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
578
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, kind: '/**' }]),
|
|
579
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { ...state, value: appendChar(state.value)(input), newLine: true }]),
|
|
622
580
|
])
|
|
623
581
|
|
|
624
582
|
/** @type {(state: _ParseCommentState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
625
583
|
const parseMultilineCommentAsteriskStateOp = create(
|
|
626
|
-
|
|
584
|
+
state => input => [empty, { ...state, kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input) }]
|
|
627
585
|
)([
|
|
628
|
-
rangeFunc(one(asterisk))(
|
|
629
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
630
|
-
rangeFunc(one(solidus))(
|
|
586
|
+
rangeFunc(one(asterisk))(state => () => [empty, { ...state, value: appendChar(state.value)(asterisk) }]),
|
|
587
|
+
rangeSetFunc(rangeSetNewLine)(state => input => [empty, { kind: '/*', value: appendChar(appendChar(state.value)(asterisk))(input), newLine: true }]),
|
|
588
|
+
rangeFunc(one(solidus))(state => () => {
|
|
631
589
|
/** @type {List<JsToken>} */
|
|
632
590
|
const tokens = state.newLine ? [{ kind: '/*', value: state.value }, { kind: 'nl' }] : [{ kind: '/*', value: state.value }]
|
|
633
591
|
return [tokens, { kind: 'initial' }]
|
|
634
|
-
})
|
|
592
|
+
})
|
|
635
593
|
])
|
|
636
594
|
|
|
595
|
+
/**
|
|
596
|
+
* The coalescing rule for whitespace/newline trivia: a maximal run collapses
|
|
597
|
+
* to a single token, and a run containing any newline is an `nl`. Equal kinds
|
|
598
|
+
* coalesce; `nl` absorbs `ws`.
|
|
599
|
+
*
|
|
600
|
+
* Exported because `fjs/djs/tokenizer` produces the same token stream and must
|
|
601
|
+
* agree byte for byte — its scanner reaches the same four decisions from
|
|
602
|
+
* grammar tags. This module defines `JsToken`, so the rule is stated here once
|
|
603
|
+
* rather than re-derived on each side with only the proofs to catch a drift.
|
|
604
|
+
*
|
|
605
|
+
* @type {(a: TriviaKind, b: TriviaKind) => TriviaKind}
|
|
606
|
+
*/
|
|
607
|
+
export const mergeTrivia = (a, b) => a === 'nl' || b === 'nl' ? 'nl' : 'ws'
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* The two trivia states, shared rather than rebuilt, so a run of trivia
|
|
611
|
+
* allocates nothing per character.
|
|
612
|
+
*
|
|
613
|
+
* @type {{ readonly ws: _ParseWhitespaceState, readonly nl: _ParseNewLineState }}
|
|
614
|
+
*/
|
|
615
|
+
const triviaState = { ws: { kind: 'ws' }, nl: { kind: 'nl' } }
|
|
616
|
+
|
|
637
617
|
/** @type {_CreateToToken<_ParseWhitespaceState>} */
|
|
638
618
|
const parseWhitespaceDefault = () => input => {
|
|
639
|
-
const next =
|
|
619
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
640
620
|
return [{ first: { kind: 'ws' }, tail: next[0] }, next[1]]
|
|
641
621
|
}
|
|
642
622
|
|
|
643
623
|
/** @type {(state: _ParseWhitespaceState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
644
624
|
const parseWhitespaceStateOp = create(parseWhitespaceDefault)([
|
|
645
|
-
rangeSetFunc(rangeSetWhiteSpace)(
|
|
646
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
625
|
+
rangeSetFunc(rangeSetWhiteSpace)(({ kind }) => () => [empty, triviaState[mergeTrivia(kind, 'ws')]]),
|
|
626
|
+
rangeSetFunc(rangeSetNewLine)(({ kind }) => () => [empty, triviaState[mergeTrivia(kind, 'nl')]])
|
|
647
627
|
])
|
|
648
628
|
|
|
649
629
|
/** @type {_CreateToToken<_ParseNewLineState>} */
|
|
650
630
|
const parseNewLineDefault = () => input => {
|
|
651
|
-
const next =
|
|
631
|
+
const next = tokenizeCharCodeOp(input, { kind: 'initial' })
|
|
652
632
|
return [{ first: { kind: 'nl' }, tail: next[0] }, next[1]]
|
|
653
633
|
}
|
|
654
634
|
|
|
655
635
|
/** @type {(state: _ParseNewLineState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
656
636
|
const parseNewLineStateOp = create(parseNewLineDefault)([
|
|
657
|
-
rangeSetFunc(rangeSetWhiteSpace)(
|
|
658
|
-
rangeSetFunc(rangeSetNewLine)(
|
|
637
|
+
rangeSetFunc(rangeSetWhiteSpace)(({ kind }) => () => [empty, triviaState[mergeTrivia(kind, 'ws')]]),
|
|
638
|
+
rangeSetFunc(rangeSetNewLine)(({ kind }) => () => [empty, triviaState[mergeTrivia(kind, 'nl')]])
|
|
659
639
|
])
|
|
660
640
|
|
|
661
641
|
/** @type {(state: _EofState) => (input: number) => readonly [List<JsToken>, _TokenizerState]} */
|
|
662
642
|
const eofStateOp = create(
|
|
663
|
-
|
|
643
|
+
state => () => [[{ kind: 'error', message: 'eof' }], state]
|
|
664
644
|
)([])
|
|
665
645
|
|
|
666
646
|
/** @type {StateScan<number, _TokenizerState, List<JsToken>>} */
|
|
@@ -699,7 +679,7 @@ const tokenizeEofOp = state => {
|
|
|
699
679
|
case 'e+':
|
|
700
680
|
case 'e-': return [[{ kind: 'error', message: 'invalid number' }, { kind: 'eof' }], { kind: 'eof', }]
|
|
701
681
|
}
|
|
702
|
-
return [[
|
|
682
|
+
return [[stateToNumberToken(state), { kind: 'eof' }], { kind: 'eof' }]
|
|
703
683
|
case 'op': return [[getOperatorToken(state.value), { kind: 'eof' }], { kind: 'eof' }]
|
|
704
684
|
case '//': return [[{ kind: '//', value: state.value }, { kind: 'eof' }], { kind: 'eof' }]
|
|
705
685
|
case '/*':
|
|
@@ -710,9 +690,6 @@ const tokenizeEofOp = state => {
|
|
|
710
690
|
}
|
|
711
691
|
}
|
|
712
692
|
|
|
713
|
-
/** @type {StateScan<_CharCodeOrEof, _TokenizerState, List<JsToken>>} */
|
|
714
|
-
const tokenizeOp = (input, state) => input === null ? tokenizeEofOp(state) : tokenizeCharCodeOp(input, state)
|
|
715
|
-
|
|
716
693
|
/** @type {(metadata: TokenMetadata) => (token: JsToken) => JsTokenWithMetadata} */
|
|
717
694
|
const mapTokenWithMetadata = metadata => token => { return { token, metadata } }
|
|
718
695
|
|
|
@@ -746,14 +723,23 @@ export const proof = {
|
|
|
746
723
|
const result = getOperatorToken('@')
|
|
747
724
|
assertEq(result.kind, 'error')
|
|
748
725
|
},
|
|
726
|
+
// `tokenize` appends exactly one trailing `null` after its input, so the
|
|
727
|
+
// scan reaches `{ kind: 'eof' }` only on that final step — nothing ever
|
|
728
|
+
// runs tokenizeCharCodeOp/tokenizeEofOp again afterward with that state.
|
|
729
|
+
// Call each directly to cover their otherwise-unreachable `'eof'` arms.
|
|
730
|
+
tokenizeCharCodeOpAfterEof: () => {
|
|
731
|
+
const [tokens, state] = tokenizeCharCodeOp('a'.charCodeAt(0), { kind: 'eof' })
|
|
732
|
+
assertStructurallySame(toArray(tokens), [{ kind: 'error', message: 'eof' }])
|
|
733
|
+
assertStructurallySame(state, { kind: 'eof' })
|
|
734
|
+
},
|
|
735
|
+
tokenizeEofOpAfterEof: () => {
|
|
736
|
+
const [tokens, state] = tokenizeEofOp({ kind: 'eof' })
|
|
737
|
+
assertStructurallySame(toArray(tokens), [{ kind: 'error', message: 'eof' }, { kind: 'eof' }])
|
|
738
|
+
assertStructurallySame(state, { kind: 'eof' })
|
|
739
|
+
},
|
|
749
740
|
throw: {
|
|
750
741
|
// union throws when two distinct non-default handlers are merged for the same range;
|
|
751
742
|
// this path is unreachable through the public API (no overlapping ranges in practice).
|
|
752
|
-
unionConflict: () =>
|
|
753
|
-
const def = (/** @type {undefined} */ _) => todo
|
|
754
|
-
const a = (/** @type {undefined} */ _) => todo
|
|
755
|
-
const b = (/** @type {undefined} */ _) => todo
|
|
756
|
-
union(def)(a)(b)
|
|
757
|
-
}
|
|
743
|
+
unionConflict: () => unionX(0)(1)(2)
|
|
758
744
|
}
|
|
759
745
|
}
|