sequitur 0.1.22 → 0.1.24
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -180
- data/CHANGELOG.md +11 -1
- data/LICENSE.txt +1 -1
- data/Rakefile +0 -2
- data/examples/integer_sample.rb +1 -2
- data/examples/porridge.rb +10 -10
- data/examples/simple_case.rb +1 -1
- data/examples/symbol_sample.rb +1 -1
- data/examples/word_sample.rb +5 -6
- data/lib/sequitur/constants.rb +5 -2
- data/lib/sequitur/digram.rb +3 -3
- data/lib/sequitur/dynamic_grammar.rb +4 -5
- data/lib/sequitur/formatter/base_formatter.rb +1 -1
- data/lib/sequitur/formatter/base_text.rb +3 -7
- data/lib/sequitur/formatter/debug.rb +0 -1
- data/lib/sequitur/grammar_visitor.rb +1 -1
- data/lib/sequitur/production.rb +200 -205
- data/lib/sequitur/production_ref.rb +9 -12
- data/lib/sequitur/sequitur_grammar.rb +135 -137
- data/lib/sequitur/symbol_sequence.rb +24 -27
- data/lib/sequitur.rb +4 -5
- data/spec/sequitur/digram_spec.rb +13 -12
- data/spec/sequitur/dynamic_grammar_spec.rb +5 -11
- data/spec/sequitur/formatter/base_text_spec.rb +70 -72
- data/spec/sequitur/formatter/debug_spec.rb +90 -92
- data/spec/sequitur/grammar_visitor_spec.rb +70 -71
- data/spec/sequitur/production_ref_spec.rb +92 -92
- data/spec/sequitur/production_spec.rb +30 -34
- data/spec/sequitur/sequitur_grammar_spec.rb +48 -49
- data/spec/sequitur/symbol_sequence_spec.rb +102 -105
- data/spec/spec_helper.rb +0 -15
- metadata +18 -60
- data/.simplecov +0 -7
- data/.travis.yml +0 -29
|
@@ -7,98 +7,98 @@ require_relative '../../lib/sequitur/production'
|
|
|
7
7
|
require_relative '../../lib/sequitur/production_ref'
|
|
8
8
|
|
|
9
9
|
module Sequitur # Re-open the module to get rid of qualified names
|
|
10
|
-
describe ProductionRef do
|
|
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
|
-
end # describe
|
|
10
|
+
describe ProductionRef do
|
|
11
|
+
let(:target) { Production.new }
|
|
12
|
+
let(:another_target) { Production.new }
|
|
13
|
+
|
|
14
|
+
subject { ProductionRef.new(target) }
|
|
15
|
+
|
|
16
|
+
context 'Creation & initialization:' do
|
|
17
|
+
it 'should be created with a production argument' do
|
|
18
|
+
expect { ProductionRef.new(target) }.not_to raise_error
|
|
19
|
+
expect(target.refcount).to eq(1)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should clone with reference count incrementing' do
|
|
23
|
+
expect(target.refcount).to eq(0)
|
|
24
|
+
expect(subject.production.refcount).to eq(1)
|
|
25
|
+
klone = subject.clone
|
|
26
|
+
expect(klone.production.refcount).to eq(2)
|
|
27
|
+
duplicate = subject.dup
|
|
28
|
+
expect(duplicate.production.refcount).to eq(3)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should know its referenced production' do
|
|
32
|
+
instance = ProductionRef.new(target)
|
|
33
|
+
expect(instance.production).to eq(target)
|
|
34
|
+
end
|
|
35
|
+
end # context
|
|
36
|
+
|
|
37
|
+
context 'Provided services:' do
|
|
38
|
+
it 'should render its referenced production' do
|
|
39
|
+
expect(subject.to_s).to eq(target.object_id.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should unbind itself from its production' do
|
|
43
|
+
expect(target.refcount).to eq(0)
|
|
44
|
+
expect(subject).not_to be_unbound
|
|
45
|
+
expect(target.refcount).to eq(1)
|
|
46
|
+
subject.unbind
|
|
47
|
+
expect(target.refcount).to eq(0)
|
|
48
|
+
expect(subject.production).to be_nil
|
|
49
|
+
expect(subject).to be_unbound
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should bind to a production' do
|
|
53
|
+
expect(target.refcount).to eq(0)
|
|
54
|
+
|
|
55
|
+
expect(subject).not_to be_unbound
|
|
56
|
+
expect(target.refcount).to eq(1)
|
|
57
|
+
|
|
58
|
+
# Case: bind again to same production
|
|
59
|
+
expect { subject.bind_to(target) }.not_to raise_error
|
|
60
|
+
expect(target.refcount).to eq(1)
|
|
61
|
+
|
|
62
|
+
# Case: bind to another production
|
|
63
|
+
expect(another_target.refcount).to eq(0)
|
|
64
|
+
subject.bind_to(another_target)
|
|
65
|
+
expect(target.refcount).to eq(0)
|
|
66
|
+
expect(another_target.refcount).to eq(1)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'should complain when binding to something else than production' do
|
|
70
|
+
subject.bind_to(target)
|
|
71
|
+
msg = 'Illegal production type String'
|
|
72
|
+
expect { subject.bind_to('WRONG') }.to raise_error(StandardError, msg)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'should compare to other production (reference)' do
|
|
76
|
+
same = ProductionRef.new(target)
|
|
77
|
+
expect(subject).to eq(subject) # Strict identity
|
|
78
|
+
expect(subject).to eq(same) # 2 references pointing to same production
|
|
79
|
+
expect(subject).to eq(target)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'should return the hash value of its production' do
|
|
83
|
+
expectation = target.hash
|
|
84
|
+
expect(subject.hash).to eq(expectation)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'should complain when requested for a hash and unbound' do
|
|
88
|
+
subject.unbind
|
|
89
|
+
expect { subject.hash }.to raise_error(StandardError)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should accept a visitor' do
|
|
93
|
+
# Use a mock visitor
|
|
94
|
+
fake = double('fake_visitor')
|
|
95
|
+
|
|
96
|
+
# Visitor should receive a visit message
|
|
97
|
+
expect(fake).to receive(:visit_prod_ref).once
|
|
98
|
+
expect { subject.accept(fake) }.not_to raise_error
|
|
99
|
+
end
|
|
100
|
+
end # context
|
|
101
|
+
end # describe
|
|
102
102
|
end # module
|
|
103
103
|
|
|
104
104
|
# End of file
|
|
@@ -5,22 +5,26 @@ require_relative '../spec_helper'
|
|
|
5
5
|
# Load the class under test
|
|
6
6
|
require_relative '../../lib/sequitur/production'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
describe Sequitur::Production do
|
|
9
|
+
# Factory method. Returns a Sequitur::Production
|
|
10
|
+
def make_production
|
|
11
|
+
Sequitur::Production.new
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
# Helper method: convert list of digrams into an array
|
|
11
15
|
# of symbol couples.
|
|
12
|
-
def to_symbols(
|
|
13
|
-
|
|
16
|
+
def to_symbols(digrams)
|
|
17
|
+
digrams.map(&:symbols)
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
let(:p_a) do
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
instance = make_production
|
|
22
|
+
instance.append_symbol(:a)
|
|
23
|
+
instance
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
let(:p_bc) do
|
|
23
|
-
instance =
|
|
27
|
+
instance = make_production
|
|
24
28
|
instance.append_symbol('b')
|
|
25
29
|
instance.append_symbol('c')
|
|
26
30
|
instance
|
|
@@ -28,7 +32,7 @@ describe Production do
|
|
|
28
32
|
|
|
29
33
|
context 'Creation & initialization:' do
|
|
30
34
|
it 'should be created without argument' do
|
|
31
|
-
expect {
|
|
35
|
+
expect { make_production }.not_to raise_error
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
it 'should not referenced yet' do
|
|
@@ -52,11 +56,11 @@ describe Production do
|
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
it 'should compare to a production reference' do
|
|
55
|
-
ref_a = ProductionRef.new(p_a)
|
|
59
|
+
ref_a = Sequitur::ProductionRef.new(p_a)
|
|
56
60
|
expect(p_a).to eq(ref_a)
|
|
57
61
|
expect(p_bc).not_to eq(ref_a)
|
|
58
62
|
|
|
59
|
-
ref_bc = ProductionRef.new(p_bc)
|
|
63
|
+
ref_bc = Sequitur::ProductionRef.new(p_bc)
|
|
60
64
|
expect(p_a).not_to eq(ref_bc)
|
|
61
65
|
expect(p_bc).to eq(ref_bc)
|
|
62
66
|
end
|
|
@@ -78,13 +82,11 @@ describe Production do
|
|
|
78
82
|
expect(subject.references).to eq([p_a])
|
|
79
83
|
expect(subject.references_of(p_a).map(&:production)).to eq([p_a])
|
|
80
84
|
|
|
81
|
-
|
|
82
85
|
# Case 3: production with repeated references
|
|
83
86
|
subject.append_symbol(p_a) # second time
|
|
84
87
|
expect(subject.references).to eq([p_a, p_a])
|
|
85
88
|
expect(subject.references_of(p_a).map(&:production)).to eq([p_a, p_a])
|
|
86
89
|
|
|
87
|
-
|
|
88
90
|
# Case 4: production with multiple distinct references
|
|
89
91
|
subject.append_symbol(p_bc)
|
|
90
92
|
expect(subject.references).to eq([p_a, p_a, p_bc])
|
|
@@ -138,7 +140,7 @@ describe Production do
|
|
|
138
140
|
|
|
139
141
|
it 'should append a production ref in its rhs' do
|
|
140
142
|
# Side-effect: refcount of production to append is incremented
|
|
141
|
-
ref_a = ProductionRef.new(p_a)
|
|
143
|
+
ref_a = Sequitur::ProductionRef.new(p_a)
|
|
142
144
|
expect(p_a.refcount).to be(1)
|
|
143
145
|
|
|
144
146
|
input = [ref_a, :b, :c, :d, ref_a] # ref_a appears twice
|
|
@@ -157,7 +159,7 @@ describe Production do
|
|
|
157
159
|
|
|
158
160
|
it 'should complain when appending ref to nil production' do
|
|
159
161
|
# Side-effect: refcount of production to append is incremented
|
|
160
|
-
ref_a = ProductionRef.new(p_a)
|
|
162
|
+
ref_a = Sequitur::ProductionRef.new(p_a)
|
|
161
163
|
expect(p_a.refcount).to be(1)
|
|
162
164
|
|
|
163
165
|
# Unbind the reference
|
|
@@ -167,7 +169,6 @@ describe Production do
|
|
|
167
169
|
end
|
|
168
170
|
end # context
|
|
169
171
|
|
|
170
|
-
|
|
171
172
|
context 'Text representation of a production rule:' do
|
|
172
173
|
it 'should emit minimal text when empty' do
|
|
173
174
|
expectation = "#{subject.object_id} : ."
|
|
@@ -175,7 +176,7 @@ describe Production do
|
|
|
175
176
|
end
|
|
176
177
|
|
|
177
178
|
it 'should emit its text representation' do
|
|
178
|
-
instance =
|
|
179
|
+
instance = make_production
|
|
179
180
|
symbols = [:a, :b, 'c', :d, :e, 1000, instance]
|
|
180
181
|
symbols.each { |symb| subject.append_symbol(symb) }
|
|
181
182
|
expectation = +"#{subject.object_id} : "
|
|
@@ -204,17 +205,17 @@ describe Production do
|
|
|
204
205
|
|
|
205
206
|
it 'should detect any repetition pattern' do
|
|
206
207
|
# Positive cases
|
|
207
|
-
cases = %w
|
|
208
|
+
cases = %w[abab abcdab abcdcd abcdefcd]
|
|
208
209
|
cases.each do |word|
|
|
209
|
-
instance =
|
|
210
|
+
instance = make_production
|
|
210
211
|
word.each_char { |symb| instance.append_symbol(symb) }
|
|
211
212
|
expect(instance.repeated_digram?).to be_truthy
|
|
212
213
|
end
|
|
213
214
|
|
|
214
215
|
# Negative cases
|
|
215
|
-
cases = %w
|
|
216
|
+
cases = %w[abc abb abba abcdef]
|
|
216
217
|
cases.each do |word|
|
|
217
|
-
instance =
|
|
218
|
+
instance = make_production
|
|
218
219
|
word.each_char { |symb| instance.append_symbol(symb) }
|
|
219
220
|
expect(instance.repeated_digram?).to be_falsey
|
|
220
221
|
end
|
|
@@ -228,9 +229,8 @@ describe Production do
|
|
|
228
229
|
expect(p_bc.refcount).to eq(0)
|
|
229
230
|
end
|
|
230
231
|
|
|
231
|
-
|
|
232
232
|
it 'should replace two-symbol sequence' do
|
|
233
|
-
%w
|
|
233
|
+
%w[a b c d e b c e].each { |symb| subject.append_symbol(symb) }
|
|
234
234
|
p_bc_before = p_bc.to_string
|
|
235
235
|
subject.reduce_step(p_bc)
|
|
236
236
|
|
|
@@ -240,9 +240,8 @@ describe Production do
|
|
|
240
240
|
expect(p_bc.to_string).to eq(p_bc_before)
|
|
241
241
|
end
|
|
242
242
|
|
|
243
|
-
|
|
244
243
|
it 'should replace a starting two-symbol sequence' do
|
|
245
|
-
%w
|
|
244
|
+
%w[b c d e b c e].each { |symb| subject.append_symbol(symb) }
|
|
246
245
|
subject.reduce_step(p_bc)
|
|
247
246
|
|
|
248
247
|
expect(subject.rhs.size).to eq(5)
|
|
@@ -250,9 +249,8 @@ describe Production do
|
|
|
250
249
|
expect(p_bc.refcount).to eq(2)
|
|
251
250
|
end
|
|
252
251
|
|
|
253
|
-
|
|
254
252
|
it 'should replace an ending two-symbol sequence' do
|
|
255
|
-
%w
|
|
253
|
+
%w[a b c d e b c].each { |symb| subject.append_symbol(symb) }
|
|
256
254
|
subject.reduce_step(p_bc)
|
|
257
255
|
|
|
258
256
|
expect(subject.rhs.size).to eq(5)
|
|
@@ -261,7 +259,7 @@ describe Production do
|
|
|
261
259
|
end
|
|
262
260
|
|
|
263
261
|
it 'should replace two consecutive two-symbol sequences' do
|
|
264
|
-
%w
|
|
262
|
+
%w[a b c b c d].each { |symb| subject.append_symbol(symb) }
|
|
265
263
|
subject.reduce_step(p_bc)
|
|
266
264
|
|
|
267
265
|
expect(subject.rhs.size).to eq(4)
|
|
@@ -282,18 +280,17 @@ describe Production do
|
|
|
282
280
|
|
|
283
281
|
subject.derive_step(p_bc)
|
|
284
282
|
expect(subject.rhs.size).to eq(3)
|
|
285
|
-
expect(subject.rhs).to eq(%w
|
|
283
|
+
expect(subject.rhs).to eq(%w[b c d])
|
|
286
284
|
expect(p_bc.refcount).to eq(0)
|
|
287
285
|
end
|
|
288
286
|
|
|
289
|
-
|
|
290
287
|
it 'should replace a production at the end' do
|
|
291
288
|
['d', p_bc].each { |symb| subject.append_symbol(symb) }
|
|
292
289
|
expect(p_bc.refcount).to eq(1)
|
|
293
290
|
subject.derive_step(p_bc)
|
|
294
291
|
|
|
295
292
|
expect(subject.rhs.size).to eq(3)
|
|
296
|
-
expect(subject.rhs).to eq(%w
|
|
293
|
+
expect(subject.rhs).to eq(%w[d b c])
|
|
297
294
|
expect(p_bc.refcount).to eq(0)
|
|
298
295
|
end
|
|
299
296
|
|
|
@@ -302,7 +299,7 @@ describe Production do
|
|
|
302
299
|
subject.derive_step(p_bc)
|
|
303
300
|
|
|
304
301
|
expect(subject.rhs.size).to eq(2)
|
|
305
|
-
expect(subject.rhs).to eq(%w
|
|
302
|
+
expect(subject.rhs).to eq(%w[b c])
|
|
306
303
|
end
|
|
307
304
|
|
|
308
305
|
it 'should replace a production in the middle' do
|
|
@@ -310,7 +307,7 @@ describe Production do
|
|
|
310
307
|
subject.derive_step(p_bc)
|
|
311
308
|
|
|
312
309
|
expect(subject.rhs.size).to eq(4)
|
|
313
|
-
expect(subject.rhs).to eq(%w
|
|
310
|
+
expect(subject.rhs).to eq(%w[a b c d])
|
|
314
311
|
end
|
|
315
312
|
end # context
|
|
316
313
|
|
|
@@ -358,6 +355,5 @@ describe Production do
|
|
|
358
355
|
end
|
|
359
356
|
end # context
|
|
360
357
|
end # describe
|
|
361
|
-
end # module
|
|
362
358
|
|
|
363
359
|
# End of file
|
|
@@ -5,20 +5,24 @@ require_relative '../spec_helper'
|
|
|
5
5
|
# Load the class under test
|
|
6
6
|
require_relative '../../lib/sequitur/sequitur_grammar'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
describe Sequitur::SequiturGrammar do
|
|
9
|
+
# Factory method. Returns a SequiturGrammar
|
|
10
|
+
def sequitur_grammar(enumerator)
|
|
11
|
+
Sequitur::SequiturGrammar.new(enumerator)
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
# Factory method. Returns an empty enumerator (
|
|
11
15
|
# i.e. without elements to iterate)
|
|
12
16
|
def empty_enum
|
|
13
|
-
|
|
17
|
+
[].to_enum
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
context 'Creation from an enumeration of tokens:' do
|
|
17
21
|
it 'could be created with an empty enumerator' do
|
|
18
|
-
expect {
|
|
22
|
+
expect { sequitur_grammar(empty_enum) }.not_to raise_error
|
|
19
23
|
|
|
20
24
|
# Creation
|
|
21
|
-
instance =
|
|
25
|
+
instance = sequitur_grammar(empty_enum)
|
|
22
26
|
|
|
23
27
|
# Initialization
|
|
24
28
|
expect(instance.productions.size).to eq(1)
|
|
@@ -28,7 +32,7 @@ describe SequiturGrammar do
|
|
|
28
32
|
|
|
29
33
|
it 'could be created with single token' do
|
|
30
34
|
# Creation
|
|
31
|
-
instance =
|
|
35
|
+
instance = sequitur_grammar([:a].to_enum)
|
|
32
36
|
|
|
33
37
|
# Initialization
|
|
34
38
|
expect(instance.productions.size).to eq(1)
|
|
@@ -38,7 +42,7 @@ describe SequiturGrammar do
|
|
|
38
42
|
|
|
39
43
|
it 'could be created with multiple unique tokens' do
|
|
40
44
|
# Creation
|
|
41
|
-
instance =
|
|
45
|
+
instance = sequitur_grammar(%i[a b c d].to_enum)
|
|
42
46
|
|
|
43
47
|
# Initialization
|
|
44
48
|
expect(instance.productions.size).to eq(1)
|
|
@@ -47,7 +51,7 @@ describe SequiturGrammar do
|
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
it 'could be created with a repeating digram' do
|
|
50
|
-
instance =
|
|
54
|
+
instance = sequitur_grammar(%i[a b a b].to_enum)
|
|
51
55
|
|
|
52
56
|
# Expectations:
|
|
53
57
|
# S : A A.
|
|
@@ -59,7 +63,7 @@ describe SequiturGrammar do
|
|
|
59
63
|
end
|
|
60
64
|
|
|
61
65
|
it 'should enforce the utility rule' do
|
|
62
|
-
instance =
|
|
66
|
+
instance = sequitur_grammar(%i[a b c a b c].to_enum)
|
|
63
67
|
|
|
64
68
|
# Expectations without utility rule:
|
|
65
69
|
# S : B B.
|
|
@@ -79,15 +83,14 @@ describe SequiturGrammar do
|
|
|
79
83
|
input = 'aaac' # This sequence raised an exception
|
|
80
84
|
|
|
81
85
|
# Creation
|
|
82
|
-
expect {
|
|
86
|
+
expect { sequitur_grammar(input.chars) }.not_to raise_error
|
|
83
87
|
end
|
|
84
88
|
|
|
85
|
-
|
|
86
89
|
it 'should cope with the example from presentation' do
|
|
87
90
|
input = 'bbebeebebebbebee'
|
|
88
91
|
|
|
89
92
|
# Creation
|
|
90
|
-
instance =
|
|
93
|
+
instance = sequitur_grammar(input.chars)
|
|
91
94
|
|
|
92
95
|
# Expectations:
|
|
93
96
|
# S: P3 P2 P3
|
|
@@ -97,7 +100,7 @@ describe SequiturGrammar do
|
|
|
97
100
|
expect(instance.productions.size).to eq(4)
|
|
98
101
|
(p1, p2, p3) = instance.productions[1..3]
|
|
99
102
|
expect(instance.start.rhs).to eq([p3, p2, p3])
|
|
100
|
-
expect(p1.rhs).to eq(%w
|
|
103
|
+
expect(p1.rhs).to eq(%w[b e])
|
|
101
104
|
expect(p2.rhs).to eq([p1, p1])
|
|
102
105
|
expect(p3.rhs).to eq(['b', p2, 'e'])
|
|
103
106
|
end
|
|
@@ -107,12 +110,10 @@ describe SequiturGrammar do
|
|
|
107
110
|
raw_input = 'bbebeebebebbebee'
|
|
108
111
|
|
|
109
112
|
# Convert them into multichar strings
|
|
110
|
-
input = raw_input.chars.map
|
|
111
|
-
'letter_' + ch
|
|
112
|
-
end
|
|
113
|
+
input = raw_input.chars.map { |ch| "letter_#{ch}" }
|
|
113
114
|
|
|
114
115
|
# Creation
|
|
115
|
-
instance =
|
|
116
|
+
instance = sequitur_grammar(input.to_enum)
|
|
116
117
|
|
|
117
118
|
# Expectations:
|
|
118
119
|
# S: P3 P2 P3
|
|
@@ -122,7 +123,7 @@ describe SequiturGrammar do
|
|
|
122
123
|
expect(instance.productions.size).to eq(4)
|
|
123
124
|
(p1, p2, p3) = instance.productions[1..3]
|
|
124
125
|
expect(instance.start.rhs).to eq([p3, p2, p3])
|
|
125
|
-
expect(p1.rhs).to eq(%w
|
|
126
|
+
expect(p1.rhs).to eq(%w[letter_b letter_e])
|
|
126
127
|
expect(p2.rhs).to eq([p1, p1])
|
|
127
128
|
expect(p3.rhs).to eq(['letter_b', p2, 'letter_e'])
|
|
128
129
|
end
|
|
@@ -135,7 +136,7 @@ describe SequiturGrammar do
|
|
|
135
136
|
input = raw_input.chars.map(&:to_sym)
|
|
136
137
|
|
|
137
138
|
# Creation
|
|
138
|
-
instance =
|
|
139
|
+
instance = sequitur_grammar(input.to_enum)
|
|
139
140
|
|
|
140
141
|
# Expectations:
|
|
141
142
|
# S: P3 P2 P3
|
|
@@ -150,16 +151,15 @@ describe SequiturGrammar do
|
|
|
150
151
|
expect(p3.rhs).to eq([:b, p2, :e])
|
|
151
152
|
end
|
|
152
153
|
|
|
153
|
-
|
|
154
154
|
it 'should work with integer values as input tokens' do
|
|
155
155
|
# Raw input is sequence of hex digits
|
|
156
156
|
raw_input = 'bbebeebebebbebee'
|
|
157
157
|
|
|
158
|
-
# Convert them into
|
|
158
|
+
# Convert them into Integers
|
|
159
159
|
input = raw_input.chars.map { |ch| ch.to_i(16) }
|
|
160
160
|
|
|
161
161
|
# Creation
|
|
162
|
-
instance =
|
|
162
|
+
instance = sequitur_grammar(input.to_enum)
|
|
163
163
|
|
|
164
164
|
# Expectations:
|
|
165
165
|
# S: P3 P2 P3
|
|
@@ -176,7 +176,7 @@ describe SequiturGrammar do
|
|
|
176
176
|
|
|
177
177
|
it 'should cope with the example from sequitur.info website' do
|
|
178
178
|
input = 'abcabdabcabd'
|
|
179
|
-
instance =
|
|
179
|
+
instance = sequitur_grammar(input.chars)
|
|
180
180
|
|
|
181
181
|
# Expectations:
|
|
182
182
|
# 0 → 2 2
|
|
@@ -186,13 +186,13 @@ describe SequiturGrammar do
|
|
|
186
186
|
expect(instance.productions.size).to eq(3)
|
|
187
187
|
(p1, p2) = instance.productions[1..2]
|
|
188
188
|
expect(instance.start.rhs).to eq([p2, p2])
|
|
189
|
-
expect(p1.rhs).to eq(%w
|
|
189
|
+
expect(p1.rhs).to eq(%w[a b])
|
|
190
190
|
expect(p2.rhs).to eq([p1, 'c', p1, 'd'])
|
|
191
191
|
end
|
|
192
192
|
|
|
193
193
|
it "should cope with the example from Salomon's book" do
|
|
194
194
|
input = 'abcdbcabcdbc'
|
|
195
|
-
instance =
|
|
195
|
+
instance = sequitur_grammar(input.chars)
|
|
196
196
|
|
|
197
197
|
# Expectations:
|
|
198
198
|
# S → CC
|
|
@@ -202,23 +202,23 @@ describe SequiturGrammar do
|
|
|
202
202
|
expect(instance.productions.size).to eq(3)
|
|
203
203
|
(p_a, p_c) = instance.productions[1..2]
|
|
204
204
|
expect(instance.start.rhs).to eq([p_c, p_c])
|
|
205
|
-
expect(p_a.rhs).to eq(%w
|
|
205
|
+
expect(p_a.rhs).to eq(%w[b c])
|
|
206
206
|
expect(p_c.rhs).to eq(['a', p_a, 'd', p_a])
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
it 'should cope with the "porridge" example from sequitur.info' do
|
|
210
210
|
# Another example from sequitur.info website
|
|
211
|
-
input =
|
|
212
|
-
pease porridge hot,
|
|
213
|
-
pease porridge cold,
|
|
214
|
-
pease porridge in the pot,
|
|
215
|
-
nine days old.
|
|
216
|
-
|
|
217
|
-
some like it hot,
|
|
218
|
-
some like it cold,
|
|
219
|
-
some like it in the pot,
|
|
220
|
-
nine days old.
|
|
221
|
-
SNIPPET
|
|
211
|
+
input = <<~SNIPPET
|
|
212
|
+
pease porridge hot,
|
|
213
|
+
pease porridge cold,
|
|
214
|
+
pease porridge in the pot,
|
|
215
|
+
nine days old.
|
|
216
|
+
|
|
217
|
+
some like it hot,
|
|
218
|
+
some like it cold,
|
|
219
|
+
some like it in the pot,
|
|
220
|
+
nine days old.
|
|
221
|
+
SNIPPET
|
|
222
222
|
# Expectations (sequitur.org)
|
|
223
223
|
# 0 → 1 2 3 4 3 5 ↵ 6 2 7 4 7 5
|
|
224
224
|
# 1 → p e a s 8 r r i d g 9 pease_porridge_
|
|
@@ -235,7 +235,7 @@ SNIPPET
|
|
|
235
235
|
# 11 → o l d old
|
|
236
236
|
# 12 → i n in
|
|
237
237
|
|
|
238
|
-
instance =
|
|
238
|
+
instance = sequitur_grammar(input.chars)
|
|
239
239
|
expect(instance.productions.size).to eq(13)
|
|
240
240
|
p0 = instance.start
|
|
241
241
|
expect(p0.rhs.size).to eq(13)
|
|
@@ -243,7 +243,7 @@ SNIPPET
|
|
|
243
243
|
(p1, p2, p3, p4, p5, p6, p7, p8, p9) = instance.productions[1..9]
|
|
244
244
|
(p10, p11, p12) = instance.productions[10..12]
|
|
245
245
|
|
|
246
|
-
#
|
|
246
|
+
# NOTE: the productions aren't sorted the same way as
|
|
247
247
|
# the sequitur.info implementation.
|
|
248
248
|
p0_expectation = [
|
|
249
249
|
p2, p8, p3, p10, p3, p12, "\n",
|
|
@@ -251,27 +251,27 @@ SNIPPET
|
|
|
251
251
|
]
|
|
252
252
|
expect(p0.rhs).to eq(p0_expectation) # Rule 0 above
|
|
253
253
|
expect(p1.rhs).to eq(['e', ' ']) # Rule 9 above
|
|
254
|
-
expect(p2.rhs).to eq([%w
|
|
254
|
+
expect(p2.rhs).to eq([%w[p e a s], p4, %w[r r i d g], p1].flatten) # R1
|
|
255
255
|
expect(p3.rhs).to eq([p5, p2]) # Rule 3 above
|
|
256
256
|
expect(p4.rhs).to eq([p1, 'p', 'o']) # Rule 8 above
|
|
257
257
|
expect(p5.rhs).to eq([',', "\n"]) # Rule 10 above
|
|
258
|
-
expect(p6.rhs).to eq(%w
|
|
259
|
-
expect(p7.rhs).to eq(%w
|
|
260
|
-
expect(p8.rhs).to eq(%w
|
|
261
|
-
p9_expectation = [%w
|
|
258
|
+
expect(p6.rhs).to eq(%w[i n]) # Rule 12 above
|
|
259
|
+
expect(p7.rhs).to eq(%w[o l d]) # Rule 11 above
|
|
260
|
+
expect(p8.rhs).to eq(%w[h o t]) # Rule 2 above
|
|
261
|
+
p9_expectation = [%w[s o m], p1, %w[l i k], p1, 'i', 't', ' '].flatten
|
|
262
262
|
expect(p9.rhs).to eq(p9_expectation) # Rule 6 above
|
|
263
263
|
expect(p10.rhs).to eq(['c', p7]) # Rule 4 above
|
|
264
264
|
expect(p11.rhs).to eq([p5, p9]) # Rule 7 above
|
|
265
265
|
p12_expectation = [
|
|
266
266
|
p6, ' ', 't', 'h', p4, 't', p5, 'n', p6, p1,
|
|
267
|
-
%w
|
|
267
|
+
%w[d a y s], ' ', p7, '.', "\n"
|
|
268
268
|
].flatten
|
|
269
269
|
expect(p12.rhs).to eq(p12_expectation) # Rule 5 above
|
|
270
270
|
end
|
|
271
271
|
|
|
272
272
|
it 'should work with a sequence of Ruby Symbols' do
|
|
273
273
|
input = 'abcabdabcabd'.chars.map(&:to_sym)
|
|
274
|
-
instance =
|
|
274
|
+
instance = sequitur_grammar(input.to_enum)
|
|
275
275
|
|
|
276
276
|
# Expectations:
|
|
277
277
|
# start : P2 P2.
|
|
@@ -288,19 +288,18 @@ SNIPPET
|
|
|
288
288
|
|
|
289
289
|
context 'Generating a text representation of itself:' do
|
|
290
290
|
it 'should generate a text representation when empty' do
|
|
291
|
-
instance =
|
|
291
|
+
instance = sequitur_grammar(empty_enum)
|
|
292
292
|
expectation = "#{instance.start.object_id} : ."
|
|
293
293
|
|
|
294
294
|
expect(instance.to_string).to eq(expectation)
|
|
295
295
|
end
|
|
296
296
|
|
|
297
297
|
it 'should generate a text representation of a simple production' do
|
|
298
|
-
instance =
|
|
298
|
+
instance = sequitur_grammar([:a].to_enum)
|
|
299
299
|
expectation = "#{instance.start.object_id} : a."
|
|
300
300
|
expect(instance.to_string).to eq(expectation)
|
|
301
301
|
end
|
|
302
302
|
end # context
|
|
303
303
|
end # describe
|
|
304
|
-
end # module
|
|
305
304
|
|
|
306
305
|
# End of file
|