functionalscript 0.3.12 → 0.3.14
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/bnf/djs/module.f.d.ts +67 -1
- package/bnf/djs/module.f.js +202 -1
- package/bnf/djs/test.f.d.ts +8 -1
- package/bnf/djs/test.f.js +143 -82
- package/bnf/func/module.f.d.ts +141 -0
- package/bnf/func/module.f.js +111 -0
- package/bnf/func/test.f.d.ts +12 -0
- package/bnf/func/test.f.js +230 -0
- package/bnf/func/testlib.f.d.ts +25 -0
- package/bnf/func/testlib.f.js +150 -0
- package/nanvm-lib/tests/test.f.d.ts +33 -0
- package/nanvm-lib/tests/test.f.js +45 -6
- package/package.json +9 -7
- package/text/utf8/module.f.d.ts +31 -2
- package/text/utf8/module.f.js +116 -28
- package/types/array/module.f.d.ts +19 -5
- package/types/array/module.f.js +13 -0
- package/types/array/test.f.d.ts +1 -0
- package/types/array/test.f.js +11 -2
- package/types/bit_vec/module.f.d.ts +2 -2
- package/types/bit_vec/module.f.js +16 -4
- package/bnf/module.f.d.ts +0 -135
- package/bnf/module.f.js +0 -142
- package/bnf/test.f.d.ts +0 -65
- package/bnf/test.f.js +0 -368
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for defining language grammar using Backus-Naur Form (BNF).
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
*
|
|
8
|
+
* Utilities for serializing and deserializing BNF grammar
|
|
9
|
+
* and creating a simple LL(1) parser.
|
|
10
|
+
*
|
|
11
|
+
* See [Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import type { Rule } from './module.f.ts'
|
|
17
|
+
*
|
|
18
|
+
* // Matches 'A-Z', 'a-z', and '0-9'
|
|
19
|
+
* const grammar: Rule = () => [
|
|
20
|
+
* [[65, 90]],
|
|
21
|
+
* [[97, 122]],
|
|
22
|
+
* [[48, 57]],
|
|
23
|
+
* ]
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import { type CodePoint } from '../../text/utf16/module.f.ts';
|
|
27
|
+
/**
|
|
28
|
+
* Represents a terminal range as a pair of Unicode code points.
|
|
29
|
+
* Typically used to define character ranges.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type TerminalRange = readonly [CodePoint, CodePoint];
|
|
38
|
+
/**
|
|
39
|
+
* Represents a sequence of rules that must match in order.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
45
|
+
* const id2: Sequence = [alpha, alpha] // Matches two uppercase letters
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export type Sequence = readonly (TerminalRange | Rule)[];
|
|
49
|
+
/**
|
|
50
|
+
* Represents a logical "or" operation between multiple sequences.
|
|
51
|
+
* Allows defining alternatives within the grammar.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
57
|
+
* const id2: Sequence = [alpha, alpha] // Matches two uppercase letters
|
|
58
|
+
* const digit: TerminalRange = [48, 57] // Matches '0-9'
|
|
59
|
+
* // Matches two uppercase letters or one digit
|
|
60
|
+
* const id2OrDigit: Or = [
|
|
61
|
+
* id2,
|
|
62
|
+
* [digit],
|
|
63
|
+
* ]
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export type Or = readonly Sequence[];
|
|
67
|
+
/**
|
|
68
|
+
* Represents a lazy grammar rule for recursive definitions.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* const alpha: TerminalRange = [65, 90] // Matches 'A-Z'
|
|
74
|
+
* // zero or more alpha symbols
|
|
75
|
+
* const alpha0x: Rule = () => [
|
|
76
|
+
* [], // Empty
|
|
77
|
+
* [alpha, alpha0x] // Recursive
|
|
78
|
+
* ]
|
|
79
|
+
* const id: Sequence = [alpha, alpha0x]
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export type Rule = () => Or;
|
|
83
|
+
/**
|
|
84
|
+
* Converts a string to an array of terminal ranges where each character is a separate range.
|
|
85
|
+
*
|
|
86
|
+
* @param s - The input string.
|
|
87
|
+
* @returns An array of terminal ranges representing each character in the string.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
*
|
|
91
|
+
* ```ts
|
|
92
|
+
* const ranges = str('abc') // [[97, 97], [98, 98], [99, 99]]
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare const str: (s: string) => readonly TerminalRange[];
|
|
96
|
+
/**
|
|
97
|
+
* Converts a single character string to a terminal range.
|
|
98
|
+
*
|
|
99
|
+
* @param a - The input character string.
|
|
100
|
+
* @returns A terminal range representing the character.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const range = cp('A'); // [65, 65]
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare const cp: (a: string) => TerminalRange;
|
|
108
|
+
/**
|
|
109
|
+
* Converts a two-character string into a terminal range.
|
|
110
|
+
*
|
|
111
|
+
* @param ab - The input string of two characters.
|
|
112
|
+
* @returns A terminal range representing the two characters.
|
|
113
|
+
*
|
|
114
|
+
* @throws {number} Throws an error if the input string does not have exactly two code points.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const result = range('AZ'); // [65, 90]
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export declare const range: (ab: string) => TerminalRange;
|
|
122
|
+
type RangeSet = readonly TerminalRange[];
|
|
123
|
+
/**
|
|
124
|
+
* A set of terminal ranges compatible with the `Or` rule.
|
|
125
|
+
*/
|
|
126
|
+
export type OrRangeSet = readonly (readonly [TerminalRange])[];
|
|
127
|
+
/**
|
|
128
|
+
* Removes a terminal range from a set of ranges.
|
|
129
|
+
*
|
|
130
|
+
* @param range the original range.
|
|
131
|
+
* @param removeSet the set of ranges to be removed.
|
|
132
|
+
* @returns The resulting set of ranges after removal.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
*
|
|
136
|
+
* ```ts
|
|
137
|
+
* const result = remove([65, 90], [cp('C'), cp('W')]) // [A..Z] w/o C and W
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare const remove: (range: TerminalRange, removeSet: RangeSet) => OrRangeSet;
|
|
141
|
+
export {};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for defining language grammar using Backus-Naur Form (BNF).
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
*
|
|
8
|
+
* Utilities for serializing and deserializing BNF grammar
|
|
9
|
+
* and creating a simple LL(1) parser.
|
|
10
|
+
*
|
|
11
|
+
* See [Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import type { Rule } from './module.f.ts'
|
|
17
|
+
*
|
|
18
|
+
* // Matches 'A-Z', 'a-z', and '0-9'
|
|
19
|
+
* const grammar: Rule = () => [
|
|
20
|
+
* [[65, 90]],
|
|
21
|
+
* [[97, 122]],
|
|
22
|
+
* [[48, 57]],
|
|
23
|
+
* ]
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import { stringToCodePointList } from "../../text/utf16/module.f.js";
|
|
27
|
+
import { map, toArray } from "../../types/list/module.f.js";
|
|
28
|
+
import { one } from "../../types/range/module.f.js";
|
|
29
|
+
const toTerminalRangeMap = map(one);
|
|
30
|
+
/**
|
|
31
|
+
* Converts a string to an array of terminal ranges where each character is a separate range.
|
|
32
|
+
*
|
|
33
|
+
* @param s - The input string.
|
|
34
|
+
* @returns An array of terminal ranges representing each character in the string.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const ranges = str('abc') // [[97, 97], [98, 98], [99, 99]]
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export const str = (s) => toArray(toTerminalRangeMap(stringToCodePointList(s)));
|
|
43
|
+
/**
|
|
44
|
+
* Converts a single character string to a terminal range.
|
|
45
|
+
*
|
|
46
|
+
* @param a - The input character string.
|
|
47
|
+
* @returns A terminal range representing the character.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const range = cp('A'); // [65, 65]
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const cp = (a) => one(a.codePointAt(0));
|
|
55
|
+
/**
|
|
56
|
+
* Converts a two-character string into a terminal range.
|
|
57
|
+
*
|
|
58
|
+
* @param ab - The input string of two characters.
|
|
59
|
+
* @returns A terminal range representing the two characters.
|
|
60
|
+
*
|
|
61
|
+
* @throws {number} Throws an error if the input string does not have exactly two code points.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const result = range('AZ'); // [65, 90]
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export const range = (ab) => {
|
|
69
|
+
const a = toArray(stringToCodePointList(ab));
|
|
70
|
+
if (a.length !== 2) {
|
|
71
|
+
throw a.length;
|
|
72
|
+
}
|
|
73
|
+
// deno-lint-ignore no-explicit-any
|
|
74
|
+
return a;
|
|
75
|
+
};
|
|
76
|
+
const removeOne = (set, [a, b]) => {
|
|
77
|
+
let result = [];
|
|
78
|
+
for (const [a0, b0] of set) {
|
|
79
|
+
if (a0 < a) {
|
|
80
|
+
// [a0
|
|
81
|
+
// ]a
|
|
82
|
+
result = [...result, [a0, Math.min(b0, a - 1)]];
|
|
83
|
+
}
|
|
84
|
+
if (b < b0) {
|
|
85
|
+
// b0]
|
|
86
|
+
// b[
|
|
87
|
+
result = [...result, [Math.max(b + 1, a0), b0]];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Removes a terminal range from a set of ranges.
|
|
94
|
+
*
|
|
95
|
+
* @param range the original range.
|
|
96
|
+
* @param removeSet the set of ranges to be removed.
|
|
97
|
+
* @returns The resulting set of ranges after removal.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
*
|
|
101
|
+
* ```ts
|
|
102
|
+
* const result = remove([65, 90], [cp('C'), cp('W')]) // [A..Z] w/o C and W
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export const remove = (range, removeSet) => {
|
|
106
|
+
let result = [range];
|
|
107
|
+
for (const r of removeSet) {
|
|
108
|
+
result = removeOne(result, r);
|
|
109
|
+
}
|
|
110
|
+
return result.map(v => [v]);
|
|
111
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { stringify } from "../../json/module.f.js";
|
|
2
|
+
import { sort } from "../../types/object/module.f.js";
|
|
3
|
+
import { cp, str, range, remove, } from "./module.f.js";
|
|
4
|
+
const deterministic = () => {
|
|
5
|
+
// {"empty":true,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32]]}
|
|
6
|
+
const ws = () => [
|
|
7
|
+
[],
|
|
8
|
+
[cp('\t'), ws], // 9
|
|
9
|
+
[cp('\n'), ws], // 10
|
|
10
|
+
[cp('\r'), ws], // 13
|
|
11
|
+
[cp(' '), ws], // 32
|
|
12
|
+
];
|
|
13
|
+
// {"empty":true,"map":[[false,42],[true,43],[false,44],[true,45]]}
|
|
14
|
+
const sign = () => [
|
|
15
|
+
[],
|
|
16
|
+
str('+'), // 43
|
|
17
|
+
str('-'), // 45
|
|
18
|
+
];
|
|
19
|
+
// {"empty":false,"map":[[false,48],[true,57]]}
|
|
20
|
+
const onenine = () => [
|
|
21
|
+
[range('19')]
|
|
22
|
+
];
|
|
23
|
+
// {"empty":false,"map":[[false,47],[true,57]]}
|
|
24
|
+
const digit = () => [
|
|
25
|
+
str('0'),
|
|
26
|
+
[onenine],
|
|
27
|
+
];
|
|
28
|
+
// {"empty":true,"map":[[false,47],[true,57]]}
|
|
29
|
+
const digits1 = () => [
|
|
30
|
+
[],
|
|
31
|
+
[digit, digits1]
|
|
32
|
+
];
|
|
33
|
+
// {"empty":false,"map":[[false,47],[true,57]]}
|
|
34
|
+
const digits = () => [
|
|
35
|
+
[digit, digits1]
|
|
36
|
+
];
|
|
37
|
+
// {"empty":true,"map":[[false,68],[true,69],[false,100],[true,101]]}
|
|
38
|
+
const exponent = () => [
|
|
39
|
+
[],
|
|
40
|
+
[cp('E'), sign, digits], // 69
|
|
41
|
+
[cp('e'), sign, digits], // 101
|
|
42
|
+
];
|
|
43
|
+
// {"empty":true,"map":[[false,45],[true,46]]}
|
|
44
|
+
const fraction = () => [
|
|
45
|
+
[],
|
|
46
|
+
[cp('.'), digits] // 46
|
|
47
|
+
];
|
|
48
|
+
// {"empty":false,"map":[[false,47],[true,57]]}
|
|
49
|
+
const integer1 = () => [
|
|
50
|
+
str('0'), // 48
|
|
51
|
+
[onenine, digits1], // 49-57
|
|
52
|
+
];
|
|
53
|
+
// {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]}
|
|
54
|
+
const integer = () => [
|
|
55
|
+
[integer1], // 48-57
|
|
56
|
+
[cp('-'), integer1], // 45
|
|
57
|
+
];
|
|
58
|
+
// {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]}
|
|
59
|
+
const number = () => [
|
|
60
|
+
[integer, fraction, exponent]
|
|
61
|
+
];
|
|
62
|
+
// {"empty":false,"map":[[false,47],[true,57],[false,64],[true,70],[false,96],[true,102]]}
|
|
63
|
+
const hex = () => [
|
|
64
|
+
[digit], // 48-57
|
|
65
|
+
[range('AF')], // A..F
|
|
66
|
+
[range('af')], // a..f
|
|
67
|
+
];
|
|
68
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,46],[true,47],[false,91],[true,92],[false,97],[true,98],[false,101],[true,102],[false,109],[true,110],[false,113],[true,114],[false,115],[true,117]]}
|
|
69
|
+
const escape = () => [
|
|
70
|
+
str('"'), // 34
|
|
71
|
+
str('/'), // 47
|
|
72
|
+
str('\\'), // 92
|
|
73
|
+
str('b'), // 98
|
|
74
|
+
str('f'), // 102
|
|
75
|
+
str('n'), // 110
|
|
76
|
+
str('r'), // 114
|
|
77
|
+
str('t'), // 116
|
|
78
|
+
[cp('u'), hex, hex, hex, hex] // 117
|
|
79
|
+
];
|
|
80
|
+
// {"empty":false,"map":[[false,31],[true,33],[false,34],[true,1114111]]}
|
|
81
|
+
const character = () => [
|
|
82
|
+
...remove([0x20, 0x10FFFF], [cp('"'), cp('\\')]),
|
|
83
|
+
[cp('\\'), escape], // 92
|
|
84
|
+
];
|
|
85
|
+
// {"empty":true,"map":[[false,31],[true,33],[false,34],[true,1114111]]}
|
|
86
|
+
const characters = () => [
|
|
87
|
+
[],
|
|
88
|
+
[character, characters]
|
|
89
|
+
];
|
|
90
|
+
// {"empty":false,"map":[[false,33],[true,34]]}
|
|
91
|
+
const string = () => [
|
|
92
|
+
[cp('"'), characters, cp('"')]
|
|
93
|
+
];
|
|
94
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
95
|
+
const element1 = () => [
|
|
96
|
+
[value, ws]
|
|
97
|
+
];
|
|
98
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
99
|
+
const element = () => [
|
|
100
|
+
[ws, element1]
|
|
101
|
+
];
|
|
102
|
+
// {"empty":true,"map":[[false,43],[true,44]]}
|
|
103
|
+
const elements2 = () => [
|
|
104
|
+
[],
|
|
105
|
+
[cp(','), elements] // 44
|
|
106
|
+
];
|
|
107
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
108
|
+
const elements1 = () => [
|
|
109
|
+
[element1, elements2]
|
|
110
|
+
];
|
|
111
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
112
|
+
const elements = () => [
|
|
113
|
+
[ws, elements1]
|
|
114
|
+
];
|
|
115
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,92],[true,93],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
116
|
+
const array1 = () => [
|
|
117
|
+
str(']'), // 93
|
|
118
|
+
[elements1, cp(']')],
|
|
119
|
+
];
|
|
120
|
+
// {"empty":false,"map":[[false,90],[true,91]]}
|
|
121
|
+
const array = () => [
|
|
122
|
+
[cp('['), ws, array1]
|
|
123
|
+
];
|
|
124
|
+
// {"empty":false,"map":[[false,33],[true,34]]}
|
|
125
|
+
const member1 = () => [
|
|
126
|
+
[string, ws, cp(':'), element]
|
|
127
|
+
];
|
|
128
|
+
// {"empty":true,"map":[[false,43],[true,44]]}
|
|
129
|
+
const members2 = () => [
|
|
130
|
+
[],
|
|
131
|
+
[cp(','), members], // 44
|
|
132
|
+
];
|
|
133
|
+
// {"empty":false,"map":[[false,33],[true,34]]}
|
|
134
|
+
const members1 = () => [
|
|
135
|
+
[member1, members2]
|
|
136
|
+
];
|
|
137
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34]]}
|
|
138
|
+
const members = () => [
|
|
139
|
+
[ws, members1]
|
|
140
|
+
];
|
|
141
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,124],[true,125]]}
|
|
142
|
+
const object1 = () => [
|
|
143
|
+
str('}'), // 125
|
|
144
|
+
[members1, cp('}')],
|
|
145
|
+
];
|
|
146
|
+
// {"empty":false,"map":[[false,122],[true,123]]}
|
|
147
|
+
const object = () => [
|
|
148
|
+
[cp('{'), ws, object1]
|
|
149
|
+
];
|
|
150
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
151
|
+
const value = () => [
|
|
152
|
+
[object], // 123
|
|
153
|
+
[array], // 91
|
|
154
|
+
[string], // 34
|
|
155
|
+
[number], // 45, 48-57
|
|
156
|
+
str('true'), // 116
|
|
157
|
+
str('false'), // 102
|
|
158
|
+
str('null'), // 110
|
|
159
|
+
];
|
|
160
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
161
|
+
const json = element;
|
|
162
|
+
const _ = json;
|
|
163
|
+
};
|
|
164
|
+
//
|
|
165
|
+
const s = stringify(sort);
|
|
166
|
+
export default {
|
|
167
|
+
example: {
|
|
168
|
+
module: () => {
|
|
169
|
+
// Matches 'A-Z', 'a-z', and '0-9'
|
|
170
|
+
const grammar = () => [
|
|
171
|
+
[range('AZ')],
|
|
172
|
+
[range('az')],
|
|
173
|
+
[range('09')],
|
|
174
|
+
];
|
|
175
|
+
const _ = grammar;
|
|
176
|
+
},
|
|
177
|
+
types: () => {
|
|
178
|
+
const alpha = range('AZ'); // Matches 'A-Z'
|
|
179
|
+
const id2 = [alpha, alpha]; // Matches two uppercase letters
|
|
180
|
+
const digit = range('09'); // Matches '0-9'
|
|
181
|
+
// Matches two uppercase letters or one digit
|
|
182
|
+
const id2OrDigit = [
|
|
183
|
+
id2,
|
|
184
|
+
[digit],
|
|
185
|
+
];
|
|
186
|
+
// Matches 'true', 'false'
|
|
187
|
+
const bool = () => [
|
|
188
|
+
str('true'),
|
|
189
|
+
str('false'),
|
|
190
|
+
];
|
|
191
|
+
// zero or more alpha symbols
|
|
192
|
+
const alpha0x = () => [
|
|
193
|
+
[], // Empty
|
|
194
|
+
[alpha, alpha0x] // Recursive
|
|
195
|
+
];
|
|
196
|
+
const id = [alpha, alpha0x];
|
|
197
|
+
const _ = [id2OrDigit, bool, id];
|
|
198
|
+
},
|
|
199
|
+
str: () => {
|
|
200
|
+
const ranges = str('abc'); // [[97, 97], [98, 98], [99, 99]]
|
|
201
|
+
const result = s(ranges);
|
|
202
|
+
if (result !== '[[97,97],[98,98],[99,99]]') {
|
|
203
|
+
throw result;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
cp: () => {
|
|
207
|
+
const range = cp('A'); // [65, 65]
|
|
208
|
+
const result = s(range);
|
|
209
|
+
if (result !== '[65,65]') {
|
|
210
|
+
throw result;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
range: () => {
|
|
214
|
+
const r = range('AZ'); // [65, 90]
|
|
215
|
+
const result = s(r);
|
|
216
|
+
if (result !== '[65,90]') {
|
|
217
|
+
throw result;
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
remove: () => {
|
|
221
|
+
const result = s(remove([65, 90], [cp('C'), cp('W')])); // [A..Z] w/o C and W
|
|
222
|
+
if (result !== '[[[65,66]],[[68,86]],[[88,90]]]') {
|
|
223
|
+
throw result;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
remove: () => {
|
|
228
|
+
const _x = remove([0x20, 0x10FFFF], [cp('"'), cp('\\')]);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Rule } from './module.f.ts';
|
|
2
|
+
export declare const classic: () => {
|
|
3
|
+
readonly ws: Rule;
|
|
4
|
+
readonly sign: Rule;
|
|
5
|
+
readonly digits: Rule;
|
|
6
|
+
readonly exponent: Rule;
|
|
7
|
+
readonly fraction: Rule;
|
|
8
|
+
readonly onenine: Rule;
|
|
9
|
+
readonly digit: Rule;
|
|
10
|
+
readonly string: Rule;
|
|
11
|
+
readonly member: Rule;
|
|
12
|
+
readonly members: Rule;
|
|
13
|
+
readonly object: Rule;
|
|
14
|
+
readonly array: Rule;
|
|
15
|
+
readonly integer: Rule;
|
|
16
|
+
readonly number: Rule;
|
|
17
|
+
readonly value: Rule;
|
|
18
|
+
readonly element: Rule;
|
|
19
|
+
readonly elements: Rule;
|
|
20
|
+
readonly json: Rule;
|
|
21
|
+
readonly hex: Rule;
|
|
22
|
+
readonly escape: Rule;
|
|
23
|
+
readonly character: Rule;
|
|
24
|
+
readonly characters: Rule;
|
|
25
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { cp, range, remove, str } from "./module.f.js";
|
|
2
|
+
// https://www.json.org/json-en.html
|
|
3
|
+
export const classic = () => {
|
|
4
|
+
// {"empty":true,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32]]}
|
|
5
|
+
const ws = () => [
|
|
6
|
+
[],
|
|
7
|
+
[cp(' '), ws], // 32
|
|
8
|
+
[cp('\n'), ws], // 10
|
|
9
|
+
[cp('\r'), ws], // 13
|
|
10
|
+
[cp('\t'), ws], // 9
|
|
11
|
+
];
|
|
12
|
+
// {"empty":true,"map":[[false,42],[true,43],[false,44],[true,45]]}
|
|
13
|
+
const sign = () => [
|
|
14
|
+
[],
|
|
15
|
+
str('+'), // 43
|
|
16
|
+
str('-'), // 45
|
|
17
|
+
];
|
|
18
|
+
// {"empty":false,"map":[[false,48],[true,57]]}
|
|
19
|
+
const onenine = () => [[[0x31, 0x39]]];
|
|
20
|
+
// {"empty":false,"map":[[false,47],[true,57]]}
|
|
21
|
+
const digit = () => [
|
|
22
|
+
str('0'),
|
|
23
|
+
[onenine],
|
|
24
|
+
];
|
|
25
|
+
// {"empty":false,"map":[[false,47],[true,57]]}
|
|
26
|
+
const digits = () => [
|
|
27
|
+
[digit],
|
|
28
|
+
[digit, digits]
|
|
29
|
+
];
|
|
30
|
+
// {"empty":true,"map":[[false,68],[true,69],[false,100],[true,101]]}
|
|
31
|
+
const exponent = () => [
|
|
32
|
+
[],
|
|
33
|
+
[cp('E'), sign, digits], // 69
|
|
34
|
+
[cp('e'), sign, digits], // 101
|
|
35
|
+
];
|
|
36
|
+
// {"empty":true,"map":[[false,45],[true,46]]}
|
|
37
|
+
const fraction = () => [
|
|
38
|
+
[],
|
|
39
|
+
[cp('.'), digits] // 46
|
|
40
|
+
];
|
|
41
|
+
// {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]}
|
|
42
|
+
const integer = () => [
|
|
43
|
+
[digit], // 48-57
|
|
44
|
+
[onenine, digits],
|
|
45
|
+
[cp('-'), digit], // 45
|
|
46
|
+
[cp('-'), onenine, digits],
|
|
47
|
+
];
|
|
48
|
+
// {"empty":false,"map":[[false,44],[true,45],[false,47],[true,57]]}
|
|
49
|
+
const number = () => [
|
|
50
|
+
[integer, fraction, exponent]
|
|
51
|
+
];
|
|
52
|
+
// {"empty":false,"map":[[false,47],[true,57],[false,64],[true,70],[false,96],[true,102]]}
|
|
53
|
+
const hex = () => [
|
|
54
|
+
[digit], // 48-57
|
|
55
|
+
[range('AF')], // A..F
|
|
56
|
+
[range('af')], // a..f
|
|
57
|
+
];
|
|
58
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,46],[true,47],[false,91],[true,92],[false,97],[true,98],[false,101],[true,102],[false,109],[true,110],[false,113],[true,114],[false,115],[true,117]]}
|
|
59
|
+
const escape = () => [
|
|
60
|
+
str('"'), // 34
|
|
61
|
+
str('\\'), // 92
|
|
62
|
+
str('/'), // 47
|
|
63
|
+
str('b'), // 98
|
|
64
|
+
str('f'), // 102
|
|
65
|
+
str('n'), // 110
|
|
66
|
+
str('r'), // 114
|
|
67
|
+
str('t'), // 116
|
|
68
|
+
[cp('u'), hex, hex, hex, hex] // 117
|
|
69
|
+
];
|
|
70
|
+
// {"empty":false,"map":[[false,31],[true,33],[false,34],[true,1114111]]}
|
|
71
|
+
const character = () => [
|
|
72
|
+
...remove([0x20, 0x10FFFF], [cp('"'), cp('\\')]),
|
|
73
|
+
[cp('\\'), escape],
|
|
74
|
+
];
|
|
75
|
+
// {"empty":true,"map":[[false,31],[true,33],[false,34],[true,1114111]]}
|
|
76
|
+
const characters = () => [
|
|
77
|
+
[],
|
|
78
|
+
[character, characters]
|
|
79
|
+
];
|
|
80
|
+
// {"empty":false,"map":[[false,33],[true,34]]}
|
|
81
|
+
const string = () => [
|
|
82
|
+
[cp('"'), characters, cp('"')]
|
|
83
|
+
];
|
|
84
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
85
|
+
const element = () => [
|
|
86
|
+
[ws, value, ws]
|
|
87
|
+
];
|
|
88
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
89
|
+
const elements = () => [
|
|
90
|
+
[element],
|
|
91
|
+
[element, cp(','), elements]
|
|
92
|
+
];
|
|
93
|
+
// {"empty":false,"map":[[false,90],[true,91]]}
|
|
94
|
+
const array = () => [
|
|
95
|
+
[cp('['), ws, cp(']')], // 91
|
|
96
|
+
[cp('['), elements, cp(']')],
|
|
97
|
+
];
|
|
98
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34]]}
|
|
99
|
+
const member = () => [
|
|
100
|
+
[ws, string, ws, cp(':'), element]
|
|
101
|
+
];
|
|
102
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34]]}
|
|
103
|
+
const members = () => [
|
|
104
|
+
[member],
|
|
105
|
+
[member, cp(','), members],
|
|
106
|
+
];
|
|
107
|
+
// {"empty":false,"map":[[false,122],[true,123]]}
|
|
108
|
+
const object = () => [
|
|
109
|
+
[cp('{'), ws, cp('}')], // 123
|
|
110
|
+
[cp('{'), members, cp('}')],
|
|
111
|
+
];
|
|
112
|
+
// {"empty":false,"map":[[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
113
|
+
const value = () => [
|
|
114
|
+
[object], // 123
|
|
115
|
+
[array], // 91
|
|
116
|
+
[string], // 34
|
|
117
|
+
[number], // 45, 48-57
|
|
118
|
+
str('true'), // 116
|
|
119
|
+
str('false'), // 102
|
|
120
|
+
str('null'), // 110
|
|
121
|
+
];
|
|
122
|
+
// {"empty":false,"map":[[false,8],[true,10],[false,12],[true,13],[false,31],[true,32],[false,33],[true,34],[false,44],[true,45],[false,47],[true,57],[false,90],[true,91],[false,101],[true,102],[false,109],[true,110],[false,115],[true,116],[false,122],[true,123]]}
|
|
123
|
+
const json = () => [
|
|
124
|
+
[element]
|
|
125
|
+
];
|
|
126
|
+
return {
|
|
127
|
+
ws,
|
|
128
|
+
sign,
|
|
129
|
+
digits,
|
|
130
|
+
exponent,
|
|
131
|
+
fraction,
|
|
132
|
+
onenine,
|
|
133
|
+
digit,
|
|
134
|
+
string,
|
|
135
|
+
member,
|
|
136
|
+
members,
|
|
137
|
+
object,
|
|
138
|
+
array,
|
|
139
|
+
integer,
|
|
140
|
+
number,
|
|
141
|
+
value,
|
|
142
|
+
element,
|
|
143
|
+
elements,
|
|
144
|
+
json,
|
|
145
|
+
hex,
|
|
146
|
+
escape,
|
|
147
|
+
character,
|
|
148
|
+
characters,
|
|
149
|
+
};
|
|
150
|
+
};
|