-
Notifications
You must be signed in to change notification settings - Fork 0
/
node.js
119 lines (99 loc) · 2.98 KB
/
node.js
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'use strict';
let counter = 0;
class Node {
constructor(accepting) {
this._transitions = new Map();
this._accepting = accepting;
this._id = counter++;
}
addTransition(symbol, node) {
let insert = {
target: node
};
if (!this._transitions.has(symbol)) {
this._transitions.set(symbol, [insert]);
} else {
this._transitions.get(symbol).push(insert);
}
}
deleteTransition(symbol) {
if (this._transitions.has(symbol)) {
this._transitions.delete(symbol);
}
}
getAllNonDeterministicTransitions() {
let transitions = [];
this._getAllNonDeterministicTransitions(transitions, new Map());
return transitions;
}
getTransitions(symbol) {
if (this._transitions.has(symbol)) {
return this._transitions.get(symbol);
}
return this._transitions.get('$REMAINING');
}
hasTransition(symbol) {
return this._transitions.has(symbol);
}
forEachTransition(func) {
for (let [transitionKey, transitionData] of this._transitions.entries()) {
func(transitionKey, transitionData);
}
}
getId() {
return this._id;
}
isAccepting() {
return this._accepting;
}
isNonDeterministicAccepting() {
return this._isNonDeterministicAccepting(new Map());
}
_isNonDeterministicAccepting(seenNodes) {
if (seenNodes.has(this)) {
return false;
}
seenNodes.set(this, '');
if (this._accepting === true) {
return this._accepting;
}
let ret = false;
if (this.hasTransition('$EMPTY')) {
this.getTransitions('$EMPTY').forEach((transition) => {
if (transition.target._isNonDeterministicAccepting(seenNodes)) {
ret = true;
}
});
}
return ret;
}
_getAllNonDeterministicTransitions(transitions, seenNodes) {
if (seenNodes.has(this)) {
return;
}
this.forEachTransition((transitionKey, transitionData) => {
transitionData.forEach((transition) => {
if (transitionKey === '$EMPTY') {
transition.target._getAllNonDeterministicTransitions(transitions, new Map([...seenNodes.entries()].concat([[this, '']])));
} else {
transitions.push({
key: transitionKey
, target: transition.target
});
}
});
});
}
_collect(collection) {
if (collection.includes(this)) {
return;
}
collection.push(this);
this.forEachTransition((transitionKey, transitionData) => {
transitionData.forEach((subData) => {
subData.target._collect(collection);
});
});
}
};
module.exports = Node;