-
Notifications
You must be signed in to change notification settings - Fork 17
/
manySepBy.ts
66 lines (63 loc) · 1.93 KB
/
manySepBy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* @module parjs/internal/implementation/combinators
*/ /** */
import {ParjsAction} from "../../action";
import {QUIET_RESULT} from "../../special-results";
import {Issues} from '../../issues';
import {ReplyKind} from "../../../../reply";
import {AnyParserAction} from "../../../action";
import {ParsingState} from "../../state";
import _ = require('lodash');
import {ArrayHelpers} from "../../functions/helpers";
/**
* Created by User on 21-Nov-16.
*/
export class PrsManySepBy extends ParjsAction {
isLoud : boolean;
expecting : string;
constructor(private many : AnyParserAction, private sep : AnyParserAction, private maxIterations : number) {
super();
this.isLoud = many.isLoud;
this.expecting = many.expecting;
}
_apply(ps : ParsingState) {
let {many, sep, maxIterations, isLoud} = this;
let arr = [];
many.apply(ps);
if (ps.atLeast(ReplyKind.HardFail)) {
return;
} else if (ps.isSoft) {
ps.value = [];
ps.kind = ReplyKind.OK;
return;
}
let {position} = ps;
ArrayHelpers.maybePush(arr, ps.value);
let i = 1;
while (true) {
if (i >= maxIterations) break;
sep.apply(ps);
if (ps.isSoft) {
break;
} else if (ps.atLeast(ReplyKind.HardFail)) {
return;
}
many.apply(ps);
if (ps.isSoft) {
break;
} else if (ps.atLeast(ReplyKind.HardFail)) {
return;
}
if (maxIterations >= Infinity && ps.position === position) {
Issues.guardAgainstInfiniteLoop("many");
}
ArrayHelpers.maybePush(arr, ps.value);
position = ps.position;
i++;
}
ps.kind = ReplyKind.OK;
ps.position = position;
ps.value = arr;
return;
}
}