madderlib 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|