-
Notifications
You must be signed in to change notification settings - Fork 1
/
cyk.js
86 lines (76 loc) · 2.67 KB
/
cyk.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
class CYK {
constructor(input) {
this.word = input.word
this.productions = input.productions
// Allocate 2d array for table of size word*word
this.table = []
for (let i = 0; i < this.word.length; i++) {
this.table[i] = []
for (let j = 0; j < this.word.length; j++) {
this.table[i][j] = null
}
}
}
get_producers(product) {
return new Set(this.productions
// Keep all productions which contain the searched product
.filter(production => production.products.has(product))
// Return producer (non-terminal)
.map(production => production.producer))
}
calc(start, end) {
// Cell is already calculated
if (this.table[start][end]) {
return this.table[start][end]
}
// Entry on the diagonal
if (start == end) {
this.table[start][end] = this.get_producers(this.word[start])
return this.table[start][end]
}
// Calculate cell
for (let i = start; i < end; i++) {
// Calculate word composition
const prefix = this.calc(start, i)
const suffix = this.calc(i+1, end)
if (!this.table[start][end]) {
this.table[start][end] = new Set()
}
// Try each permutation of prefix and suffix
for (let prefix_nt of prefix) {
for (let suffix_nt of suffix) {
const producer = this.get_producers(prefix_nt + suffix_nt)
// Merge old set with new entries
this.table[start][end] = new Set([...this.table[start][end], ...producer])
}
}
}
return this.table[start][end]
}
toString() {
this.calc(0, this.word.length-1)
let output = "<table><tr><th></th>"
for (let i in this.table[0]) {
output += `<th>${Number(i)+1}</th>`
}
output += "</tr>"
for (let line_index in this.table) {
output += `<tr><td>${Number(line_index)+1}</td>`
const line = this.table[line_index]
for (let item_set of line) {
let item_str = ""
if (!item_set) {
// This field is not looked at
} else if (item_set.size == 0) {
item_str = "-"
} else {
item_str = Array.from(item_set).join()
}
output += `<td>${item_str}</td>`
}
output += "</tr>"
}
output += "</table>"
return output
}
}