-
Notifications
You must be signed in to change notification settings - Fork 15
/
parser.go
129 lines (119 loc) · 3.22 KB
/
parser.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
122
123
124
125
126
127
128
129
package rivescript
// parse loads the RiveScript code into the bot's memory.
func (rs *RiveScript) parse(path string, lines []string) error {
rs.say("Parsing code...")
// Get the abstract syntax tree of this file.
AST, err := rs.parser.Parse(path, lines)
if err != nil {
return err
}
// Get all of the "begin" type variables
for k, v := range AST.Begin.Global {
if v == UNDEFTAG {
delete(rs.global, k)
} else {
rs.global[k] = v
}
}
for k, v := range AST.Begin.Var {
if v == UNDEFTAG {
delete(rs.vars, k)
} else {
rs.vars[k] = v
}
}
for k, v := range AST.Begin.Sub {
if v == UNDEFTAG {
delete(rs.sub, k)
} else {
rs.sub[k] = v
}
}
for k, v := range AST.Begin.Person {
if v == UNDEFTAG {
delete(rs.person, k)
} else {
rs.person[k] = v
}
}
for k, v := range AST.Begin.Array {
rs.array[k] = v
}
// Consume all the parsed triggers.
for topic, data := range AST.Topics {
// Keep a map of the topics that are included/inherited under this topic.
if _, ok := rs.includes[topic]; !ok {
rs.includes[topic] = map[string]bool{}
}
if _, ok := rs.inherits[topic]; !ok {
rs.inherits[topic] = map[string]bool{}
}
// Merge in the topic inclusions/inherits.
for included := range data.Includes {
rs.includes[topic][included] = true
}
for inherited := range data.Inherits {
rs.inherits[topic][inherited] = true
}
// Initialize the topic structure.
if _, ok := rs.topics[topic]; !ok {
rs.topics[topic] = new(astTopic)
rs.topics[topic].triggers = []*astTrigger{}
}
// Consume the AST triggers into the brain.
for _, trig := range data.Triggers {
// Convert this AST trigger into an internal astmap trigger.
foundtrigger := false
for _, previous := range rs.topics[topic].triggers {
if previous.trigger == trig.Trigger && previous.previous == trig.Previous {
previous.redirect = trig.Redirect
foundtrigger = true
for _, cond := range trig.Condition {
foundcond := false
for _, oldcond := range previous.condition {
if oldcond == cond {
foundcond = true
break
}
}
if !foundcond {
previous.condition = append(previous.condition, cond)
}
}
for _, reply := range trig.Reply {
newreply := true
for _, oldreply := range previous.reply {
if oldreply == reply {
newreply = false
break
}
}
if newreply {
previous.reply = append(previous.reply, reply)
}
}
rs.say("Found previous trigger: %s == %s", trig.Trigger, previous.trigger)
}
}
if !foundtrigger {
trigger := new(astTrigger)
trigger.trigger = trig.Trigger
trigger.reply = trig.Reply
trigger.condition = trig.Condition
trigger.redirect = trig.Redirect
trigger.previous = trig.Previous
rs.topics[topic].triggers = append(rs.topics[topic].triggers, trigger)
}
}
}
// Load all the parsed objects.
for _, object := range AST.Objects {
// Have a language handler for this?
if _, ok := rs.handlers[object.Language]; ok {
rs.say("Loading object macro %s (%s)", object.Name, object.Language)
rs.handlers[object.Language].Load(object.Name, object.Code)
rs.objlangs[object.Name] = object.Language
}
}
return nil
}