sequitur 0.1.15 → 0.1.16
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 +6 -14
- data/.ruby-version +1 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -3
- data/lib/sequitur/constants.rb +1 -1
- data/lib/sequitur/sequitur_grammar.rb +1 -1
- data/spec/sequitur/dynamic_grammar_spec.rb +1 -1
- data/spec/sequitur/formatter/base_text_spec.rb +1 -1
- data/spec/sequitur/production_ref_spec.rb +2 -2
- data/spec/sequitur/production_spec.rb +2 -2
- data/spec/sequitur/sequitur_grammar_spec.rb +304 -304
- metadata +56 -41
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
NDI0YzNmOWI4ZTBlZGNjNDkxNmNmNTRhNDJjZDMzMDY4OWE4YmU5YmRjZmJl
|
10
|
-
NzI5MjViMjhhNGYyODkyNGQzNGMyMGFhMjRkNjMyMDBlOTFlN2ZhNzgzYzk1
|
11
|
-
MTgxNjYzYTA4YmFkZWE1ZDlmOTc0MDdkMzJmOGQzMTFiYmEzYWQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
OGI1NWI4NDBlMjhhYzQ3NWUyNDI1MmFkZmI0ZTgzYWRlZWQ1OTZlZWM4Yzg1
|
14
|
-
OTIxMDc4Zjc2NmY1MDExNzQ5OWYyZTkwY2EyZjgwMTczZGFkOGE2YzJkMjAx
|
15
|
-
NGQxMWY2NDBkOTBlNTM1M2I2YWNiNDA1M2U1MjZlMWFjY2RjZTI=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b1af553fad3ecc43dc57cc44e040b01d855caf01
|
4
|
+
data.tar.gz: 541cc47ff348f3886a95bde5eba649c1f1a91913
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db612a6216a109a99a216e2cfaca23feaf20243c121fd404956bc76109f5926e67af4cb26c29f747040f93348768ab2f40e1db3070d096fd96dc687d290a3bf9
|
7
|
+
data.tar.gz: 21ae7581e271eb66e7f8a4578ae451e994670cc138afe341f18722cfbf7cd8625a559748281f2986ce121ba10da2a58438c12f1c04b8db0dd6f3e084e0e2d186
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.2.3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 0.1.16 / 2015-09-05
|
2
|
+
* [CHANGE] Minor. Code re-formatted to please Rubocop 0.34.0
|
3
|
+
* [FIX] File `sequitur.gemspec`: updated gem version in development dependencies
|
4
|
+
|
1
5
|
### 0.1.15 / 2015-06-16
|
2
6
|
* [CHANGE] Code re-formatted to please Rubocop 0.32.0
|
3
7
|
* [FIX] File `.rubocop.yml`: change some cop settings.
|
data/Gemfile
CHANGED
@@ -3,8 +3,9 @@ source 'https://rubygems.org'
|
|
3
3
|
|
4
4
|
|
5
5
|
group :development do
|
6
|
-
gem 'rake',
|
7
|
-
gem 'rspec', '>=
|
8
|
-
gem 'simplecov', '>= 0.
|
6
|
+
gem 'rake', '>= 10.0.0'
|
7
|
+
gem 'rspec', '>= 2.1.0'
|
8
|
+
gem 'simplecov', '>= 0.8.0'
|
9
9
|
gem 'coveralls', '>= 0.7.0'
|
10
10
|
end
|
11
|
+
|
data/lib/sequitur/constants.rb
CHANGED
@@ -121,7 +121,7 @@ class SequiturGrammar < DynamicGrammar
|
|
121
121
|
# And delete P
|
122
122
|
def restore_utility(prod_index)
|
123
123
|
# Retrieve useless prod from its index
|
124
|
-
useless_prod =
|
124
|
+
useless_prod = productions[prod_index]
|
125
125
|
|
126
126
|
# Retrieve production referencing useless one
|
127
127
|
referencing = nil
|
@@ -71,7 +71,7 @@ describe DynamicGrammar do
|
|
71
71
|
expect(p_b.refcount).to eq(1)
|
72
72
|
expect(p_c.refcount).to eq(1)
|
73
73
|
|
74
|
-
subject.remove_production(1)
|
74
|
+
subject.remove_production(1) # 1 => p_a
|
75
75
|
expect(subject.productions.size).to eq(4)
|
76
76
|
expect(p_b.refcount).to eq(1)
|
77
77
|
expect(p_c.refcount).to eq(1)
|
@@ -60,7 +60,7 @@ SNIPPET
|
|
60
60
|
|
61
61
|
it 'should support visit events with an explicit visitor' do
|
62
62
|
instance = BaseText.new(destination)
|
63
|
-
a_visitor = sample_grammar.visitor
|
63
|
+
a_visitor = sample_grammar.visitor # Use visitor explicitly
|
64
64
|
instance.render(a_visitor)
|
65
65
|
expectations = <<-SNIPPET
|
66
66
|
start :.
|
@@ -72,8 +72,8 @@ describe ProductionRef do
|
|
72
72
|
|
73
73
|
it 'should compare to other production (reference)' do
|
74
74
|
same = ProductionRef.new(target)
|
75
|
-
expect(subject).to eq(subject)
|
76
|
-
expect(subject).to eq(same)
|
75
|
+
expect(subject).to eq(subject) # Strict identity
|
76
|
+
expect(subject).to eq(same) # 2 references pointing to same production
|
77
77
|
expect(subject).to eq(target)
|
78
78
|
end
|
79
79
|
|
@@ -129,7 +129,7 @@ describe Production do
|
|
129
129
|
# Side-effect: refcount of production to append is incremented
|
130
130
|
expect(p_a.refcount).to be(0)
|
131
131
|
|
132
|
-
input = [p_a, :b, :c, :d, p_a, :e, :f]
|
132
|
+
input = [p_a, :b, :c, :d, p_a, :e, :f] # p_a appears twice
|
133
133
|
input.each { |symb| subject.append_symbol(symb) }
|
134
134
|
expect(p_a.refcount).to be(2)
|
135
135
|
end
|
@@ -139,7 +139,7 @@ describe Production do
|
|
139
139
|
ref_a = ProductionRef.new(p_a)
|
140
140
|
expect(p_a.refcount).to be(1)
|
141
141
|
|
142
|
-
input = [ref_a, :b, :c, :d, ref_a]
|
142
|
+
input = [ref_a, :b, :c, :d, ref_a] # ref_a appears twice
|
143
143
|
input.each { |symb| subject.append_symbol(symb) }
|
144
144
|
|
145
145
|
# References in rhs should point to p_a...
|
@@ -1,304 +1,304 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
# Load the class under test
|
4
|
-
require_relative '../../lib/sequitur/sequitur_grammar'
|
5
|
-
|
6
|
-
module Sequitur # Re-open the module to get rid of qualified names
|
7
|
-
describe SequiturGrammar do
|
8
|
-
# Factory method. Returns an empty enumerator (
|
9
|
-
# i.e. without elements to iterate)
|
10
|
-
def empty_enum()
|
11
|
-
return [].to_enum
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'Creation from an enumeration of tokens:' do
|
15
|
-
it 'could be created with an empty enumerator' do
|
16
|
-
expect { SequiturGrammar.new(empty_enum) }.not_to raise_error
|
17
|
-
|
18
|
-
# Creation
|
19
|
-
instance = SequiturGrammar.new(empty_enum)
|
20
|
-
|
21
|
-
# Initialization
|
22
|
-
expect(instance.productions.size).to eq(1)
|
23
|
-
expect(instance.start).to eq(instance.productions.first)
|
24
|
-
expect(instance.start).to be_empty
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'could be created with single token' do
|
28
|
-
# Creation
|
29
|
-
instance = SequiturGrammar.new([:a].to_enum)
|
30
|
-
|
31
|
-
# Initialization
|
32
|
-
expect(instance.productions.size).to eq(1)
|
33
|
-
expect(instance.start).to eq(instance.productions.first)
|
34
|
-
expect(instance.start.rhs).to eq([:a])
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'could be created with multiple unique tokens' do
|
38
|
-
# Creation
|
39
|
-
instance = SequiturGrammar.new([:a, :b, :c, :d].to_enum)
|
40
|
-
|
41
|
-
# Initialization
|
42
|
-
expect(instance.productions.size).to eq(1)
|
43
|
-
expect(instance.start).to eq(instance.productions.first)
|
44
|
-
expect(instance.start.rhs).to eq([:a, :b, :c, :d])
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'could be created with a repeating digram' do
|
48
|
-
instance = SequiturGrammar.new([:a, :b, :a, :b].to_enum)
|
49
|
-
|
50
|
-
# Expectations:
|
51
|
-
# S : A A.
|
52
|
-
# A : a b.
|
53
|
-
expect(instance.productions.size).to eq(2)
|
54
|
-
p_a = instance.productions[1]
|
55
|
-
expect(p_a.rhs).to eq([:a, :b])
|
56
|
-
expect(instance.start.rhs).to eq([p_a, p_a])
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'should enforce the utility rule' do
|
60
|
-
instance = SequiturGrammar.new([:a, :b, :c, :a, :b, :c].to_enum)
|
61
|
-
|
62
|
-
# Expectations without utility rule:
|
63
|
-
# S : B B.
|
64
|
-
# A : a b.
|
65
|
-
# B : A c.
|
66
|
-
|
67
|
-
# Expectations with utility rule:
|
68
|
-
# S : A A.
|
69
|
-
# A : a b c.
|
70
|
-
expect(instance.productions.size).to eq(2)
|
71
|
-
p_a = instance.productions.last
|
72
|
-
expect(p_a.rhs).to eq([:a, :b, :c])
|
73
|
-
expect(instance.start.rhs).to eq([p_a, p_a])
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'should cope with a pattern that caused an exception' do
|
77
|
-
input = 'aaac'
|
78
|
-
|
79
|
-
# Creation
|
80
|
-
expect { SequiturGrammar.new(input.chars) }.not_to raise_error
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
it 'should cope with the example from presentation' do
|
85
|
-
input = 'bbebeebebebbebee'
|
86
|
-
|
87
|
-
# Creation
|
88
|
-
instance = SequiturGrammar.new(input.chars)
|
89
|
-
|
90
|
-
# Expectations:
|
91
|
-
# S: P3 P2 P3
|
92
|
-
# P1: b e
|
93
|
-
# P2: P1 P1
|
94
|
-
# P3: b P2 e
|
95
|
-
expect(instance.productions.size).to eq(4)
|
96
|
-
(p1, p2, p3) = instance.productions[1..3]
|
97
|
-
expect(instance.start.rhs).to eq([p3, p2, p3])
|
98
|
-
expect(p1.rhs).to eq(%w(b e))
|
99
|
-
expect(p2.rhs).to eq([p1, p1])
|
100
|
-
expect(p3.rhs).to eq(['b', p2, 'e'])
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'should work with strings instead of single char input tokens' do
|
104
|
-
# Raw input is sequence of chars
|
105
|
-
raw_input = 'bbebeebebebbebee'
|
106
|
-
|
107
|
-
# Convert them into multichar strings
|
108
|
-
input = raw_input.chars.map do |ch|
|
109
|
-
'letter_' + ch
|
110
|
-
end
|
111
|
-
|
112
|
-
# Creation
|
113
|
-
instance = SequiturGrammar.new(input.to_enum)
|
114
|
-
|
115
|
-
# Expectations:
|
116
|
-
# S: P3 P2 P3
|
117
|
-
# P1: b e
|
118
|
-
# P2: P1 P1
|
119
|
-
# P3: b P2 e
|
120
|
-
expect(instance.productions.size).to eq(4)
|
121
|
-
(p1, p2, p3) = instance.productions[1..3]
|
122
|
-
expect(instance.start.rhs).to eq([p3, p2, p3])
|
123
|
-
expect(p1.rhs).to eq(%w(letter_b letter_e))
|
124
|
-
expect(p2.rhs).to eq([p1, p1])
|
125
|
-
expect(p3.rhs).to eq(['letter_b', p2, 'letter_e'])
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'should work with Symbol instead of single char input tokens' do
|
129
|
-
# Raw input is sequence of single characters
|
130
|
-
raw_input = 'bbebeebebebbebee'
|
131
|
-
|
132
|
-
# Convert them into symbols
|
133
|
-
input = raw_input.chars.map(&:to_sym)
|
134
|
-
|
135
|
-
# Creation
|
136
|
-
instance = SequiturGrammar.new(input.to_enum)
|
137
|
-
|
138
|
-
# Expectations:
|
139
|
-
# S: P3 P2 P3
|
140
|
-
# P1: b e
|
141
|
-
# P2: P1 P1
|
142
|
-
# P3: b P2 e
|
143
|
-
expect(instance.productions.size).to eq(4)
|
144
|
-
(p1, p2, p3) = instance.productions[1..3]
|
145
|
-
expect(instance.start.rhs).to eq([p3, p2, p3])
|
146
|
-
expect(p1.rhs).to eq([:b, :e])
|
147
|
-
expect(p2.rhs).to eq([p1, p1])
|
148
|
-
expect(p3.rhs).to eq([:b, p2, :e])
|
149
|
-
end
|
150
|
-
|
151
|
-
|
152
|
-
it 'should work with integer values as input tokens' do
|
153
|
-
# Raw input is sequence of hex digits
|
154
|
-
raw_input = 'bbebeebebebbebee'
|
155
|
-
|
156
|
-
# Convert them into Fixnums
|
157
|
-
input = raw_input.chars.map { |ch| ch.to_i(16) }
|
158
|
-
|
159
|
-
# Creation
|
160
|
-
instance = SequiturGrammar.new(input.to_enum)
|
161
|
-
|
162
|
-
# Expectations:
|
163
|
-
# S: P3 P2 P3
|
164
|
-
# P1: b e
|
165
|
-
# P2: P1 P1
|
166
|
-
# P3: b P2 e
|
167
|
-
expect(instance.productions.size).to eq(4)
|
168
|
-
(p1, p2, p3) = instance.productions[1..3]
|
169
|
-
expect(instance.start.rhs).to eq([p3, p2, p3])
|
170
|
-
expect(p1.rhs).to eq([0xb, 0xe])
|
171
|
-
expect(p2.rhs).to eq([p1, p1])
|
172
|
-
expect(p3.rhs).to eq([0xb, p2, 0xe])
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'should cope with the example from sequitur.info website' do
|
176
|
-
input = 'abcabdabcabd'
|
177
|
-
instance = SequiturGrammar.new(input.chars)
|
178
|
-
|
179
|
-
# Expectations:
|
180
|
-
# 0 → 2 2
|
181
|
-
# 1 → a b
|
182
|
-
# 2 → 1 c 1 d
|
183
|
-
|
184
|
-
expect(instance.productions.size).to eq(3)
|
185
|
-
(p1, p2) = instance.productions[1..2]
|
186
|
-
expect(instance.start.rhs).to eq([p2, p2])
|
187
|
-
expect(p1.rhs).to eq(%w(a b))
|
188
|
-
expect(p2.rhs).to eq([p1, 'c', p1, 'd'])
|
189
|
-
end
|
190
|
-
|
191
|
-
it "should cope with the example from Salomon's book" do
|
192
|
-
input = 'abcdbcabcdbc'
|
193
|
-
instance = SequiturGrammar.new(input.chars)
|
194
|
-
|
195
|
-
# Expectations:
|
196
|
-
# S → CC
|
197
|
-
# A → bc
|
198
|
-
# C → aAdA
|
199
|
-
|
200
|
-
expect(instance.productions.size).to eq(3)
|
201
|
-
(p_a, p_c) = instance.productions[1..2]
|
202
|
-
expect(instance.start.rhs).to eq([p_c, p_c])
|
203
|
-
expect(p_a.rhs).to eq(%w(b c))
|
204
|
-
expect(p_c.rhs).to eq(['a', p_a, 'd', p_a])
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'should cope with the "porridge" example from sequitur.info' do
|
208
|
-
# Another example from sequitur.info website
|
209
|
-
input = <<-SNIPPET
|
210
|
-
pease porridge hot,
|
211
|
-
pease porridge cold,
|
212
|
-
pease porridge in the pot,
|
213
|
-
nine days old.
|
214
|
-
|
215
|
-
some like it hot,
|
216
|
-
some like it cold,
|
217
|
-
some like it in the pot,
|
218
|
-
nine days old.
|
219
|
-
SNIPPET
|
220
|
-
# Expectations (sequitur.org)
|
221
|
-
# 0 → 1 2 3 4 3 5 ↵ 6 2 7 4 7 5
|
222
|
-
# 1 → p e a s 8 r r i d g 9 pease_porridge_
|
223
|
-
# 2 → h o t hot
|
224
|
-
# 3 → 10 1 ,↵pease_porridge_
|
225
|
-
# 4 → c 11 cold
|
226
|
-
# 5 → 12 _ t h 8 t 10 n 12 9 d a y s _ 11 . ↵
|
227
|
-
# in_the_pot,↵nine_days_old.↵
|
228
|
-
# 6 → s o m 9 l i k 9 i t _ some_like_it_
|
229
|
-
# 7 → 10 6 ,↵some_like_it_
|
230
|
-
# 8 → 9 p o e_po
|
231
|
-
# 9 → e _ e_
|
232
|
-
# 10 → , ↵ ,↵
|
233
|
-
# 11 → o l d old
|
234
|
-
# 12 → i n in
|
235
|
-
|
236
|
-
instance = SequiturGrammar.new(input.chars)
|
237
|
-
expect(instance.productions.size).to eq(13)
|
238
|
-
p0 = instance.start
|
239
|
-
expect(p0.rhs.size).to eq(13)
|
240
|
-
|
241
|
-
(p1, p2, p3, p4, p5, p6, p7, p8, p9) = instance.productions[1..9]
|
242
|
-
(p10, p11, p12) = instance.productions[10..12]
|
243
|
-
|
244
|
-
# Note: the productions aren't sorted the same way as
|
245
|
-
# the sequitur.info implementation.
|
246
|
-
p0_expectation = [
|
247
|
-
p2, p8, p3, p10, p3, p12, "\n",
|
248
|
-
p9, p8, p11, p10, p11, p12
|
249
|
-
]
|
250
|
-
expect(p0.rhs).to eq(p0_expectation)
|
251
|
-
expect(p1.rhs).to eq(['e', ' '])
|
252
|
-
expect(p2.rhs).to eq([%w(p e a s), p4, %w(r r i d g), p1].flatten) # R1
|
253
|
-
expect(p3.rhs).to eq([p5, p2])
|
254
|
-
expect(p4.rhs).to eq([p1, 'p', 'o'])
|
255
|
-
expect(p5.rhs).to eq([',', "\n"])
|
256
|
-
expect(p6.rhs).to eq(%w(i n))
|
257
|
-
expect(p7.rhs).to eq(%w(o l d))
|
258
|
-
expect(p8.rhs).to eq(%w(h o t))
|
259
|
-
p9_expectation = [%w(s o m), p1, %w(l i k), p1, 'i', 't', ' '].flatten
|
260
|
-
expect(p9.rhs).to eq(p9_expectation)
|
261
|
-
expect(p10.rhs).to eq(['c', p7])
|
262
|
-
expect(p11.rhs).to eq([p5, p9])
|
263
|
-
p12_expectation = [
|
264
|
-
p6, ' ', 't', 'h', p4, 't', p5, 'n', p6, p1,
|
265
|
-
%w(d a y s), ' ', p7, '.', "\n"
|
266
|
-
].flatten
|
267
|
-
expect(p12.rhs).to eq(p12_expectation)
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'should work with a sequence of Ruby Symbols' do
|
271
|
-
input = 'abcabdabcabd'.chars.map(&:to_sym)
|
272
|
-
instance = SequiturGrammar.new(input.to_enum)
|
273
|
-
|
274
|
-
# Expectations:
|
275
|
-
# start : P2 P2.
|
276
|
-
# P1 : :a :b
|
277
|
-
# P2 : P1 :c P1 :d.
|
278
|
-
|
279
|
-
expect(instance.productions.size).to eq(3)
|
280
|
-
(p1, p2) = instance.productions[1..2]
|
281
|
-
expect(instance.start.rhs).to eq([p2, p2])
|
282
|
-
expect(p1.rhs).to eq([:a, :b])
|
283
|
-
expect(p2.rhs).to eq([p1, :c, p1, :d])
|
284
|
-
end
|
285
|
-
end # context
|
286
|
-
|
287
|
-
context 'Generating a text representation of itself:' do
|
288
|
-
it 'should generate a text representation when empty' do
|
289
|
-
instance = SequiturGrammar.new(empty_enum)
|
290
|
-
expectation = "#{instance.start.object_id} : ."
|
291
|
-
|
292
|
-
expect(instance.to_string).to eq(expectation)
|
293
|
-
end
|
294
|
-
|
295
|
-
it 'should generate a text representation of a simple production' do
|
296
|
-
instance = SequiturGrammar.new([:a].to_enum)
|
297
|
-
expectation = "#{instance.start.object_id} : a."
|
298
|
-
expect(instance.to_string).to eq(expectation)
|
299
|
-
end
|
300
|
-
end # context
|
301
|
-
end # describe
|
302
|
-
end # module
|
303
|
-
|
304
|
-
# End of file
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
# Load the class under test
|
4
|
+
require_relative '../../lib/sequitur/sequitur_grammar'
|
5
|
+
|
6
|
+
module Sequitur # Re-open the module to get rid of qualified names
|
7
|
+
describe SequiturGrammar do
|
8
|
+
# Factory method. Returns an empty enumerator (
|
9
|
+
# i.e. without elements to iterate)
|
10
|
+
def empty_enum()
|
11
|
+
return [].to_enum
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'Creation from an enumeration of tokens:' do
|
15
|
+
it 'could be created with an empty enumerator' do
|
16
|
+
expect { SequiturGrammar.new(empty_enum) }.not_to raise_error
|
17
|
+
|
18
|
+
# Creation
|
19
|
+
instance = SequiturGrammar.new(empty_enum)
|
20
|
+
|
21
|
+
# Initialization
|
22
|
+
expect(instance.productions.size).to eq(1)
|
23
|
+
expect(instance.start).to eq(instance.productions.first)
|
24
|
+
expect(instance.start).to be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'could be created with single token' do
|
28
|
+
# Creation
|
29
|
+
instance = SequiturGrammar.new([:a].to_enum)
|
30
|
+
|
31
|
+
# Initialization
|
32
|
+
expect(instance.productions.size).to eq(1)
|
33
|
+
expect(instance.start).to eq(instance.productions.first)
|
34
|
+
expect(instance.start.rhs).to eq([:a])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'could be created with multiple unique tokens' do
|
38
|
+
# Creation
|
39
|
+
instance = SequiturGrammar.new([:a, :b, :c, :d].to_enum)
|
40
|
+
|
41
|
+
# Initialization
|
42
|
+
expect(instance.productions.size).to eq(1)
|
43
|
+
expect(instance.start).to eq(instance.productions.first)
|
44
|
+
expect(instance.start.rhs).to eq([:a, :b, :c, :d])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'could be created with a repeating digram' do
|
48
|
+
instance = SequiturGrammar.new([:a, :b, :a, :b].to_enum)
|
49
|
+
|
50
|
+
# Expectations:
|
51
|
+
# S : A A.
|
52
|
+
# A : a b.
|
53
|
+
expect(instance.productions.size).to eq(2)
|
54
|
+
p_a = instance.productions[1]
|
55
|
+
expect(p_a.rhs).to eq([:a, :b])
|
56
|
+
expect(instance.start.rhs).to eq([p_a, p_a])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should enforce the utility rule' do
|
60
|
+
instance = SequiturGrammar.new([:a, :b, :c, :a, :b, :c].to_enum)
|
61
|
+
|
62
|
+
# Expectations without utility rule:
|
63
|
+
# S : B B.
|
64
|
+
# A : a b.
|
65
|
+
# B : A c.
|
66
|
+
|
67
|
+
# Expectations with utility rule:
|
68
|
+
# S : A A.
|
69
|
+
# A : a b c.
|
70
|
+
expect(instance.productions.size).to eq(2)
|
71
|
+
p_a = instance.productions.last
|
72
|
+
expect(p_a.rhs).to eq([:a, :b, :c])
|
73
|
+
expect(instance.start.rhs).to eq([p_a, p_a])
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should cope with a pattern that caused an exception' do
|
77
|
+
input = 'aaac' # This sequence raised an exception
|
78
|
+
|
79
|
+
# Creation
|
80
|
+
expect { SequiturGrammar.new(input.chars) }.not_to raise_error
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
it 'should cope with the example from presentation' do
|
85
|
+
input = 'bbebeebebebbebee'
|
86
|
+
|
87
|
+
# Creation
|
88
|
+
instance = SequiturGrammar.new(input.chars)
|
89
|
+
|
90
|
+
# Expectations:
|
91
|
+
# S: P3 P2 P3
|
92
|
+
# P1: b e
|
93
|
+
# P2: P1 P1
|
94
|
+
# P3: b P2 e
|
95
|
+
expect(instance.productions.size).to eq(4)
|
96
|
+
(p1, p2, p3) = instance.productions[1..3]
|
97
|
+
expect(instance.start.rhs).to eq([p3, p2, p3])
|
98
|
+
expect(p1.rhs).to eq(%w(b e))
|
99
|
+
expect(p2.rhs).to eq([p1, p1])
|
100
|
+
expect(p3.rhs).to eq(['b', p2, 'e'])
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should work with strings instead of single char input tokens' do
|
104
|
+
# Raw input is sequence of chars
|
105
|
+
raw_input = 'bbebeebebebbebee'
|
106
|
+
|
107
|
+
# Convert them into multichar strings
|
108
|
+
input = raw_input.chars.map do |ch|
|
109
|
+
'letter_' + ch
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creation
|
113
|
+
instance = SequiturGrammar.new(input.to_enum)
|
114
|
+
|
115
|
+
# Expectations:
|
116
|
+
# S: P3 P2 P3
|
117
|
+
# P1: b e
|
118
|
+
# P2: P1 P1
|
119
|
+
# P3: b P2 e
|
120
|
+
expect(instance.productions.size).to eq(4)
|
121
|
+
(p1, p2, p3) = instance.productions[1..3]
|
122
|
+
expect(instance.start.rhs).to eq([p3, p2, p3])
|
123
|
+
expect(p1.rhs).to eq(%w(letter_b letter_e))
|
124
|
+
expect(p2.rhs).to eq([p1, p1])
|
125
|
+
expect(p3.rhs).to eq(['letter_b', p2, 'letter_e'])
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should work with Symbol instead of single char input tokens' do
|
129
|
+
# Raw input is sequence of single characters
|
130
|
+
raw_input = 'bbebeebebebbebee'
|
131
|
+
|
132
|
+
# Convert them into symbols
|
133
|
+
input = raw_input.chars.map(&:to_sym)
|
134
|
+
|
135
|
+
# Creation
|
136
|
+
instance = SequiturGrammar.new(input.to_enum)
|
137
|
+
|
138
|
+
# Expectations:
|
139
|
+
# S: P3 P2 P3
|
140
|
+
# P1: b e
|
141
|
+
# P2: P1 P1
|
142
|
+
# P3: b P2 e
|
143
|
+
expect(instance.productions.size).to eq(4)
|
144
|
+
(p1, p2, p3) = instance.productions[1..3]
|
145
|
+
expect(instance.start.rhs).to eq([p3, p2, p3])
|
146
|
+
expect(p1.rhs).to eq([:b, :e])
|
147
|
+
expect(p2.rhs).to eq([p1, p1])
|
148
|
+
expect(p3.rhs).to eq([:b, p2, :e])
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
it 'should work with integer values as input tokens' do
|
153
|
+
# Raw input is sequence of hex digits
|
154
|
+
raw_input = 'bbebeebebebbebee'
|
155
|
+
|
156
|
+
# Convert them into Fixnums
|
157
|
+
input = raw_input.chars.map { |ch| ch.to_i(16) }
|
158
|
+
|
159
|
+
# Creation
|
160
|
+
instance = SequiturGrammar.new(input.to_enum)
|
161
|
+
|
162
|
+
# Expectations:
|
163
|
+
# S: P3 P2 P3
|
164
|
+
# P1: b e
|
165
|
+
# P2: P1 P1
|
166
|
+
# P3: b P2 e
|
167
|
+
expect(instance.productions.size).to eq(4)
|
168
|
+
(p1, p2, p3) = instance.productions[1..3]
|
169
|
+
expect(instance.start.rhs).to eq([p3, p2, p3])
|
170
|
+
expect(p1.rhs).to eq([0xb, 0xe])
|
171
|
+
expect(p2.rhs).to eq([p1, p1])
|
172
|
+
expect(p3.rhs).to eq([0xb, p2, 0xe])
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should cope with the example from sequitur.info website' do
|
176
|
+
input = 'abcabdabcabd'
|
177
|
+
instance = SequiturGrammar.new(input.chars)
|
178
|
+
|
179
|
+
# Expectations:
|
180
|
+
# 0 → 2 2
|
181
|
+
# 1 → a b
|
182
|
+
# 2 → 1 c 1 d
|
183
|
+
|
184
|
+
expect(instance.productions.size).to eq(3)
|
185
|
+
(p1, p2) = instance.productions[1..2]
|
186
|
+
expect(instance.start.rhs).to eq([p2, p2])
|
187
|
+
expect(p1.rhs).to eq(%w(a b))
|
188
|
+
expect(p2.rhs).to eq([p1, 'c', p1, 'd'])
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should cope with the example from Salomon's book" do
|
192
|
+
input = 'abcdbcabcdbc'
|
193
|
+
instance = SequiturGrammar.new(input.chars)
|
194
|
+
|
195
|
+
# Expectations:
|
196
|
+
# S → CC
|
197
|
+
# A → bc
|
198
|
+
# C → aAdA
|
199
|
+
|
200
|
+
expect(instance.productions.size).to eq(3)
|
201
|
+
(p_a, p_c) = instance.productions[1..2]
|
202
|
+
expect(instance.start.rhs).to eq([p_c, p_c])
|
203
|
+
expect(p_a.rhs).to eq(%w(b c))
|
204
|
+
expect(p_c.rhs).to eq(['a', p_a, 'd', p_a])
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should cope with the "porridge" example from sequitur.info' do
|
208
|
+
# Another example from sequitur.info website
|
209
|
+
input = <<-SNIPPET
|
210
|
+
pease porridge hot,
|
211
|
+
pease porridge cold,
|
212
|
+
pease porridge in the pot,
|
213
|
+
nine days old.
|
214
|
+
|
215
|
+
some like it hot,
|
216
|
+
some like it cold,
|
217
|
+
some like it in the pot,
|
218
|
+
nine days old.
|
219
|
+
SNIPPET
|
220
|
+
# Expectations (sequitur.org)
|
221
|
+
# 0 → 1 2 3 4 3 5 ↵ 6 2 7 4 7 5
|
222
|
+
# 1 → p e a s 8 r r i d g 9 pease_porridge_
|
223
|
+
# 2 → h o t hot
|
224
|
+
# 3 → 10 1 ,↵pease_porridge_
|
225
|
+
# 4 → c 11 cold
|
226
|
+
# 5 → 12 _ t h 8 t 10 n 12 9 d a y s _ 11 . ↵
|
227
|
+
# in_the_pot,↵nine_days_old.↵
|
228
|
+
# 6 → s o m 9 l i k 9 i t _ some_like_it_
|
229
|
+
# 7 → 10 6 ,↵some_like_it_
|
230
|
+
# 8 → 9 p o e_po
|
231
|
+
# 9 → e _ e_
|
232
|
+
# 10 → , ↵ ,↵
|
233
|
+
# 11 → o l d old
|
234
|
+
# 12 → i n in
|
235
|
+
|
236
|
+
instance = SequiturGrammar.new(input.chars)
|
237
|
+
expect(instance.productions.size).to eq(13)
|
238
|
+
p0 = instance.start
|
239
|
+
expect(p0.rhs.size).to eq(13)
|
240
|
+
|
241
|
+
(p1, p2, p3, p4, p5, p6, p7, p8, p9) = instance.productions[1..9]
|
242
|
+
(p10, p11, p12) = instance.productions[10..12]
|
243
|
+
|
244
|
+
# Note: the productions aren't sorted the same way as
|
245
|
+
# the sequitur.info implementation.
|
246
|
+
p0_expectation = [
|
247
|
+
p2, p8, p3, p10, p3, p12, "\n",
|
248
|
+
p9, p8, p11, p10, p11, p12
|
249
|
+
]
|
250
|
+
expect(p0.rhs).to eq(p0_expectation) # Rule 0 above
|
251
|
+
expect(p1.rhs).to eq(['e', ' ']) # Rule 9 above
|
252
|
+
expect(p2.rhs).to eq([%w(p e a s), p4, %w(r r i d g), p1].flatten) # R1
|
253
|
+
expect(p3.rhs).to eq([p5, p2]) # Rule 3 above
|
254
|
+
expect(p4.rhs).to eq([p1, 'p', 'o']) # Rule 8 above
|
255
|
+
expect(p5.rhs).to eq([',', "\n"]) # Rule 10 above
|
256
|
+
expect(p6.rhs).to eq(%w(i n)) # Rule 12 above
|
257
|
+
expect(p7.rhs).to eq(%w(o l d)) # Rule 11 above
|
258
|
+
expect(p8.rhs).to eq(%w(h o t)) # Rule 2 above
|
259
|
+
p9_expectation = [%w(s o m), p1, %w(l i k), p1, 'i', 't', ' '].flatten
|
260
|
+
expect(p9.rhs).to eq(p9_expectation) # Rule 6 above
|
261
|
+
expect(p10.rhs).to eq(['c', p7]) # Rule 4 above
|
262
|
+
expect(p11.rhs).to eq([p5, p9]) # Rule 7 above
|
263
|
+
p12_expectation = [
|
264
|
+
p6, ' ', 't', 'h', p4, 't', p5, 'n', p6, p1,
|
265
|
+
%w(d a y s), ' ', p7, '.', "\n"
|
266
|
+
].flatten
|
267
|
+
expect(p12.rhs).to eq(p12_expectation) # Rule 5 above
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'should work with a sequence of Ruby Symbols' do
|
271
|
+
input = 'abcabdabcabd'.chars.map(&:to_sym)
|
272
|
+
instance = SequiturGrammar.new(input.to_enum)
|
273
|
+
|
274
|
+
# Expectations:
|
275
|
+
# start : P2 P2.
|
276
|
+
# P1 : :a :b
|
277
|
+
# P2 : P1 :c P1 :d.
|
278
|
+
|
279
|
+
expect(instance.productions.size).to eq(3)
|
280
|
+
(p1, p2) = instance.productions[1..2]
|
281
|
+
expect(instance.start.rhs).to eq([p2, p2])
|
282
|
+
expect(p1.rhs).to eq([:a, :b])
|
283
|
+
expect(p2.rhs).to eq([p1, :c, p1, :d])
|
284
|
+
end
|
285
|
+
end # context
|
286
|
+
|
287
|
+
context 'Generating a text representation of itself:' do
|
288
|
+
it 'should generate a text representation when empty' do
|
289
|
+
instance = SequiturGrammar.new(empty_enum)
|
290
|
+
expectation = "#{instance.start.object_id} : ."
|
291
|
+
|
292
|
+
expect(instance.to_string).to eq(expectation)
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'should generate a text representation of a simple production' do
|
296
|
+
instance = SequiturGrammar.new([:a].to_enum)
|
297
|
+
expectation = "#{instance.start.object_id} : a."
|
298
|
+
expect(instance.to_string).to eq(expectation)
|
299
|
+
end
|
300
|
+
end # context
|
301
|
+
end # describe
|
302
|
+
end # module
|
303
|
+
|
304
|
+
# End of file
|
metadata
CHANGED
@@ -1,86 +1,104 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequitur
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 10.0.0
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 10.0.0
|
20
23
|
type: :development
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- -
|
27
|
+
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
29
|
+
version: 10.0.0
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 10.0.0
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: rspec
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
|
-
- -
|
37
|
+
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
39
|
+
version: 2.1.0
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.1.0
|
34
43
|
type: :development
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
37
46
|
requirements:
|
38
|
-
- -
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 2.1.0
|
50
|
+
- - ">="
|
39
51
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
52
|
+
version: 2.1.0
|
41
53
|
- !ruby/object:Gem::Dependency
|
42
54
|
name: simplecov
|
43
55
|
requirement: !ruby/object:Gem::Requirement
|
44
56
|
requirements:
|
45
|
-
- -
|
57
|
+
- - ">="
|
46
58
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
59
|
+
version: 0.8.0
|
48
60
|
type: :development
|
49
61
|
prerelease: false
|
50
62
|
version_requirements: !ruby/object:Gem::Requirement
|
51
63
|
requirements:
|
52
|
-
- -
|
64
|
+
- - ">="
|
53
65
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
66
|
+
version: 0.8.0
|
55
67
|
- !ruby/object:Gem::Dependency
|
56
68
|
name: coveralls
|
57
69
|
requirement: !ruby/object:Gem::Requirement
|
58
70
|
requirements:
|
59
|
-
- -
|
71
|
+
- - ">="
|
60
72
|
- !ruby/object:Gem::Version
|
61
73
|
version: 0.7.0
|
62
74
|
type: :development
|
63
75
|
prerelease: false
|
64
76
|
version_requirements: !ruby/object:Gem::Requirement
|
65
77
|
requirements:
|
66
|
-
- -
|
78
|
+
- - ">="
|
67
79
|
- !ruby/object:Gem::Version
|
68
80
|
version: 0.7.0
|
69
81
|
- !ruby/object:Gem::Dependency
|
70
82
|
name: rubygems
|
71
83
|
requirement: !ruby/object:Gem::Requirement
|
72
84
|
requirements:
|
73
|
-
- -
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '2.0'
|
88
|
+
- - ">="
|
74
89
|
- !ruby/object:Gem::Version
|
75
90
|
version: 2.0.0
|
76
91
|
type: :development
|
77
92
|
prerelease: false
|
78
93
|
version_requirements: !ruby/object:Gem::Requirement
|
79
94
|
requirements:
|
80
|
-
- -
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '2.0'
|
98
|
+
- - ">="
|
81
99
|
- !ruby/object:Gem::Version
|
82
100
|
version: 2.0.0
|
83
|
-
description:
|
101
|
+
description: "Ruby implementation of the Sequitur algorithm. This algorithm automatically
|
84
102
|
\nfinds repetitions and hierarchical structures in a given sequence of input \ntokens.
|
85
103
|
It encodes the input into a context-free grammar. \nThe Sequitur algorithm can be
|
86
104
|
used to \na) compress a sequence of items,\nb) discover patterns in an sequence,
|
@@ -91,18 +109,23 @@ extensions: []
|
|
91
109
|
extra_rdoc_files:
|
92
110
|
- README.md
|
93
111
|
files:
|
94
|
-
- .
|
95
|
-
- .
|
96
|
-
- .ruby-gemset
|
97
|
-
- .ruby-version
|
98
|
-
- .simplecov
|
99
|
-
- .travis.yml
|
100
|
-
- .yardopts
|
101
|
-
- Gemfile
|
102
|
-
- Rakefile
|
112
|
+
- ".rspec"
|
113
|
+
- ".rubocop.yml"
|
114
|
+
- ".ruby-gemset"
|
115
|
+
- ".ruby-version"
|
116
|
+
- ".simplecov"
|
117
|
+
- ".travis.yml"
|
118
|
+
- ".yardopts"
|
103
119
|
- CHANGELOG.md
|
120
|
+
- Gemfile
|
104
121
|
- LICENSE.txt
|
105
122
|
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- examples/integer_sample.rb
|
125
|
+
- examples/porridge.rb
|
126
|
+
- examples/simple_case.rb
|
127
|
+
- examples/symbol_sample.rb
|
128
|
+
- examples/word_sample.rb
|
106
129
|
- lib/sequitur.rb
|
107
130
|
- lib/sequitur/constants.rb
|
108
131
|
- lib/sequitur/digram.rb
|
@@ -125,39 +148,31 @@ files:
|
|
125
148
|
- spec/sequitur/sequitur_grammar_spec.rb
|
126
149
|
- spec/sequitur/symbol_sequence_spec.rb
|
127
150
|
- spec/spec_helper.rb
|
128
|
-
- examples/integer_sample.rb
|
129
|
-
- examples/porridge.rb
|
130
|
-
- examples/simple_case.rb
|
131
|
-
- examples/symbol_sample.rb
|
132
|
-
- examples/word_sample.rb
|
133
151
|
homepage: https://github.com/famished-tiger/Sequitur
|
134
152
|
licenses:
|
135
153
|
- MIT
|
136
154
|
metadata: {}
|
137
|
-
post_install_message:
|
138
|
-
|
155
|
+
post_install_message: |
|
156
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
139
157
|
Thank you for installing Sequitur...
|
140
|
-
|
141
158
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
142
|
-
|
143
|
-
'
|
144
159
|
rdoc_options:
|
145
160
|
- --charset=UTF-8 --exclude="examples|features|spec"
|
146
161
|
require_paths:
|
147
162
|
- lib
|
148
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
149
164
|
requirements:
|
150
|
-
- -
|
165
|
+
- - ">="
|
151
166
|
- !ruby/object:Gem::Version
|
152
167
|
version: 1.9.1
|
153
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
169
|
requirements:
|
155
|
-
- -
|
170
|
+
- - ">="
|
156
171
|
- !ruby/object:Gem::Version
|
157
172
|
version: '0'
|
158
173
|
requirements: []
|
159
174
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.4.5.1
|
161
176
|
signing_key:
|
162
177
|
specification_version: 4
|
163
178
|
summary: Ruby implementation of the Sequitur algorithm
|