story-gen 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS +5 -1
- data/README.md +17 -0
- data/lib/names.rb +6 -217
- data/lib/story/compile.rb +70 -27
- data/sample/fight_club.sdl +10 -11
- data/sample//320/261/320/276/320/271/321/206/320/276/320/262/321/201/320/272/320/270/320/271_/320/272/320/273/321/203/320/261.sdl +11 -11
- metadata +18 -2
data/NEWS
CHANGED
data/README.md
CHANGED
@@ -249,6 +249,23 @@ There are other statements you can use:
|
|
249
249
|
|
250
250
|
A random <statement> is chosen and executed.
|
251
251
|
|
252
|
+
- "When":
|
253
|
+
|
254
|
+
<pre><code>
|
255
|
+
When <fact> <statement>
|
256
|
+
</code></pre>
|
257
|
+
|
258
|
+
When you try to state the <fact> then <statement> is executed.
|
259
|
+
|
260
|
+
<pre><code>
|
261
|
+
When X loves Y:
|
262
|
+
""X" marries "Y"!";
|
263
|
+
.
|
264
|
+
"John" loves "Liza";
|
265
|
+
</code></pre>
|
266
|
+
|
267
|
+
The code above prints "John marries Liza!"
|
268
|
+
|
252
269
|
### Notes ###
|
253
270
|
|
254
271
|
`(note: ...)` comment may have nested parentheses:
|
data/lib/names.rb
CHANGED
@@ -1,237 +1,26 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
+
require 'ffaker'
|
2
3
|
|
3
4
|
class Names
|
4
5
|
|
5
6
|
# @return [Array<String>]
|
6
7
|
def self.russian_male
|
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
|
-
}
|
8
|
+
FFaker::NameRU::FIRST_NAMES[:male]
|
107
9
|
end
|
108
10
|
|
109
11
|
# @return [Array<String>]
|
110
12
|
def self.russian_female
|
111
|
-
|
112
|
-
Агата
|
113
|
-
Ада
|
114
|
-
Адель
|
115
|
-
Адриана
|
116
|
-
Алевтина
|
117
|
-
Александра
|
118
|
-
Алина
|
119
|
-
Алиса
|
120
|
-
Алла
|
121
|
-
Альбина
|
122
|
-
Анастасия
|
123
|
-
Ангелина
|
124
|
-
Анжела
|
125
|
-
Анна
|
126
|
-
Антонина
|
127
|
-
Анфиса
|
128
|
-
Арина
|
129
|
-
|
130
|
-
Богдана
|
131
|
-
Борислава
|
132
|
-
|
133
|
-
Валентина
|
134
|
-
Валерия
|
135
|
-
Варвара
|
136
|
-
Василиса
|
137
|
-
Вера
|
138
|
-
Вероника
|
139
|
-
Виктория
|
140
|
-
Виолетта
|
141
|
-
|
142
|
-
Галина
|
143
|
-
|
144
|
-
Дарья
|
145
|
-
Диана
|
146
|
-
|
147
|
-
Ева
|
148
|
-
Евгения
|
149
|
-
Екатерина
|
150
|
-
Елена
|
151
|
-
Елизавета
|
152
|
-
|
153
|
-
Жанна
|
154
|
-
|
155
|
-
Зинаида
|
156
|
-
Зоя
|
157
|
-
|
158
|
-
Илона
|
159
|
-
Инга
|
160
|
-
Инесса
|
161
|
-
Инна
|
162
|
-
Ирина
|
163
|
-
|
164
|
-
Карина
|
165
|
-
Кира
|
166
|
-
Клавдия
|
167
|
-
Клара
|
168
|
-
Кристина
|
169
|
-
Ксения
|
170
|
-
|
171
|
-
Лариса
|
172
|
-
Лидия
|
173
|
-
Лилия
|
174
|
-
Любовь
|
175
|
-
Людмила
|
176
|
-
|
177
|
-
Майя
|
178
|
-
Маргарита
|
179
|
-
Марина
|
180
|
-
Мария
|
181
|
-
Марта
|
182
|
-
Марьяна
|
183
|
-
Мирослава
|
184
|
-
|
185
|
-
Надежда
|
186
|
-
Наталья
|
187
|
-
Нелли
|
188
|
-
Нина
|
189
|
-
|
190
|
-
Оксана
|
191
|
-
Ольга
|
192
|
-
|
193
|
-
Полина
|
194
|
-
|
195
|
-
Раиса
|
196
|
-
Регина
|
197
|
-
Римма
|
198
|
-
Роза
|
199
|
-
Роксана
|
200
|
-
Руслана
|
201
|
-
|
202
|
-
Светлана
|
203
|
-
Снежана
|
204
|
-
София
|
205
|
-
|
206
|
-
Таисия
|
207
|
-
Тамара
|
208
|
-
Татьяна
|
209
|
-
|
210
|
-
Ульяна
|
211
|
-
|
212
|
-
Христина
|
213
|
-
|
214
|
-
Эвелина
|
215
|
-
Элеонора
|
216
|
-
Эльвира
|
217
|
-
Эмма
|
218
|
-
|
219
|
-
Юлиана
|
220
|
-
Юлия
|
221
|
-
|
222
|
-
Яна
|
223
|
-
Ярослава
|
224
|
-
}
|
13
|
+
FFaker::NameRU::FIRST_NAMES[:female]
|
225
14
|
end
|
226
15
|
|
227
16
|
# @return [Array<String>]
|
228
17
|
def self.english_male
|
229
|
-
|
18
|
+
FFaker::Name::FIRST_NAMES_MALE
|
230
19
|
end
|
231
20
|
|
232
21
|
# @return [Array<String>]
|
233
22
|
def self.english_female
|
234
|
-
|
23
|
+
FFaker::Name::FIRST_NAMES_FEMALE
|
235
24
|
end
|
236
25
|
|
237
|
-
end
|
26
|
+
end
|
data/lib/story/compile.rb
CHANGED
@@ -28,26 +28,31 @@ class Story
|
|
28
28
|
#
|
29
29
|
c = Parse.new.(text, file).to_code
|
30
30
|
#
|
31
|
-
|
32
|
-
|
31
|
+
relation_id_to_var_id = Hash.new { |h, relation_id| h[relation_id] = h.size }
|
32
|
+
relation_ids = lambda { relation_id_to_var_id.keys }
|
33
|
+
relation_id_to_var_arg_valuesss_var = lambda do |relation_id|
|
34
|
+
"@#{INTERNAL_VAR_PREFIX}var_arg_valuesss#{relation_id_to_var_id[relation_id]}"
|
35
|
+
end
|
36
|
+
relation_id_to_trigger_var = lambda do |relation_id|
|
37
|
+
"@#{INTERNAL_VAR_PREFIX}trigger#{relation_id_to_var_id[relation_id]}"
|
33
38
|
end
|
34
39
|
#
|
35
40
|
c = c.map_non_code_parts do |part|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
41
|
+
case part
|
42
|
+
when VarArgValuesssVar then relation_id_to_var_arg_valuesss_var[part.relation_id]
|
43
|
+
when TriggerVar then relation_id_to_trigger_var[part.relation_id]
|
44
|
+
else raise "unknown non-code part type: #{part.inspect}"
|
40
45
|
end
|
41
46
|
end
|
42
47
|
#
|
43
|
-
relation_ids_code =
|
48
|
+
relation_ids_code = relation_ids.().
|
44
49
|
map { |relation_id| relation_id.join(" ") }.
|
45
50
|
sort.
|
46
51
|
to_rb
|
47
52
|
#
|
48
|
-
init_var_arg_valuesss_vars =
|
49
|
-
map do |relation_id
|
50
|
-
"#{
|
53
|
+
init_var_arg_valuesss_vars = relation_ids.().
|
54
|
+
map do |relation_id|
|
55
|
+
"#{relation_id_to_var_arg_valuesss_var[relation_id]} = Set.new # #{relation_id}\n"
|
51
56
|
end.
|
52
57
|
join_code
|
53
58
|
#
|
@@ -118,6 +123,9 @@ class Story
|
|
118
123
|
# @!visibility private
|
119
124
|
VarArgValuesssVar = Struct.new :relation_id, :pos
|
120
125
|
|
126
|
+
#@!visibility private
|
127
|
+
TriggerVar = Struct.new :relation_id, :pos
|
128
|
+
|
121
129
|
Var = ASTNode.new :name, :original_name do
|
122
130
|
|
123
131
|
alias name_super name
|
@@ -202,24 +210,24 @@ class Story
|
|
202
210
|
reject
|
203
211
|
else
|
204
212
|
args = subexpr.args
|
213
|
+
args_code = args.zip(0...args.size).
|
214
|
+
map do |arg, i|
|
215
|
+
case arg
|
216
|
+
when Asterisk then raise Parse::Error.new(arg.pos, "not supported")
|
217
|
+
when Var then at(arg.pos) { arg.name }
|
218
|
+
when Above[Var] then at(arg.pos) { arg.var.name }
|
219
|
+
else arg.to_rb
|
220
|
+
end
|
221
|
+
end.
|
222
|
+
join_code(", ")
|
223
|
+
trigger_var = non_code(TriggerVar[subexpr.relation_id, pos])
|
205
224
|
code <<
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
raise Parse::Error.new(arg.pos, "not supported")
|
213
|
-
when Var then
|
214
|
-
at(arg.pos) { arg.name }
|
215
|
-
when Above[Var] then
|
216
|
-
at(arg.pos) { arg.var.name }
|
217
|
-
else
|
218
|
-
arg.to_rb
|
219
|
-
end
|
220
|
-
end.
|
221
|
-
join_code(", ") <<
|
222
|
-
"])"
|
225
|
+
"(if " << trigger_var << " then " << "\n"<<
|
226
|
+
trigger_var << ".call(" << args_code << ")" << "\n"<<
|
227
|
+
"else" << "\n" <<
|
228
|
+
non_code(VarArgValuesssVar[subexpr.relation_id, pos]) <<
|
229
|
+
".add([" << args_code << "])" << "\n"<<
|
230
|
+
"end)"
|
223
231
|
end
|
224
232
|
end
|
225
233
|
|
@@ -249,6 +257,34 @@ class Story
|
|
249
257
|
|
250
258
|
end
|
251
259
|
|
260
|
+
Statement::When = ASTNode.new :condition, :action do
|
261
|
+
|
262
|
+
def to_code
|
263
|
+
case condition
|
264
|
+
when FactExpr::Primary
|
265
|
+
args_code = condition.args.
|
266
|
+
map do |arg|
|
267
|
+
case arg
|
268
|
+
when Asterisk then nil
|
269
|
+
when Var then arg.name
|
270
|
+
when Above[Var] then arg.var.name
|
271
|
+
else raise Parse::Error.new(arg.pos, "not supported")
|
272
|
+
end
|
273
|
+
end.
|
274
|
+
compact.
|
275
|
+
join_code(", ")
|
276
|
+
code << "(" << non_code(TriggerVar[condition.relation_id, pos]) << " = " <<
|
277
|
+
"lambda do |" << args_code << "|\n" <<
|
278
|
+
action.to_code << "\n" <<
|
279
|
+
"end\n" <<
|
280
|
+
")"
|
281
|
+
else
|
282
|
+
raise Parse::Error.new(condition.pos, "not supported")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
252
288
|
Statement::Compound = ASTNode.new :statements do
|
253
289
|
|
254
290
|
def to_code
|
@@ -616,6 +652,7 @@ class Story
|
|
616
652
|
|
617
653
|
rule :statement do
|
618
654
|
_{ statement_if } or
|
655
|
+
_{ statement_when } or
|
619
656
|
_{ statement_while } or
|
620
657
|
_{ statement_for_all } or
|
621
658
|
_{ statement_n_times } or
|
@@ -669,6 +706,11 @@ class Story
|
|
669
706
|
}
|
670
707
|
end
|
671
708
|
|
709
|
+
rule :statement_when do
|
710
|
+
_when_ and f = fact_expr_primary and s = statement and
|
711
|
+
_(Statement::When[f, s])
|
712
|
+
end
|
713
|
+
|
672
714
|
rule :statement_while do
|
673
715
|
_while_ and f = fact_expr and s = statement and
|
674
716
|
_(Statement::While[f, s])
|
@@ -845,6 +887,7 @@ class Story
|
|
845
887
|
keyword :all, "`all'", /^(all|всех)$/
|
846
888
|
keyword :_while_, "`while'", /^([Ww]hile|[Пп]ока)$/
|
847
889
|
keyword :_if_, "`if'", /^([Ii]f|[Ее]сли)$/
|
890
|
+
keyword :_when_, "`when'", /^([Ww]hen|[Кк]огда)$/
|
848
891
|
keyword :_then_, "`then'", /^(then|то)$/
|
849
892
|
keyword :otherwise, "`otherwise'", /^([Oo]therwise|[Ии]наче)$/
|
850
893
|
keyword :_not_, "`not'", /^(not|не)$/
|
data/sample/fight_club.sdl
CHANGED
@@ -8,7 +8,6 @@ Fight club
|
|
8
8
|
|
9
9
|
```
|
10
10
|
require 'unique_names'
|
11
|
-
|
12
11
|
names = UniqueNames.english_male
|
13
12
|
```
|
14
13
|
|
@@ -33,6 +32,15 @@ names = UniqueNames.english_male
|
|
33
32
|
nl;
|
34
33
|
.
|
35
34
|
|
35
|
+
When A beats B:
|
36
|
+
if:
|
37
|
+
- ^A uses "hands" then ""A" has beaten "B". ";
|
38
|
+
- ^A uses "feet" then ""A" has kicked "B". ";
|
39
|
+
- ^A uses "hooves" then ""A" has kicked "B" and knocked him out. ";
|
40
|
+
- ^A uses "claws" then ""A" has scratched the whole "B". ";
|
41
|
+
B is not in;
|
42
|
+
.
|
43
|
+
|
36
44
|
nl
|
37
45
|
"Let the tournament begin!" nl
|
38
46
|
nl
|
@@ -40,16 +48,7 @@ nl
|
|
40
48
|
While the tournament not complete:
|
41
49
|
If X is in and Y is in and X != Y then:
|
42
50
|
(note: fight!)
|
43
|
-
either (X
|
44
|
-
if A won and B lost then:
|
45
|
-
if:
|
46
|
-
- ^A uses "hands" then ""A" has beaten "B". ";
|
47
|
-
- ^A uses "feet" then ""A" has kicked "B". ";
|
48
|
-
- ^A uses "hooves" then ""A" has kicked "B" and knocked him out. ";
|
49
|
-
- ^A uses "claws" then ""A" has scratched the whole "B". ";
|
50
|
-
A not won; B not lost;
|
51
|
-
B is not in;
|
52
|
-
.
|
51
|
+
either (X beats Y) or (Y beats X);
|
53
52
|
.
|
54
53
|
Otherwise the tournament complete;
|
55
54
|
.
|
@@ -33,6 +33,15 @@ names = UniqueNames.russian_male
|
|
33
33
|
nl;
|
34
34
|
.
|
35
35
|
|
36
|
+
Когда A победил B:
|
37
|
+
если:
|
38
|
+
- ^A использует "руки", то ""A" избил "B". ";
|
39
|
+
- ^A использует "ноги", то ""A" запинал "B". ";
|
40
|
+
- ^A использует "копыта", то ""A" лягнул "B" и вырубил его. ";
|
41
|
+
- ^A использует "когти", то ""A" исцарапал всего "B". ";
|
42
|
+
B не участвует в турнире;
|
43
|
+
.
|
44
|
+
|
36
45
|
nl
|
37
46
|
"Да начнется турнир!" nl
|
38
47
|
nl
|
@@ -40,19 +49,10 @@ nl
|
|
40
49
|
Пока не конец турнира:
|
41
50
|
Если X участвует в турнире и Y участвует в турнире и X != Y, то:
|
42
51
|
(note: бой!)
|
43
|
-
либо (X
|
44
|
-
если A победил и B проиграл, то:
|
45
|
-
если:
|
46
|
-
- ^A использует "руки", то ""A" избил "B". ";
|
47
|
-
- ^A использует "ноги", то ""A" запинал "B". ";
|
48
|
-
- ^A использует "копыта", то ""A" лягнул "B" и вырубил его. ";
|
49
|
-
- ^A использует "когти", то ""A" исцарапал всего "B". ";
|
50
|
-
A не победил; B не проиграл;
|
51
|
-
B не участвует в турнире;
|
52
|
-
.
|
52
|
+
либо (X победил Y), либо (Y победил X);
|
53
53
|
.
|
54
54
|
Иначе конец турнира;
|
55
55
|
.
|
56
56
|
Если X участвует в турнире, то ""X" - победитель!"
|
57
57
|
nl
|
58
|
-
nl
|
58
|
+
nl
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: story-gen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parse-framework
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: ffaker
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
description: Generate stories from descriptions based on Facts!
|
31
47
|
email: various.furriness@gmail.com
|
32
48
|
executables:
|