-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathPosInfo.js
More file actions
102 lines (90 loc) · 3.23 KB
/
Copy pathPosInfo.js
File metadata and controls
102 lines (90 loc) · 3.23 KB
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
export class PosInfo {
constructor() {
this.applicationMemoKeyStack = []; // active applications at this position
this.memo = {};
this.maxExaminedLength = 0;
this.maxRightmostFailureOffset = -1;
this.currentLeftRecursion = undefined;
}
isActive(application) {
return this.applicationMemoKeyStack.indexOf(application.toMemoKey()) >= 0;
}
enter(application) {
this.applicationMemoKeyStack.push(application.toMemoKey());
}
exit() {
this.applicationMemoKeyStack.pop();
}
startLeftRecursion(headApplication, memoRec) {
memoRec.isLeftRecursion = true;
memoRec.headApplication = headApplication;
memoRec.nextLeftRecursion = this.currentLeftRecursion;
this.currentLeftRecursion = memoRec;
const {applicationMemoKeyStack} = this;
const indexOfFirstInvolvedRule =
applicationMemoKeyStack.indexOf(headApplication.toMemoKey()) + 1;
const involvedApplicationMemoKeys = applicationMemoKeyStack.slice(
indexOfFirstInvolvedRule
);
memoRec.isInvolved = function (applicationMemoKey) {
return involvedApplicationMemoKeys.indexOf(applicationMemoKey) >= 0;
};
memoRec.updateInvolvedApplicationMemoKeys = function () {
for (let idx = indexOfFirstInvolvedRule; idx < applicationMemoKeyStack.length; idx++) {
const applicationMemoKey = applicationMemoKeyStack[idx];
if (!this.isInvolved(applicationMemoKey)) {
involvedApplicationMemoKeys.push(applicationMemoKey);
}
}
};
}
endLeftRecursion() {
this.currentLeftRecursion = this.currentLeftRecursion.nextLeftRecursion;
}
// Note: this method doesn't get called for the "head" of a left recursion -- for LR heads,
// the memoized result (which starts out being a failure) is always used.
shouldUseMemoizedResult(memoRec) {
if (!memoRec.isLeftRecursion) {
return true;
}
const {applicationMemoKeyStack} = this;
for (let idx = 0; idx < applicationMemoKeyStack.length; idx++) {
const applicationMemoKey = applicationMemoKeyStack[idx];
if (memoRec.isInvolved(applicationMemoKey)) {
return false;
}
}
return true;
}
memoize(memoKey, memoRec) {
this.memo[memoKey] = memoRec;
this.maxExaminedLength = Math.max(this.maxExaminedLength, memoRec.examinedLength);
this.maxRightmostFailureOffset = Math.max(
this.maxRightmostFailureOffset,
memoRec.rightmostFailureOffset
);
return memoRec;
}
clearObsoleteEntries(pos, invalidatedIdx) {
if (pos + this.maxExaminedLength <= invalidatedIdx) {
// Optimization: none of the rule applications that were memoized here examined the
// interval of the input that changed, so nothing has to be invalidated.
return;
}
const {memo} = this;
this.maxExaminedLength = 0;
this.maxRightmostFailureOffset = -1;
Object.keys(memo).forEach(k => {
const memoRec = memo[k];
if (pos + memoRec.examinedLength > invalidatedIdx) {
memo[k] = undefined;
} else {
this.maxExaminedLength = Math.max(this.maxExaminedLength, memoRec.examinedLength);
this.maxRightmostFailureOffset = Math.max(
this.maxRightmostFailureOffset,
memoRec.rightmostFailureOffset
);
}
});
}
}