forked from francescomari/dfa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dfa.js
99 lines (69 loc) · 2.66 KB
/
dfa.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
exports.create = function (definition) {
var error;
function validate() {
var i, name, character, destination;
// Definition is mandatory
if (!definition) {
return "Invalid definition";
}
// Start state is mandatory
if (!definition.start) {
return "Start state not specified";
}
// Final states are mandatory
if (!definition.finals) {
return "Final states not specified";
}
// At least one final state must be specified
if (definition.finals.length === 0) {
return "No final states listed";
}
// Definition of states must be specified
if (!definition.states) {
return "No states specified";
}
// Definition of start state must be specified
if (definition.start in definition.states === false) {
return "The initial state has no definition";
}
// Definition of every final state must be specified
for (i = 0; i < definition.finals.length; i++) {
if (definition.finals[i] in definition.states === false) {
return "Final state '" + definition.finals[i] + "' has no definition";
}
}
for (name in definition.states) {
for (character in definition.states[name]) {
// Each state must process one character at a time
if (character.length !== 1) {
return "Invalid character '" + character + "' for state '" + name + "'";
}
destination = definition.states[name][character];
// The destination for each state must have a definition
if (destination in definition.states === false) {
return "State '" + name + "' wants to jump to non-existing state '" + destination + "'";
}
}
}
return null;
}
error = validate();
if (error) {
throw new Error(error);
}
return {
accept: function (s) {
var i, current;
if (typeof s !== "string") {
throw new Error("Input is not a string");
}
current = definition.start;
// During the process, current can be undefined because of unrecognized character
// for the current state. We can stop the loop as soon as current becomes undefined.
for (i = 0; i < s.length && current; i++) {
current = definition.states[current][s[i]];
}
return definition.finals.indexOf(current) !== -1;
}
};
}