madderlib 0.1.0
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/CHANGELOG +3 -0
- data/LICENSE +22 -0
- data/README.rdoc +173 -0
- data/Rakefile +134 -0
- data/lib/madderlib.rb +27 -0
- data/lib/madderlib/builder.rb +659 -0
- data/lib/madderlib/conditional/allowed.rb +144 -0
- data/lib/madderlib/conditional/helper.rb +135 -0
- data/lib/madderlib/conditional/likely.rb +162 -0
- data/lib/madderlib/conditional/recur.rb +103 -0
- data/lib/madderlib/conditional/registry.rb +56 -0
- data/lib/madderlib/conditional/repeat.rb +130 -0
- data/lib/madderlib/context.rb +140 -0
- data/lib/madderlib/core.rb +217 -0
- data/lib/madderlib/extensions.rb +40 -0
- data/lib/madderlib/instruction.rb +171 -0
- data/lib/madderlib/phrase.rb +284 -0
- data/lib/madderlib/sequencer.rb +337 -0
- data/madderlib.gemspec +72 -0
- data/spec/benchmark_spec.rb +69 -0
- data/spec/builder_spec.rb +321 -0
- data/spec/builder_to_other_spec.rb +47 -0
- data/spec/builder_to_sequencer_spec.rb +388 -0
- data/spec/conditional_allowed_spec.rb +130 -0
- data/spec/conditional_helper_spec.rb +131 -0
- data/spec/conditional_likely_spec.rb +138 -0
- data/spec/conditional_recur_spec.rb +102 -0
- data/spec/conditional_registry_spec.rb +94 -0
- data/spec/conditional_repeat_spec.rb +88 -0
- data/spec/doc_spec.rb +550 -0
- data/spec/error_spec.rb +33 -0
- data/spec/examples_spec.rb +151 -0
- data/spec/extensions_spec.rb +47 -0
- data/spec/grammar_spec.rb +101 -0
- data/spec/instruction_spec.rb +133 -0
- data/spec/kernel_spec.rb +58 -0
- data/spec/phrase_spec.rb +7 -0
- data/spec/sequencer_spec.rb +317 -0
- data/spec/spec_helper.rb +54 -0
- metadata +98 -0
data/spec/kernel_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe MadderLib::KernelMethods do
|
6
|
+
after(:each) do
|
7
|
+
# complete the current grammar
|
8
|
+
# so that the next test isn't so limited
|
9
|
+
madderlib_grammar.complete
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
it "madderlib requires a block" do
|
14
|
+
end
|
15
|
+
|
16
|
+
it "provides access to a Builder" do
|
17
|
+
# empty
|
18
|
+
builder = madderlib { }
|
19
|
+
|
20
|
+
builder.should_not be_nil
|
21
|
+
builder.id.should be_nil
|
22
|
+
builder.should be_a(MadderLib::Builder)
|
23
|
+
builder.phrases.should have(0).phrases
|
24
|
+
|
25
|
+
# id only
|
26
|
+
builder = madderlib(:id) { }
|
27
|
+
|
28
|
+
builder.should_not be_nil
|
29
|
+
builder.id.should equal(:id)
|
30
|
+
builder.should be_a(MadderLib::Builder)
|
31
|
+
builder.phrases.should have(0).phrases
|
32
|
+
end
|
33
|
+
|
34
|
+
it "provides a new Builder each time" do
|
35
|
+
builder = madderlib { }
|
36
|
+
madderlib { }.should_not equal(builder)
|
37
|
+
|
38
|
+
|
39
|
+
it "provides access to a Grammar" do
|
40
|
+
grammar = madderlib_grammar
|
41
|
+
|
42
|
+
# empty
|
43
|
+
grammar.should_not be_nil
|
44
|
+
grammar.should be_a(MadderLib::Grammar)
|
45
|
+
grammar.should have(0).builders
|
46
|
+
grammar.builder_map.should have(0).builders
|
47
|
+
end
|
48
|
+
|
49
|
+
it "provides the same Grammar, until completed" do
|
50
|
+
# same
|
51
|
+
grammar = madderlib_grammar
|
52
|
+
madderlib_grammar.should equal(grammar)
|
53
|
+
|
54
|
+
# different
|
55
|
+
grammar.complete
|
56
|
+
madderlib_grammar.should_not equal(grammar)
|
57
|
+
end
|
58
|
+
end
|
data/spec/phrase_spec.rb
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe MadderLib::Sequencer do
|
6
|
+
|
7
|
+
it "handles a single say" do
|
8
|
+
sequencer = (madderlib :single_say do
|
9
|
+
say :hello
|
10
|
+
end).to_sequencer
|
11
|
+
|
12
|
+
sequencer.words.should eql(%w{ hello })
|
13
|
+
end
|
14
|
+
|
15
|
+
it "handles multiple says" do
|
16
|
+
sequencer = (madderlib :multiple_say do
|
17
|
+
# all in sequence
|
18
|
+
# multiple words per phrase
|
19
|
+
# a few syntactical varieties
|
20
|
+
say :cover, :contents
|
21
|
+
and_then.say :beginning
|
22
|
+
says :middle
|
23
|
+
also.says :end
|
24
|
+
end).to_sequencer
|
25
|
+
|
26
|
+
sequencer.words.should eql(%w{
|
27
|
+
cover contents beginning middle end
|
28
|
+
})
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
it "handles flat before sequencing" do
|
34
|
+
# one instance, single word
|
35
|
+
sequencer = (madderlib :flat_single_before do
|
36
|
+
a(:ref).says :ref
|
37
|
+
before(:ref).say :before
|
38
|
+
end).to_sequencer
|
39
|
+
|
40
|
+
sequencer.words.should eql(%w{ before ref })
|
41
|
+
|
42
|
+
# multiple instances, multiple words
|
43
|
+
sequencer = (madderlib :flat_multiple_before do
|
44
|
+
before(:ref).say :b, :c
|
45
|
+
a(:ref).says(:ref)
|
46
|
+
before(:ref).say :a
|
47
|
+
end).to_sequencer
|
48
|
+
|
49
|
+
sequencer.words.should eql(%w{ a b c ref })
|
50
|
+
end
|
51
|
+
|
52
|
+
it "handles flat after sequencing" do
|
53
|
+
# one instance, single word
|
54
|
+
sequencer = (madderlib :flat_single_after do
|
55
|
+
a(:ref).says :ref
|
56
|
+
after(:ref).say :after
|
57
|
+
end).to_sequencer
|
58
|
+
|
59
|
+
sequencer.words.should eql(%w{ ref after })
|
60
|
+
|
61
|
+
# multiple instances, multiple words
|
62
|
+
sequencer = (madderlib :flat_multiple_after do
|
63
|
+
after(:ref).say :x, :y
|
64
|
+
a(:ref).says(:ref)
|
65
|
+
after(:ref).say :z
|
66
|
+
end).to_sequencer
|
67
|
+
|
68
|
+
sequencer.words.should eql(%w{ ref x y z })
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
it "handles nested before sequencing" do
|
74
|
+
# one instance, single word
|
75
|
+
sequencer = (madderlib :nested_single_before do
|
76
|
+
a(:ref).says :ref
|
77
|
+
before(:ref, :inner).say :inner
|
78
|
+
before(:inner).say :outer
|
79
|
+
end).to_sequencer
|
80
|
+
|
81
|
+
sequencer.words.should eql(%w{ outer inner ref })
|
82
|
+
|
83
|
+
# multiple instances, multiple words
|
84
|
+
sequencer = (madderlib :nested_multiple_before do
|
85
|
+
# visually:
|
86
|
+
# [ :a [ :b [:c :d ] :e ] :f :ref ]
|
87
|
+
before(:ref).say :f
|
88
|
+
before(:ref, :inner_e).say :e1, :e2
|
89
|
+
before(:inner_e, :outer_d).say :d
|
90
|
+
a(:ref).says(:ref)
|
91
|
+
before(:outer_d).say :c
|
92
|
+
before(:inner_e).say :b1, :b2
|
93
|
+
before(:ref).say :a
|
94
|
+
end).to_sequencer
|
95
|
+
|
96
|
+
sequencer.words.should eql(%w{ a b1 b2 c d e1 e2 f ref })
|
97
|
+
end
|
98
|
+
|
99
|
+
it "handles nested after sequencing" do
|
100
|
+
# one instance, single word
|
101
|
+
sequencer = (madderlib :nested_single_before do
|
102
|
+
a(:ref).says :ref
|
103
|
+
after(:inner).say :outer
|
104
|
+
after(:ref, :inner).say :inner
|
105
|
+
end).to_sequencer
|
106
|
+
|
107
|
+
sequencer.words.should eql(%w{ ref inner outer })
|
108
|
+
|
109
|
+
# multiple instances, multiple words
|
110
|
+
sequencer = (madderlib :nested_multiple_before do
|
111
|
+
# visually:
|
112
|
+
# [ :ref :u [ :v [ :w :x ] :y ] :z ]
|
113
|
+
after(:ref).say :u
|
114
|
+
after(:ref, :inner_v).say :v1, :v2
|
115
|
+
after(:inner_v, :outer_w).say :w
|
116
|
+
a(:ref).says(:ref)
|
117
|
+
after(:outer_w).say :x
|
118
|
+
after(:inner_v).say :y1, :y2
|
119
|
+
after(:ref).say :z
|
120
|
+
end).to_sequencer
|
121
|
+
|
122
|
+
sequencer.words.should eql(%w{ ref u v1 v2 w x y1 y2 z })
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
it "handles complex nested sequencing" do
|
128
|
+
sequencer = (madderlib :nested_complex do
|
129
|
+
# visually:
|
130
|
+
# [ :a [ [ :b :c [ :d :e ] ] :f [ :g :h ] :i ] :ref [ :r [ :s :t ] :u [ [ :v :w ] :x :y ] ] :z ]
|
131
|
+
# as if that helps
|
132
|
+
# yes, it's palindromic around :ref
|
133
|
+
before(:c).say :b
|
134
|
+
before(:f, :c).say :c
|
135
|
+
after(:c, :d).say :d
|
136
|
+
after(:d).say :e
|
137
|
+
before(:ref, :f).say :f
|
138
|
+
before(:h).say :g
|
139
|
+
after(:f, :h).say :h
|
140
|
+
# dupl after
|
141
|
+
after(:f).say :i
|
142
|
+
# dupl before
|
143
|
+
before(:ref).say :a
|
144
|
+
|
145
|
+
a(:ref).says(:ref)
|
146
|
+
|
147
|
+
after(:x).say :y
|
148
|
+
after(:u, :x).say :x
|
149
|
+
before(:x, :w).say :w
|
150
|
+
before(:w).say :v
|
151
|
+
after(:ref, :u).say :u
|
152
|
+
before(:u, :t).say :t
|
153
|
+
before(:t).say :s
|
154
|
+
# dupl before
|
155
|
+
before(:u).say :r
|
156
|
+
# dupl after
|
157
|
+
after(:ref).say :z
|
158
|
+
end).to_sequencer
|
159
|
+
|
160
|
+
sequencer.words.should eql(%w{
|
161
|
+
a b c d e f g h i
|
162
|
+
ref
|
163
|
+
r s t u v w x y z
|
164
|
+
})
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
it "handles anytimes, without anything else" do
|
170
|
+
sequencer = (madderlib :empty_anytimes do
|
171
|
+
anytime.say :anything
|
172
|
+
end).to_sequencer
|
173
|
+
|
174
|
+
sequencer.words.should eql(%w{ anything })
|
175
|
+
end
|
176
|
+
|
177
|
+
it "handles simple anytimes" do
|
178
|
+
# will always occur at the end (no other option)
|
179
|
+
sequencer = (madderlib :single_anytimes do
|
180
|
+
say :something
|
181
|
+
anytime.say :anything
|
182
|
+
end).to_sequencer
|
183
|
+
|
184
|
+
sequencer.words.should eql(%w{ something anything })
|
185
|
+
|
186
|
+
# only one place to go
|
187
|
+
# because it won't start or end the sequence
|
188
|
+
builder = madderlib :multiple_anytimes do
|
189
|
+
say :one
|
190
|
+
say :two
|
191
|
+
anytime.say :gotcha
|
192
|
+
end
|
193
|
+
|
194
|
+
pound_on do
|
195
|
+
items = builder.words
|
196
|
+
items.should eql(%w{ one gotcha two })
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "handles after-positional anytimes" do
|
201
|
+
# nowhere to go
|
202
|
+
# but will NOT end the sequence
|
203
|
+
builder = madderlib :blocked_after_anytimes do
|
204
|
+
say :one
|
205
|
+
a(:lower).says :two
|
206
|
+
anytime.after(:lower).say :gotcha
|
207
|
+
end
|
208
|
+
|
209
|
+
pound_on do
|
210
|
+
items = builder.words
|
211
|
+
items.should eql(%w{ one two })
|
212
|
+
end
|
213
|
+
|
214
|
+
# only one place
|
215
|
+
builder = madderlib :simple_after_anytimes do
|
216
|
+
say :one
|
217
|
+
a(:lower).says :two
|
218
|
+
say :three
|
219
|
+
anytime.after(:lower).say :gotcha
|
220
|
+
end
|
221
|
+
|
222
|
+
pound_on do
|
223
|
+
items = builder.words
|
224
|
+
items.should eql(%w{ one two gotcha three })
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
it "handles before-positional anytimes" do
|
229
|
+
# nowhere to go
|
230
|
+
# because it will NOT start the sequence
|
231
|
+
builder = madderlib :blocked_before_anytimes do
|
232
|
+
an(:upper).says :one
|
233
|
+
say :two
|
234
|
+
anytime.before(:upper).say :gotcha
|
235
|
+
end
|
236
|
+
|
237
|
+
pound_on do
|
238
|
+
items = builder.words
|
239
|
+
items.should eql(%w{ one two })
|
240
|
+
end
|
241
|
+
|
242
|
+
# only one place
|
243
|
+
builder = madderlib :simple_before_anytimes do
|
244
|
+
say :one
|
245
|
+
an(:upper).says :two
|
246
|
+
say :three
|
247
|
+
anytime.before(:upper).say :gotcha
|
248
|
+
end
|
249
|
+
|
250
|
+
pound_on do
|
251
|
+
items = builder.words
|
252
|
+
items.should eql(%w{ one gotcha two three })
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
it "doesn't tolerate invalid bounding conditions" do
|
257
|
+
(lambda do
|
258
|
+
(builder = madderlib :between_exception_anytimes do
|
259
|
+
# before > after ... never works
|
260
|
+
# assume that before and after aren't first or last, respectively
|
261
|
+
# those are tolerated no-op conditions
|
262
|
+
say :one
|
263
|
+
a(:first).says :two
|
264
|
+
a(:second).says :three
|
265
|
+
say :four
|
266
|
+
anytime.between(:second, :first).say :never
|
267
|
+
end).to_sequencer.words
|
268
|
+
end).should raise_error MadderLib::Error
|
269
|
+
end
|
270
|
+
|
271
|
+
it "handles bounded anytimes" do
|
272
|
+
# nowhere to go
|
273
|
+
# this IS a valid (though stupid) bounding condition
|
274
|
+
builder = madderlib :bounded_nowhere_anytimes do
|
275
|
+
a(:phrase).says :one
|
276
|
+
anytime.after(:phrase).before(:phrase).say :never
|
277
|
+
end
|
278
|
+
|
279
|
+
pound_on do
|
280
|
+
items = builder.words
|
281
|
+
items.should eql(%w{ one })
|
282
|
+
end
|
283
|
+
|
284
|
+
# one place only
|
285
|
+
builder = madderlib :bounded_anytimes do
|
286
|
+
say :one
|
287
|
+
a(:lower).says :two
|
288
|
+
an(:upper).says :three
|
289
|
+
say :four
|
290
|
+
anytime.between(:lower, :upper).say :gotcha
|
291
|
+
end
|
292
|
+
|
293
|
+
pound_on do
|
294
|
+
items = builder.words
|
295
|
+
items.should eql(%w{ one two gotcha three four })
|
296
|
+
end
|
297
|
+
|
298
|
+
# a small range
|
299
|
+
builder = madderlib :between_anytimes do
|
300
|
+
a(:lower).says :one
|
301
|
+
say :two
|
302
|
+
an(:upper).says :three
|
303
|
+
anytime.after(:lower).before(:upper).say :gotcha
|
304
|
+
end
|
305
|
+
|
306
|
+
pound_on do
|
307
|
+
items = builder.words
|
308
|
+
|
309
|
+
items.shift.should eql('one')
|
310
|
+
items.pop.should eql('three')
|
311
|
+
|
312
|
+
items.index('gotcha').should_not be_nil
|
313
|
+
items.delete 'gotcha'
|
314
|
+
items.should eql(%w{ two })
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# external
|
2
|
+
%w{ rubygems spec }.each {|lib| require lib }
|
3
|
+
|
4
|
+
# optional
|
5
|
+
require 'ruby-debug' rescue nil
|
6
|
+
|
7
|
+
# our dependencies
|
8
|
+
# loaded after debug is ready
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'madderlib')
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
module Spec::DSL::Main
|
14
|
+
def pound_on(count=100)
|
15
|
+
# that'll be enough
|
16
|
+
count.times { yield }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
module MadderLib
|
23
|
+
class Builder
|
24
|
+
# normally private
|
25
|
+
# oops! reserved names!
|
26
|
+
###attr_reader :ordered, :depends
|
27
|
+
def orderings; @ordered; end
|
28
|
+
def dependencies; @depends; end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Sequencer
|
32
|
+
# normally private
|
33
|
+
attr_reader :steps
|
34
|
+
|
35
|
+
# oops! reserved names!
|
36
|
+
###attr_reader :anytime, :before, :after
|
37
|
+
def anytimes; @anytime; end
|
38
|
+
def befores; @before; end
|
39
|
+
def afters; @after; end
|
40
|
+
|
41
|
+
send :public, :sequence
|
42
|
+
send :public, :traverse
|
43
|
+
end
|
44
|
+
|
45
|
+
class Instruction
|
46
|
+
class << self
|
47
|
+
send :public, :wordify
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class AnytimePhrase
|
52
|
+
attr_reader :repeat_logic
|
53
|
+
end
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: madderlib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Foley
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-14 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: "MadderLib : a Sentence-Building DSL for the easily amused"
|
17
|
+
email: admin@cantremember.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
- CHANGELOG
|
25
|
+
- LICENSE
|
26
|
+
files:
|
27
|
+
- CHANGELOG
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- lib/madderlib.rb
|
32
|
+
- lib/madderlib/builder.rb
|
33
|
+
- lib/madderlib/conditional/allowed.rb
|
34
|
+
- lib/madderlib/conditional/helper.rb
|
35
|
+
- lib/madderlib/conditional/likely.rb
|
36
|
+
- lib/madderlib/conditional/recur.rb
|
37
|
+
- lib/madderlib/conditional/registry.rb
|
38
|
+
- lib/madderlib/conditional/repeat.rb
|
39
|
+
- lib/madderlib/context.rb
|
40
|
+
- lib/madderlib/core.rb
|
41
|
+
- lib/madderlib/extensions.rb
|
42
|
+
- lib/madderlib/instruction.rb
|
43
|
+
- lib/madderlib/phrase.rb
|
44
|
+
- lib/madderlib/sequencer.rb
|
45
|
+
- madderlib.gemspec
|
46
|
+
- spec/benchmark_spec.rb
|
47
|
+
- spec/builder_spec.rb
|
48
|
+
- spec/builder_to_other_spec.rb
|
49
|
+
- spec/builder_to_sequencer_spec.rb
|
50
|
+
- spec/conditional_allowed_spec.rb
|
51
|
+
- spec/conditional_helper_spec.rb
|
52
|
+
- spec/conditional_likely_spec.rb
|
53
|
+
- spec/conditional_recur_spec.rb
|
54
|
+
- spec/conditional_registry_spec.rb
|
55
|
+
- spec/conditional_repeat_spec.rb
|
56
|
+
- spec/doc_spec.rb
|
57
|
+
- spec/error_spec.rb
|
58
|
+
- spec/examples_spec.rb
|
59
|
+
- spec/extensions_spec.rb
|
60
|
+
- spec/grammar_spec.rb
|
61
|
+
- spec/instruction_spec.rb
|
62
|
+
- spec/kernel_spec.rb
|
63
|
+
- spec/phrase_spec.rb
|
64
|
+
- spec/sequencer_spec.rb
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://wiki.cantremember.com/MadderLib
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --line-numbers
|
71
|
+
- --inline-source
|
72
|
+
- --title
|
73
|
+
- MadderLib
|
74
|
+
- --main
|
75
|
+
- README.rdoc
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "1.8"
|
83
|
+
version:
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
version:
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project: madderlib
|
93
|
+
rubygems_version: 1.3.1
|
94
|
+
signing_key:
|
95
|
+
specification_version: 2
|
96
|
+
summary: madderlib 0.1.0
|
97
|
+
test_files: []
|
98
|
+
|