-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcdawg.go
121 lines (103 loc) · 3.03 KB
/
cdawg.go
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
120
121
// Copyright 2015 Cutehacks AS. All rights reserved.
// License can be found in the LICENSE file.
package main
import (
"fmt"
"os"
"sort"
"strconv"
"strings"
"io/ioutil"
"encoding/json"
)
type Node struct {
value string
pattern string
key uint8
nodes map[uint8] *Node
}
func NewNode() *Node {
return &Node{
nodes: make(map[uint8] *Node),
}
}
func BuildGraph(mapping map[string]string) (*Node) {
var keys []string
for k := range mapping {
keys = append(keys, k)
}
sort.Strings(keys)
root := NewNode()
for _, k := range keys {
var tree = root
for i := 0; i < len(k); i++ {
key := k[i]
sub, ok := tree.nodes[key];
if !ok {
sub = NewNode()
tree.nodes[key] = sub
}
sub.key = key
tree = sub
}
tree.value = mapping[k]
tree.pattern = k
}
return root
}
func WriteSwitch(root *Node, depth int, indent string) {
indent += " "
if len(root.nodes) == 0 {
fmt.Println(indent + "return QPair<const uint *, int>(0, 0); // no deeper pattern")
return
}
if (depth == 0) {
fmt.Println(indent + "if (i >= length)")
fmt.Println(indent + " return QPair<const uint *, int>(0, 0);")
fmt.Println(indent + "switch (text[i].unicode()) {")
} else {
fmt.Println(indent + "if (i + " + strconv.Itoa(depth) + " >= length)")
fmt.Println(indent + " return QPair<const uint *, int>(0, 0);")
fmt.Println(indent + "switch (text[i + " + strconv.Itoa(depth) + "].unicode()) {")
}
for key := range root.nodes {
sub, _ := root.nodes[key]
if len(sub.value) > 0 { // we have a match
fmt.Println(indent + " case " + strconv.Itoa(int(key)) + ":")
fmt.Println(indent + " if (i + " + strconv.Itoa(depth + 1) + " >= length || text[i + " + strconv.Itoa(depth + 1) + "].isSpace() || text[i + " + strconv.Itoa(depth + 1) + "].isPunct()) {")
fmt.Println(indent + " static const uint unicode[] = { 0x" + strings.Replace(sub.value, "-", ", 0x", -1) + ", 0 };")
fmt.Println(indent + " return QPair<const uint *, int>(unicode, " + strconv.Itoa(depth + 1 ) + ");" + " // " + sub.pattern + " found")
fmt.Println(indent + " }")
WriteSwitch(sub, depth + 1, indent + " ")
} else { // continue searching
fmt.Println(indent + " case " + strconv.Itoa(int(key)) + ": ")
WriteSwitch(sub, depth + 1, indent + " ")
}
}
fmt.Println(indent + " default: return QPair<const uint *, int>(0, 0);");
fmt.Println(indent + "}")
}
func WriteFunc(root *Node) {
fmt.Println("// Generated by the CDAWG tool by Cutehacks AS.")
fmt.Println("// See https://github.com/Cutehacks/cdawg\n")
fmt.Println("#include <QPair>")
fmt.Println("#include <QString>\n")
fmt.Println("QPair<const uint *, int> cdawg_match(const QString &text, int length, int i)\n{")
WriteSwitch(root, 0, "")
fmt.Println(" return QPair<const uint *, int>(0, 0);")
fmt.Println("}")
}
func main() {
data, err := ioutil.ReadFile(os.Args[1])
if err != nil {
fmt.Println(err)
return
}
var mapping map[string]string
err = json.Unmarshal([]byte(data), &mapping)
if err != nil {
fmt.Println(err)
return
}
WriteFunc(BuildGraph(mapping))
}