securemark 0.294.11 → 0.295.1
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 +8 -0
- package/design.md +5 -5
- package/dist/index.js +119 -119
- package/package.json +1 -1
- package/src/combinator/control/constraint/block.ts +1 -1
- package/src/combinator/control/constraint/contract.ts +5 -6
- package/src/combinator/control/constraint/line.ts +1 -2
- package/src/combinator/control/manipulation/convert.ts +1 -1
- package/src/combinator/control/manipulation/fallback.ts +1 -1
- package/src/combinator/control/manipulation/indent.ts +2 -2
- package/src/combinator/control/manipulation/lazy.ts +1 -1
- package/src/combinator/control/manipulation/match.ts +2 -5
- package/src/combinator/control/manipulation/recovery.ts +1 -1
- package/src/combinator/control/manipulation/reverse.ts +1 -1
- package/src/combinator/control/manipulation/scope.ts +3 -7
- package/src/combinator/control/manipulation/surround.ts +45 -56
- package/src/combinator/control/monad/bind.ts +7 -12
- package/src/combinator/control/monad/fmap.ts +4 -4
- package/src/combinator/data/parser/context.ts +12 -12
- package/src/combinator/data/parser/inits.ts +3 -6
- package/src/combinator/data/parser/sequence.ts +3 -6
- package/src/combinator/data/parser/some.ts +2 -2
- package/src/combinator/data/parser/subsequence.ts +1 -1
- package/src/combinator/data/parser/tails.ts +1 -1
- package/src/combinator/data/parser/union.ts +1 -1
- package/src/combinator/data/parser.ts +10 -9
- package/src/parser/context.ts +6 -6
- package/src/parser/inline/annotation.ts +1 -1
- package/src/parser/inline/autolink/account.ts +1 -1
- package/src/parser/inline/autolink/url.ts +4 -5
- package/src/parser/inline/bracket.ts +27 -18
- package/src/parser/inline/extension/indexee.ts +1 -1
- package/src/parser/inline/link.ts +3 -3
- package/src/parser/inline/media.ts +1 -1
- package/src/parser/inline/reference.ts +9 -9
- package/src/parser/inline/ruby.ts +2 -2
- package/src/parser/visibility.ts +2 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, failsafe } from '../../data/parser';
|
|
2
2
|
import { isBlankline } from './line';
|
|
3
3
|
|
|
4
|
-
export function block<P extends Parser
|
|
4
|
+
export function block<P extends Parser>(parser: P, separation?: boolean): P;
|
|
5
5
|
export function block<N>(parser: Parser<N>, separation = true): Parser<N> {
|
|
6
6
|
assert(parser);
|
|
7
7
|
return failsafe(input => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Parser, Input, List, Data, Ctx, Node, Context, failsafe } from '../../data/parser';
|
|
2
2
|
import { matcher } from '../../../combinator';
|
|
3
3
|
|
|
4
|
-
//export function contract<P extends Parser
|
|
4
|
+
//export function contract<P extends Parser>(patterns: string | RegExp | (string | RegExp)[], parser: P, cond: (nodes: readonly Data<P>[], rest: string) => boolean): P;
|
|
5
5
|
//export function contract<N>(patterns: string | RegExp | (string | RegExp)[], parser: Parser<N>, cond: (nodes: readonly N[], rest: string) => boolean): Parser<N> {
|
|
6
6
|
// return verify(validate(patterns, parser), cond);
|
|
7
7
|
//}
|
|
8
8
|
|
|
9
|
-
export function validate<P extends Parser
|
|
10
|
-
export function validate<P extends Parser
|
|
9
|
+
export function validate<P extends Parser>(pattern: string | RegExp, parser: P): P;
|
|
10
|
+
export function validate<P extends Parser>(cond: ((input: Input<Context<P>>) => boolean), parser: P): P;
|
|
11
11
|
export function validate<N>(pattern: string | RegExp | ((input: Input<Ctx>) => boolean), parser: Parser<N>): Parser<N> {
|
|
12
12
|
if (typeof pattern === 'function') return guard(pattern, parser);
|
|
13
13
|
const match = matcher(pattern, false);
|
|
@@ -20,7 +20,7 @@ export function validate<N>(pattern: string | RegExp | ((input: Input<Ctx>) => b
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function guard<P extends Parser
|
|
23
|
+
function guard<P extends Parser>(f: (input: Input<Context<P>>) => boolean, parser: P): P;
|
|
24
24
|
function guard<N>(f: (input: Input<Ctx>) => boolean, parser: Parser<N>): Parser<N> {
|
|
25
25
|
return input =>
|
|
26
26
|
f(input)
|
|
@@ -28,7 +28,7 @@ function guard<N>(f: (input: Input<Ctx>) => boolean, parser: Parser<N>): Parser<
|
|
|
28
28
|
: undefined;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export function verify<P extends Parser
|
|
31
|
+
export function verify<P extends Parser>(parser: P, cond: (nodes: List<Data<Node<P>>>, context: Context<P>) => boolean): P;
|
|
32
32
|
export function verify<N>(parser: Parser<N>, cond: (nodes: List<Data<N>>, context: Ctx) => boolean): Parser<N> {
|
|
33
33
|
assert(parser);
|
|
34
34
|
return failsafe(input => {
|
|
@@ -36,7 +36,6 @@ export function verify<N>(parser: Parser<N>, cond: (nodes: List<Data<N>>, contex
|
|
|
36
36
|
const { source, position } = context;
|
|
37
37
|
if (position === source.length) return;
|
|
38
38
|
const result = parser(input);
|
|
39
|
-
assert(context.position > position || !result);
|
|
40
39
|
if (result && !cond(result, context)) return;
|
|
41
40
|
return result;
|
|
42
41
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser, input, failsafe } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function line<P extends Parser
|
|
3
|
+
export function line<P extends Parser>(parser: P): P;
|
|
4
4
|
export function line<N>(parser: Parser<N>): Parser<N> {
|
|
5
5
|
assert(parser);
|
|
6
6
|
return failsafe(({ context }) => {
|
|
@@ -12,7 +12,6 @@ export function line<N>(parser: Parser<N>): Parser<N> {
|
|
|
12
12
|
const result = parser(input(line, context));
|
|
13
13
|
context.position += position;
|
|
14
14
|
context.position += result && context.position === position ? line.length : 0;
|
|
15
|
-
assert(context.position > position || !result);
|
|
16
15
|
context.source = source;
|
|
17
16
|
context.offset -= position;
|
|
18
17
|
if (result === undefined) return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser, List, Ctx, Context, subinput, failsafe } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function convert<P extends Parser
|
|
3
|
+
export function convert<P extends Parser>(conv: (source: string, context: Context<P>) => string, parser: P, empty?: boolean): P;
|
|
4
4
|
export function convert<N>(conv: (source: string, context: Ctx) => string, parser: Parser<N>, empty = false): Parser<N> {
|
|
5
5
|
assert(parser);
|
|
6
6
|
return failsafe(input => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, Node, Context } from '../../data/parser';
|
|
2
2
|
import { union } from '../../data/parser/union';
|
|
3
3
|
|
|
4
|
-
export function fallback<P extends Parser
|
|
4
|
+
export function fallback<P extends Parser>(parser: P, otherwise: Parser<Node<P>, Context<P>>): P;
|
|
5
5
|
export function fallback<N>(parser: Parser<N>, otherwise: Parser<N>): Parser<N> {
|
|
6
6
|
return union([parser, otherwise]);
|
|
7
7
|
}
|
|
@@ -7,8 +7,8 @@ import { match } from './match';
|
|
|
7
7
|
import { open } from './surround';
|
|
8
8
|
import { memoize } from 'spica/memoize';
|
|
9
9
|
|
|
10
|
-
export function indent<P extends Parser
|
|
11
|
-
export function indent<P extends Parser
|
|
10
|
+
export function indent<P extends Parser>(parser: P, separation?: boolean): P;
|
|
11
|
+
export function indent<P extends Parser>(opener: RegExp, parser: P, separation?: boolean): P;
|
|
12
12
|
export function indent<N>(opener: RegExp | Parser<N>, parser: Parser<N> | boolean = false, separation = false): Parser<N> {
|
|
13
13
|
if (typeof opener === 'function') {
|
|
14
14
|
separation = parser as boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function lazy<P extends Parser
|
|
3
|
+
export function lazy<P extends Parser>(builder: () => P): P;
|
|
4
4
|
export function lazy<N>(builder: () => Parser<N>): Parser<N> {
|
|
5
5
|
let parser: Parser<N>;
|
|
6
6
|
return input =>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, failsafe } from '../../data/parser';
|
|
2
2
|
import { consume } from '../../../combinator';
|
|
3
3
|
|
|
4
|
-
export function match<P extends Parser
|
|
4
|
+
export function match<P extends Parser>(pattern: RegExp, f: (matched: RegExpMatchArray) => P): P;
|
|
5
5
|
export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Parser<N>): Parser<N> {
|
|
6
6
|
assert(!pattern.flags.match(/[gm]/) && pattern.sticky && !pattern.source.startsWith('^'));
|
|
7
7
|
const count = typeof pattern === 'object'
|
|
@@ -18,9 +18,6 @@ export function match<N>(pattern: RegExp, f: (matched: RegExpMatchArray) => Pars
|
|
|
18
18
|
count && consume(params[0].length, context);
|
|
19
19
|
const result = f(params)(input);
|
|
20
20
|
context.position += result && context.position === position ? params[0].length : 0;
|
|
21
|
-
|
|
22
|
-
return context.position > position
|
|
23
|
-
? result
|
|
24
|
-
: undefined;
|
|
21
|
+
return result;
|
|
25
22
|
});
|
|
26
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser, Input, Result, Ctx, Node, Context } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function recover<P extends Parser
|
|
3
|
+
export function recover<P extends Parser>(parser: P, fallback: (input: Input<Context<P>>, reason: unknown) => Result<Node<P>>): P;
|
|
4
4
|
export function recover<N>(parser: Parser<N>, fallback: (input: Input<Ctx>, reason: unknown) => Result<N>): Parser<N> {
|
|
5
5
|
return input => {
|
|
6
6
|
const { context } = input;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, List, Data } from '../../data/parser';
|
|
2
2
|
import { fmap } from '../monad/fmap';
|
|
3
3
|
|
|
4
|
-
export function reverse<P extends Parser
|
|
4
|
+
export function reverse<P extends Parser>(parser: P): P;
|
|
5
5
|
export function reverse<N>(parser: Parser<N>): Parser<N> {
|
|
6
6
|
return fmap(parser, nodes => nodes.foldr((node, acc) => acc.push(nodes.delete(node)) && acc, new List<Data<N>>()));
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parser, Context, input, failsafe } from '../../data/parser';
|
|
2
2
|
import { matcher } from '../../../combinator';
|
|
3
3
|
|
|
4
|
-
export function focus<P extends Parser
|
|
4
|
+
export function focus<P extends Parser>(scope: string | RegExp, parser: P, slice?: boolean): P;
|
|
5
5
|
export function focus<N>(scope: string | RegExp, parser: Parser<N>, slice = true): Parser<N> {
|
|
6
6
|
assert(parser);
|
|
7
7
|
const match = matcher(scope, false);
|
|
@@ -16,7 +16,6 @@ export function focus<N>(scope: string | RegExp, parser: Parser<N>, slice = true
|
|
|
16
16
|
if (!slice) {
|
|
17
17
|
const result = parser(arg);
|
|
18
18
|
context.position += result && context.position === position ? range : 0;
|
|
19
|
-
assert(context.position > position || !result);
|
|
20
19
|
return result;
|
|
21
20
|
}
|
|
22
21
|
context.offset ??= 0;
|
|
@@ -24,7 +23,6 @@ export function focus<N>(scope: string | RegExp, parser: Parser<N>, slice = true
|
|
|
24
23
|
const result = parser(input(src, context));
|
|
25
24
|
context.position += position;
|
|
26
25
|
context.position += result && context.position === position ? src.length : 0;
|
|
27
|
-
assert(context.position > position || !result);
|
|
28
26
|
context.source = source;
|
|
29
27
|
context.offset -= position;
|
|
30
28
|
return result;
|
|
@@ -32,8 +30,8 @@ export function focus<N>(scope: string | RegExp, parser: Parser<N>, slice = true
|
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
//export function rewrite<N, C extends Ctx, D extends Parser<unknown, C>[]>(scope: Parser<unknown, C, D>, parser: Parser<N, C, never>): Parser<N, C, D>;
|
|
35
|
-
export function rewrite<P extends Parser
|
|
36
|
-
export function rewrite<N>(scope: Parser
|
|
33
|
+
export function rewrite<P extends Parser>(scope: Parser<unknown, Context<P>>, parser: P, slice?: boolean): P;
|
|
34
|
+
export function rewrite<N>(scope: Parser, parser: Parser<N>, slice = true): Parser<N> {
|
|
37
35
|
assert(scope);
|
|
38
36
|
assert(parser);
|
|
39
37
|
return failsafe(arg => {
|
|
@@ -48,7 +46,6 @@ export function rewrite<N>(scope: Parser<unknown>, parser: Parser<N>, slice = tr
|
|
|
48
46
|
context.position = position;
|
|
49
47
|
const res2 = parser(arg);
|
|
50
48
|
context.position += res2 && context.position === position ? range : 0;
|
|
51
|
-
assert(context.position > position || !res2);
|
|
52
49
|
return res2;
|
|
53
50
|
}
|
|
54
51
|
const src = source.slice(position, context.position);
|
|
@@ -59,7 +56,6 @@ export function rewrite<N>(scope: Parser<unknown>, parser: Parser<N>, slice = tr
|
|
|
59
56
|
const res2 = parser(input(src, context));
|
|
60
57
|
context.position += position;
|
|
61
58
|
context.position += res2 && context.position === position ? src.length : 0;
|
|
62
|
-
assert(context.position > position || !res2);
|
|
63
59
|
context.source = source;
|
|
64
60
|
context.offset -= position;
|
|
65
61
|
return res2;
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, failsafe } from '../../data/parser';
|
|
2
2
|
import { matcher, clear } from '../../../combinator';
|
|
3
3
|
|
|
4
|
-
export function surround<P extends Parser
|
|
4
|
+
export function surround<P extends Parser, S = string>(
|
|
5
5
|
opener: string | RegExp | Parser<S, Context<P>>, parser: IntermediateParser<P>, closer: string | RegExp | Parser<S, Context<P>>,
|
|
6
6
|
optional?: false,
|
|
7
7
|
backtracks?: readonly number[],
|
|
8
8
|
f?: (rss: [List<Data<S>>, List<Data<SubNode<P>>>, List<Data<S>>], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
9
9
|
g?: (rss: [List<Data<S>>, List<Data<SubNode<P>>> | undefined], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
10
10
|
): P;
|
|
11
|
-
export function surround<P extends Parser
|
|
11
|
+
export function surround<P extends Parser, S = string>(
|
|
12
12
|
opener: string | RegExp | Parser<S, Context<P>>, parser: IntermediateParser<P>, closer: string | RegExp | Parser<S, Context<P>>,
|
|
13
13
|
optional?: boolean,
|
|
14
14
|
backtracks?: readonly number[],
|
|
15
15
|
f?: (rss: [List<Data<S>>, List<Data<SubNode<P>>> | undefined, List<Data<S>>], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
16
16
|
g?: (rss: [List<Data<S>>, List<Data<SubNode<P>>> | undefined], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
17
17
|
): P;
|
|
18
|
-
export function surround<P extends Parser
|
|
18
|
+
export function surround<P extends Parser, S = string>(
|
|
19
19
|
opener: string | RegExp | Parser<S, Context<P>>, parser: P, closer: string | RegExp | Parser<S, Context<P>>,
|
|
20
20
|
optional?: false,
|
|
21
21
|
backtracks?: readonly number[],
|
|
22
22
|
f?: (rss: [List<Data<S>>, List<Data<Node<P>>>, List<Data<S>>], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
23
23
|
g?: (rss: [List<Data<S>>, List<Data<Node<P>>> | undefined], context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>,
|
|
24
24
|
): P;
|
|
25
|
-
export function surround<P extends Parser
|
|
25
|
+
export function surround<P extends Parser, S = string>(
|
|
26
26
|
opener: string | RegExp | Parser<S, Context<P>>, parser: P, closer: string | RegExp | Parser<S, Context<P>>,
|
|
27
27
|
optional?: boolean,
|
|
28
28
|
backtracks?: readonly number[],
|
|
@@ -68,6 +68,7 @@ export function surround<N>(
|
|
|
68
68
|
closer = clear(matcher(closer, true));
|
|
69
69
|
}
|
|
70
70
|
assert(closer);
|
|
71
|
+
const [blen, rbs, wbs] = reduce(backtracks);
|
|
71
72
|
return failsafe(input => {
|
|
72
73
|
const { context } = input;
|
|
73
74
|
const { source, position } = context;
|
|
@@ -75,26 +76,23 @@ export function surround<N>(
|
|
|
75
76
|
const { linebreak } = context;
|
|
76
77
|
context.linebreak = 0;
|
|
77
78
|
const nodesO = opener(input);
|
|
78
|
-
assert(context.position >= position);
|
|
79
79
|
if (!nodesO) {
|
|
80
80
|
return void revert(context, linebreak);
|
|
81
81
|
}
|
|
82
|
-
if (isBacktrack(context,
|
|
82
|
+
if (rbs && isBacktrack(context, rbs, position, blen)) {
|
|
83
83
|
return void revert(context, linebreak);
|
|
84
84
|
}
|
|
85
85
|
const nodesM = context.position < source.length ? parser(input) : undefined;
|
|
86
|
-
assert(context.position >= position);
|
|
87
86
|
context.range = context.position - position;
|
|
88
87
|
if (!nodesM && !optional) {
|
|
89
|
-
setBacktrack(context,
|
|
88
|
+
wbs && setBacktrack(context, wbs, position);
|
|
90
89
|
const result = g?.([nodesO, nodesM], context);
|
|
91
90
|
return result || void revert(context, linebreak);
|
|
92
91
|
}
|
|
93
92
|
const nodesC = nodesM || optional ? closer(input) : undefined;
|
|
94
|
-
assert(context.position >= position);
|
|
95
93
|
context.range = context.position - position;
|
|
96
94
|
if (!nodesC) {
|
|
97
|
-
setBacktrack(context,
|
|
95
|
+
wbs && setBacktrack(context, wbs, position);
|
|
98
96
|
const result = g?.([nodesO, nodesM], context);
|
|
99
97
|
return result || void revert(context, linebreak);
|
|
100
98
|
}
|
|
@@ -111,7 +109,7 @@ export function surround<N>(
|
|
|
111
109
|
return result || void revert(context, linebreak);
|
|
112
110
|
});
|
|
113
111
|
}
|
|
114
|
-
export function open<P extends Parser
|
|
112
|
+
export function open<P extends Parser>(
|
|
115
113
|
opener: string | RegExp | Parser<Node<P>, Context<P>>,
|
|
116
114
|
parser: P,
|
|
117
115
|
optional?: boolean,
|
|
@@ -127,11 +125,11 @@ export function open<N>(
|
|
|
127
125
|
opener: string | RegExp | Parser<N, Ctx>,
|
|
128
126
|
parser: string | RegExp | Parser<N>,
|
|
129
127
|
optional?: boolean,
|
|
130
|
-
backtracks
|
|
128
|
+
backtracks: readonly number[] = [],
|
|
131
129
|
): Parser<N> {
|
|
132
130
|
return surround(opener, parser as Parser<N>, '', optional, backtracks);
|
|
133
131
|
}
|
|
134
|
-
export function close<P extends Parser
|
|
132
|
+
export function close<P extends Parser>(
|
|
135
133
|
parser: P,
|
|
136
134
|
closer: string | RegExp | Parser<Node<P>, Context<P>>,
|
|
137
135
|
optional?: boolean,
|
|
@@ -147,72 +145,63 @@ export function close<N>(
|
|
|
147
145
|
parser: string | RegExp | Parser<N>,
|
|
148
146
|
closer: string | RegExp | Parser<N, Ctx>,
|
|
149
147
|
optional?: boolean,
|
|
150
|
-
backtracks
|
|
148
|
+
backtracks: readonly number[] = [],
|
|
151
149
|
): Parser<N> {
|
|
152
150
|
return surround('', parser as Parser<N>, closer, optional, backtracks);
|
|
153
151
|
}
|
|
154
152
|
|
|
155
|
-
const
|
|
153
|
+
const commandsize = 2;
|
|
156
154
|
export function isBacktrack(
|
|
157
155
|
context: Ctx,
|
|
158
|
-
|
|
156
|
+
backtrack: number,
|
|
159
157
|
position: number = context.position,
|
|
160
158
|
length: number = 1,
|
|
161
159
|
): boolean {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
for (let i = 0; i < length; ++i) {
|
|
169
|
-
if (position + i === source.length) break;
|
|
170
|
-
if (source[position + i] !== source[position + 0]) break;
|
|
171
|
-
const pos = position + i + offset;
|
|
172
|
-
if (!(pos in backtracks)) continue;
|
|
173
|
-
if (backtracks[pos] & 1 << size(backtrack >>> statesize)) return true;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
160
|
+
assert(1 & backtrack);
|
|
161
|
+
assert(backtrack >>> commandsize);
|
|
162
|
+
assert(0 < length && length < 3);
|
|
163
|
+
const { backtracks = {}, offset = 0 } = context;
|
|
164
|
+
for (let i = 0; i < length; ++i) {
|
|
165
|
+
if (backtracks[position + i + offset] & backtrack >>> commandsize) return true;
|
|
176
166
|
}
|
|
177
167
|
return false;
|
|
178
168
|
}
|
|
179
169
|
export function setBacktrack(
|
|
180
170
|
context: Ctx,
|
|
181
|
-
|
|
171
|
+
backtrack: number,
|
|
182
172
|
position: number,
|
|
183
173
|
length: number = 1,
|
|
184
174
|
): void {
|
|
185
175
|
// バックトラックの可能性がなく記録不要の場合もあるが判別が面倒なので省略
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
176
|
+
assert(2 & backtrack);
|
|
177
|
+
assert(backtrack >>> commandsize);
|
|
178
|
+
assert(0 < length && length < 3);
|
|
179
|
+
const { backtracks = {}, offset = 0 } = context;
|
|
180
|
+
for (let i = 0; i < length; ++i) {
|
|
181
|
+
backtracks[position + i + offset] |= backtrack >>> commandsize;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function reduce(backtracks: readonly number[]): readonly [number, number, number] {
|
|
185
|
+
let len = 1;
|
|
186
|
+
let rbs = 0;
|
|
187
|
+
let wbs = 0;
|
|
189
188
|
for (const backtrack of backtracks) {
|
|
190
|
-
if (backtrack
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
189
|
+
if (backtrack >>> commandsize === 0) {
|
|
190
|
+
len = backtrack;
|
|
191
|
+
assert(len > 0);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
assert(backtrack >>> commandsize);
|
|
195
|
+
if (1 & backtrack) {
|
|
196
|
+
rbs |= backtrack;
|
|
197
|
+
}
|
|
198
|
+
if (2 & backtrack) {
|
|
199
|
+
wbs |= backtrack;
|
|
197
200
|
}
|
|
198
201
|
}
|
|
202
|
+
return [len, rbs, wbs];
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
function revert(context: Ctx, linebreak: number | undefined): void {
|
|
202
206
|
context.linebreak = linebreak;
|
|
203
207
|
}
|
|
204
|
-
function size(bits: number): number {
|
|
205
|
-
if (bits === 0) return 0;
|
|
206
|
-
let p = 0;
|
|
207
|
-
for (let s = 32 / 2; s > 0; s >>>= 1) {
|
|
208
|
-
const q = p + s;
|
|
209
|
-
if (bits >>> q === 0) continue;
|
|
210
|
-
p = q;
|
|
211
|
-
}
|
|
212
|
-
return p + 1;
|
|
213
|
-
}
|
|
214
|
-
assert(size(0 << 0) === 0);
|
|
215
|
-
assert(size(1 << 0) === 1);
|
|
216
|
-
assert(size(1 << 1) === 2);
|
|
217
|
-
assert(size(1 << 30) === 31);
|
|
218
|
-
assert(size(1 << 31) === 32);
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import { Parser, Result, List, Data, Ctx, Node, Context, SubParsers, SubNode, IntermediateParser, failsafe } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function bind<P extends Parser
|
|
4
|
-
export function bind<P extends Parser
|
|
5
|
-
export function bind<N, P extends Parser
|
|
6
|
-
export function bind<U, P extends Parser
|
|
3
|
+
export function bind<P extends Parser>(parser: IntermediateParser<P>, f: (nodes: List<Data<SubNode<P>>>, context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>): P;
|
|
4
|
+
export function bind<P extends Parser>(parser: P, f: (nodes: List<Data<Node<P>>>, context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>): P;
|
|
5
|
+
export function bind<N, P extends Parser>(parser: Parser<N, Context<P>, SubParsers<P>>, f: (nodes: List<Data<N>>, context: Context<P>) => Result<Node<P>, Context<P>, SubParsers<P>>): P;
|
|
6
|
+
export function bind<U, P extends Parser>(parser: P, f: (nodes: List<Data<Node<P>>>, context: Context<P>) => Result<U, Context<P>, SubParsers<P>>): Parser<U, Context<P>, SubParsers<P>>;
|
|
7
7
|
export function bind<N, U>(parser: Parser<N>, f: (nodes: List<Data<N>>, context: Ctx) => Result<U>): Parser<U> {
|
|
8
8
|
assert(parser);
|
|
9
9
|
return failsafe(input => {
|
|
10
10
|
const { context } = input;
|
|
11
11
|
const { source, position } = context;
|
|
12
12
|
if (position === source.length) return;
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
if (res1 === undefined) return;
|
|
13
|
+
const result = parser(input);
|
|
14
|
+
if (result === undefined) return;
|
|
16
15
|
context.range = context.position - position;
|
|
17
|
-
|
|
18
|
-
assert(context.position > position || !res2);
|
|
19
|
-
return context.position > position
|
|
20
|
-
? res2
|
|
21
|
-
: undefined;
|
|
16
|
+
return f(result, context);
|
|
22
17
|
});
|
|
23
18
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Parser, List, Data, Ctx, SubParsers, Node, Context, IntermediateParser, SubNode } from '../../data/parser';
|
|
2
2
|
import { bind } from './bind';
|
|
3
3
|
|
|
4
|
-
export function fmap<P extends Parser
|
|
5
|
-
export function fmap<P extends Parser
|
|
6
|
-
export function fmap<N, P extends Parser
|
|
7
|
-
export function fmap<U, P extends Parser
|
|
4
|
+
export function fmap<P extends Parser>(parser: IntermediateParser<P>, f: (nodes: List<Data<SubNode<P>>>, context: Context<P>) => List<Data<Node<P>>>): P;
|
|
5
|
+
export function fmap<P extends Parser>(parser: P, f: (nodes: List<Data<Node<P>>>, context: Context<P>) => List<Data<Node<P>>>): P;
|
|
6
|
+
export function fmap<N, P extends Parser>(parser: Parser<N, Context<P>, SubParsers<P>>, f: (nodes: List<Data<N>>, context: Context<P>) => List<Data<Node<P>>>): P;
|
|
7
|
+
export function fmap<U, P extends Parser>(parser: P, f: (nodes: List<Data<Node<P>>>, context: Context<P>) => List<Data<U>>): Parser<U, Context<P>, SubParsers<P>>;
|
|
8
8
|
export function fmap<N, U>(parser: Parser<N>, f: (nodes: List<Data<N>>, context: Ctx) => List<Data<U>>): Parser<U> {
|
|
9
9
|
return bind(parser, (nodes, context) => f(nodes, context));
|
|
10
10
|
}
|
|
@@ -2,7 +2,7 @@ import { min } from 'spica/alias';
|
|
|
2
2
|
import { Parser, Result, List, Data, Ctx, CtxOptions, Node, Context } from '../../data/parser';
|
|
3
3
|
import { clone } from 'spica/assign';
|
|
4
4
|
|
|
5
|
-
export function reset<P extends Parser
|
|
5
|
+
export function reset<P extends Parser>(base: CtxOptions, parser: P): P;
|
|
6
6
|
export function reset<N>(base: Ctx, parser: Parser<N>): Parser<N> {
|
|
7
7
|
assert(Object.getPrototypeOf(base) === Object.prototype);
|
|
8
8
|
assert(Object.freeze(base));
|
|
@@ -13,7 +13,7 @@ export function reset<N>(base: Ctx, parser: Parser<N>): Parser<N> {
|
|
|
13
13
|
apply(parser, { ...context }, changes, values, true);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function context<P extends Parser
|
|
16
|
+
export function context<P extends Parser>(base: CtxOptions, parser: P): P;
|
|
17
17
|
export function context<N>(base: Ctx, parser: Parser<N>): Parser<N> {
|
|
18
18
|
assert(Object.getPrototypeOf(base) === Object.prototype);
|
|
19
19
|
assert(Object.freeze(base));
|
|
@@ -23,7 +23,7 @@ export function context<N>(base: Ctx, parser: Parser<N>): Parser<N> {
|
|
|
23
23
|
apply(parser, context, changes, values);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function apply<P extends Parser
|
|
26
|
+
function apply<P extends Parser>(parser: P, context: Context<P>, changes: readonly [string, unknown][], values: unknown[], reset?: boolean): Result<Node<P>>;
|
|
27
27
|
function apply<N>(parser: Parser<N>, context: Ctx, changes: readonly [string, unknown][], values: unknown[], reset = false): Result<N> {
|
|
28
28
|
for (let i = 0; i < changes.length; ++i) {
|
|
29
29
|
const change = changes[i];
|
|
@@ -64,8 +64,8 @@ function apply<N>(parser: Parser<N>, context: Ctx, changes: readonly [string, un
|
|
|
64
64
|
return result;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export function creation<P extends Parser
|
|
68
|
-
export function creation(cost: number, parser: Parser
|
|
67
|
+
export function creation<P extends Parser>(cost: number, parser: P): P;
|
|
68
|
+
export function creation(cost: number, parser: Parser): Parser {
|
|
69
69
|
assert(cost >= 0);
|
|
70
70
|
return input => {
|
|
71
71
|
const { context } = input;
|
|
@@ -85,8 +85,8 @@ export function consume(cost: number, context: Ctx): void {
|
|
|
85
85
|
resources.clock -= cost;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export function recursion<P extends Parser
|
|
89
|
-
export function recursion(recursion: number, parser: Parser
|
|
88
|
+
export function recursion<P extends Parser>(recursion: number, parser: P): P;
|
|
89
|
+
export function recursion(recursion: number, parser: Parser): Parser {
|
|
90
90
|
assert(recursion >= 0);
|
|
91
91
|
return input => {
|
|
92
92
|
const { context } = input;
|
|
@@ -102,7 +102,7 @@ export function recursion(recursion: number, parser: Parser<unknown>): Parser<un
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
export function precedence<P extends Parser
|
|
105
|
+
export function precedence<P extends Parser>(precedence: number, parser: P): P;
|
|
106
106
|
export function precedence<N>(precedence: number, parser: Parser<N>): Parser<N> {
|
|
107
107
|
assert(precedence >= 0);
|
|
108
108
|
return input => {
|
|
@@ -119,8 +119,8 @@ export function precedence<N>(precedence: number, parser: Parser<N>): Parser<N>
|
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
export function state<P extends Parser
|
|
123
|
-
export function state<P extends Parser
|
|
122
|
+
export function state<P extends Parser>(state: number, parser: P): P;
|
|
123
|
+
export function state<P extends Parser>(state: number, positive: boolean, parser: P): P;
|
|
124
124
|
export function state<N>(state: number, positive: boolean | Parser<N>, parser?: Parser<N>): Parser<N> {
|
|
125
125
|
if (typeof positive === 'function') {
|
|
126
126
|
parser = positive;
|
|
@@ -140,8 +140,8 @@ export function state<N>(state: number, positive: boolean | Parser<N>, parser?:
|
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
export function constraint<P extends Parser
|
|
144
|
-
//export function constraint<P extends Parser
|
|
143
|
+
export function constraint<P extends Parser>(state: number, parser: P): P;
|
|
144
|
+
//export function constraint<P extends Parser>(state: number, positive: boolean, parser: P): P;
|
|
145
145
|
export function constraint<N>(state: number, positive: boolean | Parser<N>, parser?: Parser<N>): Parser<N> {
|
|
146
146
|
if (typeof positive === 'function') {
|
|
147
147
|
parser = positive;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Parser, List, Data, Ctx, Node, Context, SubParsers, SubNode } from '../parser';
|
|
2
2
|
|
|
3
|
-
export function inits<P extends Parser
|
|
3
|
+
export function inits<P extends Parser>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
4
4
|
export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, Ctx, D> {
|
|
5
5
|
assert(parsers.every(f => f));
|
|
6
6
|
if (parsers.length === 1) return parsers[0];
|
|
7
7
|
return input => {
|
|
8
8
|
const { context } = input;
|
|
9
|
-
const { source
|
|
9
|
+
const { source } = context;
|
|
10
10
|
let nodes: List<Data<N>> | undefined;
|
|
11
11
|
for (let len = parsers.length, i = 0; i < len; ++i) {
|
|
12
12
|
if (context.position === source.length) break;
|
|
@@ -16,9 +16,6 @@ export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: Lis
|
|
|
16
16
|
nodes = nodes?.import(result) ?? result;
|
|
17
17
|
if (resume?.(result) === false) break;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
return context.position > position
|
|
21
|
-
? nodes
|
|
22
|
-
: undefined;
|
|
19
|
+
return nodes;
|
|
23
20
|
};
|
|
24
21
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Parser, List, Data, Ctx, Node, Context, SubParsers, SubNode } from '../parser';
|
|
2
2
|
|
|
3
|
-
export function sequence<P extends Parser
|
|
3
|
+
export function sequence<P extends Parser>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
4
4
|
export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, Ctx, D> {
|
|
5
5
|
assert(parsers.every(f => f));
|
|
6
6
|
if (parsers.length === 1) return parsers[0];
|
|
7
7
|
return input => {
|
|
8
8
|
const { context } = input;
|
|
9
|
-
const { source
|
|
9
|
+
const { source } = context;
|
|
10
10
|
let nodes: List<Data<N>> | undefined;
|
|
11
11
|
for (let len = parsers.length, i = 0; i < len; ++i) {
|
|
12
12
|
if (context.position === source.length) return;
|
|
@@ -16,9 +16,6 @@ export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes:
|
|
|
16
16
|
nodes = nodes?.import(result) ?? result;
|
|
17
17
|
if (resume?.(result) === false) return;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
return context.position > position
|
|
21
|
-
? nodes
|
|
22
|
-
: undefined;
|
|
19
|
+
return nodes;
|
|
23
20
|
};
|
|
24
21
|
}
|
|
@@ -3,8 +3,8 @@ import { Delimiters } from './context/delimiter';
|
|
|
3
3
|
|
|
4
4
|
type DelimiterOption = readonly [delimiter: string | RegExp, precedence: number];
|
|
5
5
|
|
|
6
|
-
export function some<P extends Parser
|
|
7
|
-
export function some<P extends Parser
|
|
6
|
+
export function some<P extends Parser>(parser: P, limit?: number): P;
|
|
7
|
+
export function some<P extends Parser>(parser: P, end?: string | RegExp, delimiters?: readonly DelimiterOption[], limit?: number): P;
|
|
8
8
|
export function some<N>(parser: Parser<N>, end?: string | RegExp | number, delimiters: readonly DelimiterOption[] = [], limit = -1): Parser<N> {
|
|
9
9
|
if (typeof end === 'number') return some(parser, undefined, delimiters, end);
|
|
10
10
|
assert(parser);
|
|
@@ -2,7 +2,7 @@ import { Parser, List, Data, Ctx, Node, Context, SubParsers, SubNode } from '../
|
|
|
2
2
|
import { union } from './union';
|
|
3
3
|
import { inits } from './inits';
|
|
4
4
|
|
|
5
|
-
export function subsequence<P extends Parser
|
|
5
|
+
export function subsequence<P extends Parser>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
6
6
|
export function subsequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, Ctx, D> {
|
|
7
7
|
assert(parsers.every(f => f));
|
|
8
8
|
return union(
|
|
@@ -2,7 +2,7 @@ import { Parser, List, Data, Ctx, Node, Context, SubParsers, SubNode } from '../
|
|
|
2
2
|
import { union } from './union';
|
|
3
3
|
import { sequence } from './sequence';
|
|
4
4
|
|
|
5
|
-
export function tails<P extends Parser
|
|
5
|
+
export function tails<P extends Parser>(parsers: SubParsers<P>, resume?: (nodes: List<Data<SubNode<P>>>) => boolean): SubNode<P> extends Node<P> ? P : Parser<SubNode<P>, Context<P>, SubParsers<P>>;
|
|
6
6
|
export function tails<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Data<N>>) => boolean): Parser<N, Ctx, D> {
|
|
7
7
|
return union(parsers.map((_, i) => sequence(parsers.slice(i), resume)) as D);
|
|
8
8
|
}
|