Skip to content

Commit 21f52ac

Browse files
authored
Merge pull request aichaos#105 from aichaos/bug/76-fix-deparse-functions
Fix the deparse method and add unit tests
2 parents 1f597e8 + 3a17f0e commit 21f52ac

5 files changed

Lines changed: 534 additions & 104 deletions

File tree

eg/deparse/README.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# RiveScript Deparse
2+
3+
This example purely consists of additional documentation and examples of the
4+
`deparse()` method of RiveScript.
5+
6+
## Relevant Methods
7+
8+
* `rs.deparse()`
9+
10+
This method exports the current in-memory representation of the RiveScript
11+
brain as a JSON-serializable data structure. See [Schema](#schema) for the
12+
format of this data structure.
13+
14+
* `rs.write(fh[, deparsed])`
15+
16+
This method converts a data structure like the one from `deparse()` into plain
17+
text RiveScript source code and writes it to the file-like object ``fh``.
18+
19+
By default this will use the current in-memory representation of the
20+
RiveScript brain. For example, if you loaded a directory of RiveScript files
21+
and then called `write()` you would get a large text blob that contains
22+
all the source code of all the files from that directory. Note, however, that
23+
the formatting of the original reply data might be lost because the output
24+
from `write()` is working backwards from the in-memory representation, so
25+
for example, comments in the original source code aren't preserved and places
26+
where `^Continue` was used will instead result in one single line of code
27+
in the output.
28+
29+
If you pass in a data structure formatted the same way as the one `deparse()`
30+
returns, you can write that code instead. This way you could
31+
programmatically generate RiveScript data (for example, from a custom user
32+
interface for authoring bots) and convert it into valid RiveScript source code
33+
using this method.
34+
35+
## Schema
36+
37+
The data structure returned by `deparse()` looks like this, annotated:
38+
39+
```yaml
40+
begin:
41+
global: map of key/value pairs for `! global` global variable definitions
42+
var: map of key/value pairs for `! var` bot variable definitions
43+
sub: map of key/value pairs for `! sub` substitution definitions
44+
person: map of key/value pairs for `! person` substitution definitions
45+
array: map of `! array` names to arrays of their values
46+
triggers: array of trigger data (see below)
47+
topics: map of topic names -> array of trigger data under that topic
48+
$name: []
49+
```
50+
51+
The trigger data is stored in arrays underneath `begin.triggers` (for those in
52+
the `> begin` block) and `topics.$NAME` for triggers under a particular topic,
53+
with the default topic being named "random".
54+
55+
Each trigger is an object with the following schema:
56+
57+
```yaml
58+
trigger: the plain text trigger
59+
reply: array of the plain text `-Reply` commands, or `[]`
60+
condition: array of the plain text `*Condition` commands, or `[]`
61+
redirect: the text of the `@Redirect` command, or `null`
62+
previous: the text of the `%Previous` command, or `null`
63+
```
64+
65+
## Examples
66+
67+
Here are some example code snippets that show what the deparsed data structure
68+
looks like.
69+
70+
Python Code (`example.py`)
71+
72+
```python
73+
from rivescript import RiveScript
74+
import json
75+
76+
bot = RiveScript()
77+
bot.load_file("example.rive")
78+
79+
dep = bot.deparse()
80+
print(json.dumps(dep, indent=2))
81+
```
82+
83+
RiveScript Code (`example.rive`)
84+
85+
```rivescript
86+
! version = 1.0
87+
88+
! var name = Aiden
89+
! var age = 5
90+
91+
! sub what's = what is
92+
93+
! array colors = red blue green yellow cyan magenta black white
94+
95+
> begin
96+
+ request
97+
- {ok}
98+
< begin
99+
100+
+ hello bot
101+
- Hello human.
102+
103+
+ hi robot
104+
@ hello bot
105+
106+
+ my name is *
107+
- <set name=<formal>>Nice to meet you, <get name>.
108+
- <set name=<formal>>Hello, <get name>.
109+
110+
+ what is my name
111+
* <get name> != undefined => Your name is <get name>.
112+
- You didn't tell me your name.
113+
114+
> topic game-global
115+
+ help
116+
- How to play...
117+
< topic
118+
119+
> topic game-room-1 inherits game-global
120+
+ look
121+
- You're in a room labeled "1".
122+
< topic
123+
124+
> object reverse javascript
125+
var msg = args.join(" ");
126+
return msg.split("").reverse().join("");
127+
< object
128+
129+
+ say * in reverse
130+
- <call>reverse <star></call>
131+
```
132+
133+
JSON output:
134+
135+
```javascript
136+
{
137+
"begin": {
138+
"global": {},
139+
"var": {
140+
"name": "Aiden",
141+
"age": "5"
142+
},
143+
"sub": {
144+
"what's": "what is"
145+
},
146+
"person": {},
147+
"array": {
148+
"colors": [
149+
"red",
150+
"blue",
151+
"green",
152+
"yellow",
153+
"cyan",
154+
"magenta",
155+
"black",
156+
"white"
157+
]
158+
},
159+
"triggers": [
160+
{
161+
"trigger": "request",
162+
"reply": [
163+
"{ok}"
164+
],
165+
"condition": [],
166+
"redirect": null,
167+
"previous": null
168+
}
169+
]
170+
},
171+
"topics": {
172+
"random": {
173+
"triggers": [
174+
{
175+
"trigger": "hello bot",
176+
"reply": [
177+
"Hello human."
178+
],
179+
"condition": [],
180+
"redirect": null,
181+
"previous": null
182+
},
183+
{
184+
"trigger": "hi robot",
185+
"reply": [],
186+
"condition": [],
187+
"redirect": "hello bot",
188+
"previous": null
189+
},
190+
{
191+
"trigger": "my name is *",
192+
"reply": [
193+
"<set name=<formal>>Nice to meet you, <get name>.",
194+
"<set name=<formal>>Hello, <get name>."
195+
],
196+
"condition": [],
197+
"redirect": null,
198+
"previous": null
199+
},
200+
{
201+
"trigger": "what is my name",
202+
"reply": [
203+
"You didn't tell me your name."
204+
],
205+
"condition": [
206+
"<get name> != undefined => Your name is <get name>."
207+
],
208+
"redirect": null,
209+
"previous": null
210+
},
211+
{
212+
"trigger": "say * in reverse",
213+
"reply": [
214+
"<call>reverse <star></call>"
215+
],
216+
"condition": [],
217+
"redirect": null,
218+
"previous": null
219+
}
220+
],
221+
"includes": {},
222+
"inherits": {}
223+
},
224+
"game-global": {
225+
"triggers": [
226+
{
227+
"trigger": "help",
228+
"reply": [
229+
"How to play..."
230+
],
231+
"condition": [],
232+
"redirect": null,
233+
"previous": null
234+
}
235+
],
236+
"includes": {},
237+
"inherits": {}
238+
},
239+
"game-room-1": {
240+
"triggers": [
241+
{
242+
"trigger": "look",
243+
"reply": [
244+
"You're in a room labeled \"1\"."
245+
],
246+
"condition": [],
247+
"redirect": null,
248+
"previous": null
249+
}
250+
],
251+
"includes": {},
252+
"inherits": {
253+
"game-global": 1
254+
}
255+
}
256+
}
257+
}
258+
```

eg/deparse/example.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python
2+
3+
# Manipulate sys.path to be able to import rivescript from this local git
4+
# repository.
5+
import os
6+
import sys
7+
sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
8+
9+
from rivescript import RiveScript
10+
import json
11+
12+
bot = RiveScript()
13+
bot.load_file("example.rive")
14+
15+
dep = bot.deparse()
16+
print(json.dumps(dep, indent=2))

eg/deparse/example.rive

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
! version = 1.0
2+
3+
! var name = Aiden
4+
! var age = 5
5+
6+
! sub what's = what is
7+
8+
! array colors = red blue green yellow cyan magenta black white
9+
10+
> begin
11+
+ request
12+
- {ok}
13+
< begin
14+
15+
+ hello bot
16+
- Hello human.
17+
18+
+ hi robot
19+
@ hello bot
20+
21+
+ my name is *
22+
- <set name=<formal>>Nice to meet you, <get name>.
23+
- <set name=<formal>>Hello, <get name>.
24+
25+
+ what is my name
26+
* <get name> != undefined => Your name is <get name>.
27+
- You didn't tell me your name.
28+
29+
> topic game-global
30+
+ help
31+
- How to play...
32+
< topic
33+
34+
> topic game-room-1 inherits game-global
35+
+ look
36+
- You're in a room labeled "1".
37+
< topic
38+
39+
> object reverse javascript
40+
var msg = args.join(" ");
41+
return msg.split("").reverse().join("");
42+
< object
43+
44+
+ say * in reverse
45+
- <call>reverse <star></call>

0 commit comments

Comments
 (0)