functionalscript 0.3.10 → 0.3.12
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 +1 -0
- package/bnf/djs/module.f.d.ts +11 -0
- package/bnf/djs/module.f.js +6 -0
- package/bnf/djs/test.f.d.ts +1 -0
- package/bnf/djs/test.f.js +221 -0
- package/bnf/module.f.d.ts +135 -0
- package/bnf/module.f.js +142 -0
- package/bnf/test.f.d.ts +65 -0
- package/bnf/test.f.js +368 -0
- package/crypto/prime_field/module.f.d.ts +1 -4
- package/crypto/secp/module.f.d.ts +2 -2
- package/dev/test/module.f.js +2 -1
- package/fsc/module.f.js +5 -6
- package/fsm/module.f.d.ts +9 -9
- package/fsm/module.f.js +13 -22
- package/html/module.f.js +1 -2
- package/issues/31-json.f.d.ts +1 -0
- package/issues/31-json.f.js +241 -0
- package/js/tokenizer/module.f.js +6 -1
- package/nanvm-lib/tests/test.f.d.ts +4 -0
- package/nanvm-lib/tests/test.f.js +5 -7
- package/nodejs/version/module.f.d.ts +1 -1
- package/package.json +1 -1
- package/text/module.f.js +3 -3
- package/text/utf16/module.f.d.ts +11 -5
- package/text/utf16/module.f.js +2 -0
- package/text/utf16/test.f.js +8 -1
- package/types/btree/find/module.f.d.ts +2 -2
- package/types/btree/remove/module.f.d.ts +4 -4
- package/types/btree/remove/module.f.js +9 -11
- package/types/btree/remove/test.f.js +2 -2
- package/types/btree/set/module.f.d.ts +3 -3
- package/types/byte_set/test.f.js +31 -31
- package/types/function/module.f.d.ts +1 -1
- package/types/range_map/module.f.d.ts +79 -2
- package/types/range_map/module.f.js +49 -2
- package/types/range_map/test.f.d.ts +1 -0
- package/types/range_map/test.f.js +76 -33
- package/types/result/module.f.d.ts +48 -1
- package/types/result/module.f.js +40 -2
- package/types/result/test.f.d.ts +4 -0
- package/types/result/test.f.js +18 -0
- package/types/sorted_list/module.f.js +8 -7
- package/types/sorted_set/module.f.d.ts +28 -0
- package/types/sorted_set/test.f.d.ts +1 -0
- package/types/sorted_set/test.f.js +19 -0
- package/types/string/module.f.d.ts +17 -0
- package/types/string/module.f.js +17 -0
- package/types/string/test.f.d.ts +1 -0
- package/types/string/test.f.js +15 -0
- package/types/string_set/module.f.d.ts +21 -0
- package/types/string_set/module.f.js +21 -0
- package/types/string_set/test.f.d.ts +1 -0
- package/types/string_set/test.f.js +18 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ FunctionalScript is a safe, purely functional programming language and a strict
|
|
|
15
15
|
[A working draft of the FunctionalScript specification](./issues/lang/README.md).
|
|
16
16
|
|
|
17
17
|
Learn more about
|
|
18
|
+
|
|
18
19
|
- [Purely Functional Programming in JavaScript](https://blog.bitsrc.io/purely-functional-programming-in-javascript-91114b1b2dff?sk=5f7132e56902f38fcf4c6164bfa681ed),
|
|
19
20
|
- [FunctionalScript and I/O](https://medium.com/@sergeyshandar/functionalscript-5cf817345376?sk=30b32189a81d1a2dad16c2244f32328d).
|
|
20
21
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules for serializing and deserializing the BNF grammar.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { TerminalRange } from '../module.f.ts';
|
|
7
|
+
export type Sequence<Id> = readonly (TerminalRange | Id)[];
|
|
8
|
+
export type Rule<Id> = readonly Sequence<Id>[];
|
|
9
|
+
export type RuleMap<Id extends string> = {
|
|
10
|
+
readonly [k in Id]: Rule<Id>;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { one } from "../../types/range/module.f.js";
|
|
2
|
+
import { toTerminalRangeSequence } from "../module.f.js";
|
|
3
|
+
const s = toTerminalRangeSequence;
|
|
4
|
+
const c = (a) => one(a.codePointAt(0));
|
|
5
|
+
const classic = () => {
|
|
6
|
+
const map = {
|
|
7
|
+
json: [
|
|
8
|
+
['element']
|
|
9
|
+
],
|
|
10
|
+
value: [
|
|
11
|
+
['object'],
|
|
12
|
+
['array'],
|
|
13
|
+
['string'],
|
|
14
|
+
['number'],
|
|
15
|
+
s('true'),
|
|
16
|
+
s('false'),
|
|
17
|
+
s('null'),
|
|
18
|
+
],
|
|
19
|
+
object: [
|
|
20
|
+
[c('{'), 'ws', c('}')],
|
|
21
|
+
[c('{'), 'members', c('}')],
|
|
22
|
+
],
|
|
23
|
+
members: [
|
|
24
|
+
['member'],
|
|
25
|
+
['member', c(','), 'members'],
|
|
26
|
+
],
|
|
27
|
+
member: [
|
|
28
|
+
['ws', 'string', 'ws', c(':'), 'element'],
|
|
29
|
+
],
|
|
30
|
+
array: [
|
|
31
|
+
[c('['), 'ws', c(']')],
|
|
32
|
+
[c('['), 'elements', c(']')],
|
|
33
|
+
],
|
|
34
|
+
elements: [
|
|
35
|
+
['element'],
|
|
36
|
+
['element', c(','), 'elements'],
|
|
37
|
+
],
|
|
38
|
+
element: [
|
|
39
|
+
['ws', 'value', 'ws'],
|
|
40
|
+
],
|
|
41
|
+
string: [
|
|
42
|
+
[c('"'), 'characters', c('"')],
|
|
43
|
+
],
|
|
44
|
+
characters: [
|
|
45
|
+
[],
|
|
46
|
+
['character', 'characters'],
|
|
47
|
+
],
|
|
48
|
+
character: [
|
|
49
|
+
[[0x20, 0x21]], // exclude '"' 0x22
|
|
50
|
+
[[0x23, 0x5B]], // exclude '\' 0x5C
|
|
51
|
+
[[0x5D, 0x10FFFF]], // 93-1114111
|
|
52
|
+
[c('\\'), 'escape'], // 92
|
|
53
|
+
],
|
|
54
|
+
escape: [
|
|
55
|
+
[c('"')],
|
|
56
|
+
[c('\\')],
|
|
57
|
+
[c('/')],
|
|
58
|
+
[c('b')],
|
|
59
|
+
[c('f')],
|
|
60
|
+
[c('n')],
|
|
61
|
+
[c('r')],
|
|
62
|
+
[c('t')],
|
|
63
|
+
[c('u'), 'hex', 'hex', 'hex', 'hex'],
|
|
64
|
+
],
|
|
65
|
+
hex: [
|
|
66
|
+
['digit'],
|
|
67
|
+
[[0x41, 0x46]], // A-F
|
|
68
|
+
[[0x61, 0x66]], // a-f
|
|
69
|
+
],
|
|
70
|
+
number: [
|
|
71
|
+
['integer', 'fraction', 'exponent'],
|
|
72
|
+
],
|
|
73
|
+
integer: [
|
|
74
|
+
['digit'],
|
|
75
|
+
['onenine', 'digits'],
|
|
76
|
+
[c('-'), 'digit'],
|
|
77
|
+
[c('-'), 'onenine', 'digits'],
|
|
78
|
+
],
|
|
79
|
+
digits: [
|
|
80
|
+
['digit'],
|
|
81
|
+
['digit', 'digits'],
|
|
82
|
+
],
|
|
83
|
+
digit: [
|
|
84
|
+
[c('0')],
|
|
85
|
+
['onenine'],
|
|
86
|
+
],
|
|
87
|
+
onenine: [
|
|
88
|
+
[[0x31, 0x39]], // 1-9
|
|
89
|
+
],
|
|
90
|
+
fraction: [
|
|
91
|
+
[],
|
|
92
|
+
[c('.'), 'digits'],
|
|
93
|
+
],
|
|
94
|
+
exponent: [
|
|
95
|
+
[],
|
|
96
|
+
[c('E'), 'sign', 'digits'],
|
|
97
|
+
[c('e'), 'sign', 'digits'],
|
|
98
|
+
],
|
|
99
|
+
sign: [
|
|
100
|
+
[],
|
|
101
|
+
[c('+')],
|
|
102
|
+
[c('-')],
|
|
103
|
+
],
|
|
104
|
+
ws: [
|
|
105
|
+
[],
|
|
106
|
+
[c(' '), 'ws'],
|
|
107
|
+
[c('\n'), 'ws'],
|
|
108
|
+
[c('\r'), 'ws'],
|
|
109
|
+
[c('\t'), 'ws'],
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
const _map = map;
|
|
113
|
+
};
|
|
114
|
+
const deterministic = () => {
|
|
115
|
+
const map = {
|
|
116
|
+
json: [
|
|
117
|
+
['ws', 'element']
|
|
118
|
+
],
|
|
119
|
+
value: [
|
|
120
|
+
[c('{'), 'ws', 'object', c('}')],
|
|
121
|
+
[c('['), 'ws', 'array', c(']')],
|
|
122
|
+
['string'],
|
|
123
|
+
['number'],
|
|
124
|
+
s('true'),
|
|
125
|
+
s('false'),
|
|
126
|
+
s('null'),
|
|
127
|
+
],
|
|
128
|
+
object: [
|
|
129
|
+
[],
|
|
130
|
+
['member', 'members'],
|
|
131
|
+
],
|
|
132
|
+
members: [
|
|
133
|
+
[],
|
|
134
|
+
[c(','), 'ws', 'member', 'members'],
|
|
135
|
+
],
|
|
136
|
+
member: [
|
|
137
|
+
['string', 'ws', c(':'), 'ws', 'element'],
|
|
138
|
+
],
|
|
139
|
+
array: [
|
|
140
|
+
[],
|
|
141
|
+
['element', 'elements'],
|
|
142
|
+
],
|
|
143
|
+
elements: [
|
|
144
|
+
[],
|
|
145
|
+
[c(','), 'ws', 'element', 'elements'],
|
|
146
|
+
],
|
|
147
|
+
element: [
|
|
148
|
+
['value', 'ws'],
|
|
149
|
+
],
|
|
150
|
+
string: [
|
|
151
|
+
[c('"'), 'characters', c('"')],
|
|
152
|
+
],
|
|
153
|
+
characters: [
|
|
154
|
+
[],
|
|
155
|
+
['character', 'characters'],
|
|
156
|
+
],
|
|
157
|
+
character: [
|
|
158
|
+
[[0x20, 0x21]], // exclude '"' 0x22
|
|
159
|
+
[[0x23, 0x5B]], // exclude '\' 0x5C
|
|
160
|
+
[[0x5D, 0x10FFFF]], // 93-1114111
|
|
161
|
+
[c('\\'), 'escape'], // 92
|
|
162
|
+
],
|
|
163
|
+
escape: [
|
|
164
|
+
[c('"')],
|
|
165
|
+
[c('\\')],
|
|
166
|
+
[c('/')],
|
|
167
|
+
[c('b')],
|
|
168
|
+
[c('f')],
|
|
169
|
+
[c('n')],
|
|
170
|
+
[c('r')],
|
|
171
|
+
[c('t')],
|
|
172
|
+
[c('u'), 'hex', 'hex', 'hex', 'hex'],
|
|
173
|
+
],
|
|
174
|
+
hex: [
|
|
175
|
+
['digit'],
|
|
176
|
+
[[0x41, 0x46]], // A-F
|
|
177
|
+
[[0x61, 0x66]], // a-f
|
|
178
|
+
],
|
|
179
|
+
number: [
|
|
180
|
+
['integer', 'fraction', 'exponent'],
|
|
181
|
+
[c('-'), 'integer', 'fraction', 'exponent'],
|
|
182
|
+
],
|
|
183
|
+
integer: [
|
|
184
|
+
[c('0')],
|
|
185
|
+
['onenine', 'digits'],
|
|
186
|
+
],
|
|
187
|
+
digits: [
|
|
188
|
+
[],
|
|
189
|
+
['digit', 'digits'],
|
|
190
|
+
],
|
|
191
|
+
digit: [
|
|
192
|
+
[c('0')],
|
|
193
|
+
['onenine'],
|
|
194
|
+
],
|
|
195
|
+
onenine: [
|
|
196
|
+
[[0x31, 0x39]], // 1-9
|
|
197
|
+
],
|
|
198
|
+
fraction: [
|
|
199
|
+
[],
|
|
200
|
+
[c('.'), 'digit', 'digits'],
|
|
201
|
+
],
|
|
202
|
+
exponent: [
|
|
203
|
+
[],
|
|
204
|
+
[c('E'), 'sign', 'digit', 'digits'],
|
|
205
|
+
[c('e'), 'sign', 'digit', 'digits'],
|
|
206
|
+
],
|
|
207
|
+
sign: [
|
|
208
|
+
[],
|
|
209
|
+
[c('+')],
|
|
210
|
+
[c('-')],
|
|
211
|
+
],
|
|
212
|
+
ws: [
|
|
213
|
+
[],
|
|
214
|
+
[c(' '), 'ws'],
|
|
215
|
+
[c('\n'), 'ws'],
|
|
216
|
+
[c('\r'), 'ws'],
|
|
217
|
+
[c('\t'), 'ws'],
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
const _map = map;
|
|
221
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for defining language grammars using Backus-Naur Form (BNF).
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
*
|
|
8
|
+
* The primary utility of this module is to define grammars for text processing,
|
|
9
|
+
* parsing, and lexing in a structured and reusable way.
|
|
10
|
+
*
|
|
11
|
+
* See [Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* ```js
|
|
16
|
+
* import { firstSet, type Rule, type Set } from './module.f.ts'
|
|
17
|
+
*
|
|
18
|
+
* const grammar: Rule = [
|
|
19
|
+
* { or: [[65, 90], [97, 122], [48, 57]] }, // Matches 'A-Z', 'a-z', and '0-9'
|
|
20
|
+
* ];
|
|
21
|
+
*
|
|
22
|
+
* const s = firstSet(grammar)
|
|
23
|
+
* if (s.empty) { throw s }
|
|
24
|
+
* if (setOp.get('0'.codePointAt(0))(s.map) !== true) { throw s }
|
|
25
|
+
* if (setOp.get('h'.codePointAt(0))(s.map) !== true) { throw s }
|
|
26
|
+
* if (setOp.get('$'.codePointAt(0))(s.map) !== false) { throw s }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { type CodePoint } from '../text/utf16/module.f.ts';
|
|
30
|
+
import { type RangeMapOp, type RangeMapArray } from '../types/range_map/module.f.ts';
|
|
31
|
+
/**
|
|
32
|
+
* Represents a terminal range as a pair of Unicode code points.
|
|
33
|
+
* Typically used to define character ranges.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export type TerminalRange = readonly [CodePoint, CodePoint];
|
|
42
|
+
/**
|
|
43
|
+
* Represents a sequence of rules that must match in order.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
49
|
+
* const id2: Sequence = [alpha, alpha] // Matches two uppercase letters
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export type Sequence = readonly Rule[];
|
|
53
|
+
/**
|
|
54
|
+
* Represents a logical "or" operation between multiple sequences.
|
|
55
|
+
* Allows defining alternatives within the grammar.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
61
|
+
* const id2: Sequence = [alpha, alpha] // Matches two uppercase letters
|
|
62
|
+
* const digit: TerminalRange = [48, 57] // Matches '0-9'
|
|
63
|
+
* // Matches two uppercase letters or one digit
|
|
64
|
+
* const id2OrDigit: Or = { or: [
|
|
65
|
+
* id2,
|
|
66
|
+
* digit,
|
|
67
|
+
* ] }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export type Or = {
|
|
71
|
+
readonly or: Sequence;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Represents a grammar rule, which can be:
|
|
75
|
+
* - A sequence of rules (`Sequence`)
|
|
76
|
+
* - An "or" operation (`Or`)
|
|
77
|
+
* - A terminal range (`TerminalRange`)
|
|
78
|
+
* - A string (representing a literal sequence of characters)
|
|
79
|
+
*
|
|
80
|
+
* @remarks The rule can't have recursions.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* // Matches 'true', 'false'
|
|
86
|
+
* const bool: DataRule = { or: [
|
|
87
|
+
* 'true',
|
|
88
|
+
* 'false',
|
|
89
|
+
* ] }
|
|
90
|
+
*/
|
|
91
|
+
export type DataRule = Or | Sequence | TerminalRange | string;
|
|
92
|
+
/**
|
|
93
|
+
* Represents a lazy grammar rule for recursive definitions.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
*
|
|
97
|
+
* ```ts
|
|
98
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
99
|
+
* // Matches a string of uppercase letters
|
|
100
|
+
* const id: LazyRule = () => [alpha, { or: [
|
|
101
|
+
* [], // Empty
|
|
102
|
+
* id // Recursive
|
|
103
|
+
* ] }]
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export type LazyRule = () => DataRule;
|
|
107
|
+
/**
|
|
108
|
+
* Represents a rule in the grammar.
|
|
109
|
+
*/
|
|
110
|
+
export type Rule = DataRule | LazyRule;
|
|
111
|
+
export declare const toTerminalRangeSequence: (s: string) => readonly TerminalRange[];
|
|
112
|
+
/**
|
|
113
|
+
* A set that represents possible code points.
|
|
114
|
+
*/
|
|
115
|
+
export type CpSet = {
|
|
116
|
+
/**
|
|
117
|
+
* Whether a grammar rule allows an empty sequence.
|
|
118
|
+
*/
|
|
119
|
+
readonly empty: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* The range map representing a set of possible code points.
|
|
122
|
+
*/
|
|
123
|
+
readonly map: RangeMapArray<boolean>;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Operations on code point sets.
|
|
127
|
+
*/
|
|
128
|
+
export declare const setOp: RangeMapOp<boolean>;
|
|
129
|
+
/**
|
|
130
|
+
* Processes a `Rule` and converts it into a `Set` of possible code points at the start of the rule.
|
|
131
|
+
*
|
|
132
|
+
* @param rule - The grammar rule to process.
|
|
133
|
+
* @returns A set representing the first possible code points in the grammar rule.
|
|
134
|
+
*/
|
|
135
|
+
export declare const firstSet: (rule: Rule) => CpSet;
|
package/bnf/module.f.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for defining language grammars using Backus-Naur Form (BNF).
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
*
|
|
8
|
+
* The primary utility of this module is to define grammars for text processing,
|
|
9
|
+
* parsing, and lexing in a structured and reusable way.
|
|
10
|
+
*
|
|
11
|
+
* See [Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* ```js
|
|
16
|
+
* import { firstSet, type Rule, type Set } from './module.f.ts'
|
|
17
|
+
*
|
|
18
|
+
* const grammar: Rule = [
|
|
19
|
+
* { or: [[65, 90], [97, 122], [48, 57]] }, // Matches 'A-Z', 'a-z', and '0-9'
|
|
20
|
+
* ];
|
|
21
|
+
*
|
|
22
|
+
* const s = firstSet(grammar)
|
|
23
|
+
* if (s.empty) { throw s }
|
|
24
|
+
* if (setOp.get('0'.codePointAt(0))(s.map) !== true) { throw s }
|
|
25
|
+
* if (setOp.get('h'.codePointAt(0))(s.map) !== true) { throw s }
|
|
26
|
+
* if (setOp.get('$'.codePointAt(0))(s.map) !== false) { throw s }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { stringToCodePointList } from "../text/utf16/module.f.js";
|
|
30
|
+
import { map, toArray } from "../types/list/module.f.js";
|
|
31
|
+
import { rangeMap } from "../types/range_map/module.f.js";
|
|
32
|
+
const toTerminalRangeMap = map((cp) => [cp, cp]);
|
|
33
|
+
export const toTerminalRangeSequence = (s) => toArray(toTerminalRangeMap(stringToCodePointList(s)));
|
|
34
|
+
/**
|
|
35
|
+
* Operations on code point sets.
|
|
36
|
+
*/
|
|
37
|
+
export const setOp = rangeMap({
|
|
38
|
+
union: a => b => a || b,
|
|
39
|
+
equal: a => b => a === b,
|
|
40
|
+
def: false
|
|
41
|
+
});
|
|
42
|
+
const { merge, fromRange } = setOp;
|
|
43
|
+
const rangeToSet = (r) => ({ empty: false, map: fromRange(r)(true) });
|
|
44
|
+
const isTerminalRange = (rule) => typeof rule[0] === 'number';
|
|
45
|
+
const passSet = { empty: true, map: [] };
|
|
46
|
+
/**
|
|
47
|
+
* Processes a `Rule` and converts it into a `Set` of possible code points at the start of the rule.
|
|
48
|
+
*
|
|
49
|
+
* @param rule - The grammar rule to process.
|
|
50
|
+
* @returns A set representing the first possible code points in the grammar rule.
|
|
51
|
+
*/
|
|
52
|
+
export const firstSet = (rule) => {
|
|
53
|
+
if (typeof rule === 'function') {
|
|
54
|
+
rule = rule();
|
|
55
|
+
}
|
|
56
|
+
if (typeof rule === 'string') {
|
|
57
|
+
const first = toTerminalRangeSequence(rule).at(0);
|
|
58
|
+
if (first === undefined) {
|
|
59
|
+
return passSet;
|
|
60
|
+
}
|
|
61
|
+
return rangeToSet(first);
|
|
62
|
+
}
|
|
63
|
+
if (rule instanceof Array) {
|
|
64
|
+
if (isTerminalRange(rule)) {
|
|
65
|
+
return rangeToSet(rule);
|
|
66
|
+
}
|
|
67
|
+
let result = [];
|
|
68
|
+
for (const r of rule) {
|
|
69
|
+
const { empty, map } = firstSet(r);
|
|
70
|
+
result = toArray(merge(result)(map));
|
|
71
|
+
if (!empty) {
|
|
72
|
+
return { empty: false, map: result };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { empty: true, map: result };
|
|
76
|
+
}
|
|
77
|
+
let empty = false;
|
|
78
|
+
let map = [];
|
|
79
|
+
for (const r of rule.or) {
|
|
80
|
+
const { empty: rEmpty, map: rMap } = firstSet(r);
|
|
81
|
+
map = toArray(merge(map)(rMap));
|
|
82
|
+
empty ||= rEmpty;
|
|
83
|
+
}
|
|
84
|
+
return { empty, map };
|
|
85
|
+
};
|
|
86
|
+
// type MatchMap = {
|
|
87
|
+
// empty: boolean
|
|
88
|
+
// map: RangeMapArray<MatchMap>
|
|
89
|
+
// }
|
|
90
|
+
// const defMatchMap: MatchMap = { empty: false, map: [] }
|
|
91
|
+
// const unionMap = (a: MatchMap) => (b: MatchMap) =>
|
|
92
|
+
// ({ empty: a.empty || b.empty, map: toArray(matchMapOp.merge(a.map)(b.map)) })
|
|
93
|
+
// /**
|
|
94
|
+
// * Operations on code point map.
|
|
95
|
+
// */
|
|
96
|
+
// const matchMapOp: RangeMapOp<MatchMap> = rangeMap({
|
|
97
|
+
// union: unionMap,
|
|
98
|
+
// equal: a => b => a === b,
|
|
99
|
+
// def: defMatchMap
|
|
100
|
+
// })
|
|
101
|
+
// const { merge: mergeMap, fromRange: fromRangeMap } = matchMapOp
|
|
102
|
+
// const pass: MatchMap = { empty: true, map: [] }
|
|
103
|
+
// const rangeToMatchMap = (r: TerminalRange, p: MatchMap): MatchMap => ({ empty: false, map: fromRangeMap(r)(p) })
|
|
104
|
+
// /**
|
|
105
|
+
// * Processes a `Rule` and converts it into a `Set` of possible code points at the start of the rule.
|
|
106
|
+
// *
|
|
107
|
+
// * @param rule - The grammar rule to process.
|
|
108
|
+
// * @returns A set representing the first possible code points in the grammar rule.
|
|
109
|
+
// */
|
|
110
|
+
// export const matchMap = (rule: Rule): MatchMap => {
|
|
111
|
+
// if (typeof rule === 'function') {
|
|
112
|
+
// rule = rule()
|
|
113
|
+
// }
|
|
114
|
+
// if (typeof rule === 'string') {
|
|
115
|
+
// const a = toTerminalRangeSequence(rule)
|
|
116
|
+
// let result = pass
|
|
117
|
+
// for (const r of a) {
|
|
118
|
+
// result = rangeToMatchMap(r, result)
|
|
119
|
+
// }
|
|
120
|
+
// return result
|
|
121
|
+
// }
|
|
122
|
+
// if (rule instanceof Array) {
|
|
123
|
+
// if (isTerminalRange(rule)) {
|
|
124
|
+
// return rangeToMatchMap(rule, pass)
|
|
125
|
+
// }
|
|
126
|
+
// let result = pass
|
|
127
|
+
// for (const r of rule.toReversed()) {
|
|
128
|
+
// todo()
|
|
129
|
+
// /*
|
|
130
|
+
// const rMap = matchMap(r)
|
|
131
|
+
// result = unionMap(result)(rMap)
|
|
132
|
+
// */
|
|
133
|
+
// }
|
|
134
|
+
// return result
|
|
135
|
+
// }
|
|
136
|
+
// let result = pass
|
|
137
|
+
// for (const r of rule.or) {
|
|
138
|
+
// const rMap = matchMap(r)
|
|
139
|
+
// result = unionMap(result)(rMap)
|
|
140
|
+
// }
|
|
141
|
+
// return result
|
|
142
|
+
// }
|
package/bnf/test.f.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
example: {
|
|
3
|
+
module: () => void;
|
|
4
|
+
types: () => void;
|
|
5
|
+
};
|
|
6
|
+
classic: () => {
|
|
7
|
+
ws: () => void;
|
|
8
|
+
sign: () => void;
|
|
9
|
+
digits: () => void;
|
|
10
|
+
exponent: () => void;
|
|
11
|
+
fraction: () => void;
|
|
12
|
+
onenine: () => void;
|
|
13
|
+
digit: () => void;
|
|
14
|
+
string: () => void;
|
|
15
|
+
member: () => void;
|
|
16
|
+
members: () => void;
|
|
17
|
+
object: () => void;
|
|
18
|
+
array: () => void;
|
|
19
|
+
integer: () => void;
|
|
20
|
+
number: () => void;
|
|
21
|
+
value: () => void;
|
|
22
|
+
element: () => void;
|
|
23
|
+
elements: () => void;
|
|
24
|
+
json: () => void;
|
|
25
|
+
hex: () => void;
|
|
26
|
+
escape: () => void;
|
|
27
|
+
character: () => void;
|
|
28
|
+
characters: () => void;
|
|
29
|
+
};
|
|
30
|
+
deterministic: () => {
|
|
31
|
+
ws: () => void;
|
|
32
|
+
sign: () => void;
|
|
33
|
+
digits1: () => void;
|
|
34
|
+
digits: () => void;
|
|
35
|
+
exponent: () => void;
|
|
36
|
+
fraction: () => void;
|
|
37
|
+
onenine: () => void;
|
|
38
|
+
digit: () => void;
|
|
39
|
+
string: () => void;
|
|
40
|
+
member1: () => void;
|
|
41
|
+
member: () => void;
|
|
42
|
+
members2: () => void;
|
|
43
|
+
members1: () => void;
|
|
44
|
+
members: () => void;
|
|
45
|
+
object1: () => void;
|
|
46
|
+
object: () => void;
|
|
47
|
+
array1: () => void;
|
|
48
|
+
array: () => void;
|
|
49
|
+
integer1: () => void;
|
|
50
|
+
integer: () => void;
|
|
51
|
+
number: () => void;
|
|
52
|
+
value: () => void;
|
|
53
|
+
element1: () => void;
|
|
54
|
+
element: () => void;
|
|
55
|
+
elements2: () => void;
|
|
56
|
+
elements1: () => void;
|
|
57
|
+
elements: () => void;
|
|
58
|
+
json: () => void;
|
|
59
|
+
hex: () => void;
|
|
60
|
+
escape: () => void;
|
|
61
|
+
character: () => void;
|
|
62
|
+
characters: () => void;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export default _default;
|