forked from appgurueu/lustils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.js
108 lines (93 loc) · 2.4 KB
/
parse.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
const {
deepClone
} = require("./object.js");
const {
obtainStreams
} = require("./stream.js");
function isDigit(x) {
return x >= "0" && x <= "9";
}
function isLetter(x) {
return (x >= "a" && x <= "z") || (x >= "A" && x <= "Z");
}
function isHexDigit(x) {
return isDigit(x) || (x >= "a" && x <= "f") || (x >= "A" && x <= "F");
}
class MealyState {
constructor() {
this.transitions = {};
this.any = {
state: this,
write: true
};
}
setAnyTransition(transition) {
this.any = transition;
}
consume(aut, c) {
return this.transitions[c] || this.any;
}
setTransition(character, transition) {
if (Array.isArray(character)) {
for (let c of character) {
this.setTransition(c, transition);
}
} else {
this.transitions[character] = transition;
}
}
}
class MealySpecialState extends MealyState {
constructor() {
super();
}
setConsumer(consumer) {
this.consume = consumer;
}
}
class ExtendedMealyMachineBase {
constructor(data, initial_state) {
this.data = data || {};
this.initial_state = initial_state || new MealyState();
}
}
class ExtendedMealyMachine {
constructor(base) {
this.current_state = base.initial_state;
this.data = deepClone(base.data);
}
consume(c, output) {
let transition = this.current_state.consume(this, c);
if (!transition.state) {
return;
}
this.current_state = transition.state;
if (transition.write) {
output.write(transition.write === true ? c : transition.write);
}
}
consumeStream(input, output) {
let c;
while ((c = input.read()) && typeof (c) === "string" && c !== "") {
this.consume(c, output);
}
this.consume("", output); // in order to write out the buffer
}
static applier(machine_base) {
return function (input, output) {
[input, output] = obtainStreams(input, output);
let machine = new ExtendedMealyMachine(machine_base);
machine.consumeStream(input, output);
return output;
};
}
}
module.exports = {
isDigit,
isLetter,
isHexDigit,
MealyState,
MealySpecialState,
ExtendedMealyMachineBase,
ExtendedMealyMachine,
};