sequitur 0.1.13 → 0.1.14

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTk1NDVlNDJjZDIzZTY5OTE4ODI3MWM0MDc0M2EwMjIyNzRmZTk5Ng==
4
+ YTYxNDJlM2U5ZWQ1YTk3OGQzOTYyODhjMWNmMDU1ZWQwYzZjNTY0Yg==
5
5
  data.tar.gz: !binary |-
6
- MWE5OTE1MmE2NjQ0ZTk1ZmUyYzIwZTllMjFiMmE4OGU1ZGJiODZiMQ==
6
+ NmFiMDlmY2E4YjMzYjFkNTRhNzY2M2M0NTdjNTRkM2QxYzE1ZGJkOA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YWU0MzRlZGZjZWIyNDUzMjNhZDU3ZWFmZDIxZmExMTc0NWI1YTFjNDhkYmQ4
10
- NGMzYzc1ZWQwMGM4ZGUzMjVlN2JhNDhjMTU2YWUzYjU3OTQ4NWY2ZTFmZGE1
11
- NGQyZGM4ZTdkOTcyNjQ1MmRkNTgyM2NjYjcxYmU0NWI4NWE1ODc=
9
+ ZDYxMGQ1NmRjNWQ5M2MwODBhZjliNmJhZTQ5ZWMwMmI1NzA1NTEwNjhiNmYx
10
+ ZmYxYjg1NDMzMmE5NzJhNjY2OTQyMjUyMDhlYzU0Y2Y0NmQzYWU3ZTUxMjYw
11
+ ZDc4NzE0MTEwZmQzMTRhNDZiM2VmMGI2NDk5ZjM4YmJjNDdhMDc=
12
12
  data.tar.gz: !binary |-
13
- OTA0NjIxZWU3OGU0MjY2MWVlYWQ4NDVmYTc0NDA0ZDQyZTQ1MTQzNmZhMjRj
14
- ZDMwMmFiMzlkZGE5MmRkN2FmMGVjMWJhNWEwZmM4YjJjNWFkMDQ2YjRmMWQ3
15
- MDU3MTY3NDIwZWZiZGQ1Y2UyNTU2ODZmZWJhOWQxZDE1MDY4MzM=
13
+ NzEwYzcwOTI4NWUyYTNjZmE3MDkyNjcxYWM2MDJkYjkzYWI1YWE3YmRhZjg4
14
+ YzAxMTQ0NWM1ZTRmNzFhNjZiZTUyYTIzODE3ODY4ZGJhMGQzMmY1MmEzZTI0
15
+ MWYwMDlkYmMzMzNhYTRkNGQzOGU5YmI5ZWM1OWNmMTQ3NjgxYzI=
data/.rubocop.yml CHANGED
@@ -3,7 +3,11 @@ AllCops:
3
3
  - 'examples/**/*'
4
4
  - 'features/**/*'
5
5
  - 'gems/**/*'
6
+ - 'lab/**/*'
6
7
 
8
+ AbcSize:
9
+ Max: 20
10
+
7
11
  # This is disabled because some demos use UTF-8
8
12
  AsciiComments:
9
13
  Enabled: false
@@ -34,10 +38,7 @@ Documentation:
34
38
  Enabled: false
35
39
 
36
40
  EmptyLines:
37
- Enabled: false
38
-
39
- EmptyLinesAroundBody:
40
- Enabled: false
41
+ Enabled: false
41
42
 
42
43
  Encoding:
43
44
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
- ### 0.1.13 / 2014-10-07
2
- * [FIX] File `LICENSE.txt`: was missing in the distribuation but was referenced in README.
1
+ ### 0.1.14 / 2015-02-06
2
+ * [CHANGE] Code re-formatted to please Rubocop 0.29
3
+ * [FIX] File `.rubocop.yml`: removal of setting for obsolete EmptyLinesAroundBody cop.
4
+
5
+
6
+ ### 0.1.13 / 2015-02-05
7
+ * [FIX] File `LICENSE.txt`: was missing in the distribution but was referenced in README.
3
8
  * [CHANGE] File `README.md`: added badge from license (MIT).
4
9
 
5
10
 
data/Rakefile CHANGED
@@ -2,12 +2,10 @@ require 'rubygems'
2
2
  require_relative './lib/sequitur/constants'
3
3
 
4
4
  namespace :gem do
5
-
6
- desc 'Push the gem to rubygems.org'
7
- task :push do
8
- system("gem push sequitur-#{Sequitur::Version}.gem")
9
- end
10
-
5
+ desc 'Push the gem to rubygems.org'
6
+ task :push do
7
+ system("gem push sequitur-#{Sequitur::Version}.gem")
8
+ end
11
9
  end # namespace
12
10
 
13
11
  # Testing-specific tasks
data/lib/sequitur.rb CHANGED
@@ -9,7 +9,6 @@ require_relative './sequitur/formatter/base_text'
9
9
 
10
10
 
11
11
  module Sequitur
12
-
13
12
  # Build a Sequitur-generated grammar based on the sequence of input tokens.
14
13
  #
15
14
  # @param tokens [StringOrEnumerator] The input sequence of input tokens.
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Sequitur # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.1.13'
6
+ Version = '0.1.14'
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = 'Ruby implementation of the Sequitur algorithm'
@@ -1,7 +1,6 @@
1
1
  # File: digram.rb
2
2
 
3
3
  module Sequitur # Module for classes implementing the Sequitur algorithm
4
-
5
4
  # In linguistics, a digram is a sequence of two letters.
6
5
  # In Sequitur, a digram is a sequence of two consecutive symbols that
7
6
  # appear in a production rule. Each symbol in a digram
@@ -44,9 +43,7 @@ class Digram
44
43
  def repeating?()
45
44
  return symbols[0] == symbols[1]
46
45
  end
47
-
48
46
  end # class
49
-
50
47
  end # module
51
48
 
52
49
  # End of file
@@ -2,7 +2,6 @@ require_relative 'production'
2
2
  require_relative 'grammar_visitor'
3
3
 
4
4
  module Sequitur # Module for classes implementing the Sequitur algorithm
5
-
6
5
  # A dynamic grammar is a context-free grammar that can be built incrementally.
7
6
  # Formally, a grammar has:
8
7
  # One start production
@@ -100,7 +99,5 @@ class DynamicGrammar
100
99
  aProduction.append_symbol(aSymbol)
101
100
  end
102
101
  end # class
103
-
104
102
  end # module
105
-
106
103
  # End of file
@@ -1,8 +1,6 @@
1
1
  module Sequitur
2
-
3
2
  # Namespace dedicated to grammar formatters.
4
3
  module Formatter
5
-
6
4
  # Superclass for grammar formatters.
7
5
  class BaseFormatter
8
6
  # The IO output stream in which the formatter's result will be sent.
@@ -31,7 +29,6 @@ module Sequitur
31
29
  a_visitor.start
32
30
  a_visitor.unsubscribe(self)
33
31
  end
34
-
35
32
  end # class
36
33
  end # module
37
34
  end # module
@@ -2,7 +2,6 @@ require_relative 'base_formatter'
2
2
 
3
3
  module Sequitur
4
4
  module Formatter
5
-
6
5
  # A formatter class that can render a dynamic grammar in plain text.
7
6
  # @example
8
7
  # some_grammar = ... # Points to a DynamicGrammar-like object
@@ -11,7 +10,6 @@ module Sequitur
11
10
  # # Render the grammar (through a visitor)
12
11
  # formatter.run(some_grammar.visitor)
13
12
  class BaseText < BaseFormatter
14
-
15
13
  # Constructor.
16
14
  # @param anIO [IO] The output stream to which the rendered grammar
17
15
  # is written.
@@ -87,7 +85,6 @@ module Sequitur
87
85
  name = (prod_index == 0) ? 'start' : "P#{prod_index}"
88
86
  return name
89
87
  end
90
-
91
88
  end # class
92
89
  end # module
93
90
  end # module
@@ -3,7 +3,6 @@ require_relative 'base_formatter'
3
3
 
4
4
  module Sequitur
5
5
  module Formatter
6
-
7
6
  # A formatter class that can render the notification events
8
7
  # from a grammar visitor
9
8
  # @example
@@ -123,9 +122,7 @@ module Sequitur
123
122
  def output_event(anEvent, indentationLevel)
124
123
  output.puts "#{' ' * 2 * indentationLevel}#{anEvent}"
125
124
  end
126
-
127
125
  end # class
128
126
  end # module
129
127
  end # module
130
-
131
128
  # End of file
@@ -1,5 +1,4 @@
1
1
  module Sequitur # Module for classes implementing the Sequitur algorithm
2
-
3
2
  # A visitor class dedicated in the visit of Grammar.
4
3
  class GrammarVisitor
5
4
  # Link to the grammar to visit
@@ -101,10 +100,7 @@ class GrammarVisitor
101
100
  a_subscriber.send(msg, *args)
102
101
  end
103
102
  end
104
-
105
-
106
103
  end # class
107
-
108
104
  end # module
109
105
 
110
106
  # End of file
@@ -3,8 +3,6 @@ require_relative 'symbol_sequence'
3
3
  require_relative 'production_ref'
4
4
 
5
5
  module Sequitur # Module for classes implementing the Sequitur algorithm
6
-
7
-
8
6
  # In a context-free grammar, a production is a rule in which
9
7
  # its left-hand side (LHS) consists solely of a non-terminal symbol
10
8
  # and the right-hand side (RHS) consists of a sequence of symbols.
@@ -171,7 +169,6 @@ class Production
171
169
  # # Then ...
172
170
  # p.positions_of(a, a) # => [0, 3]
173
171
  def positions_of(symb1, symb2)
174
-
175
172
  # Find the positions where the digram occur in rhs
176
173
  indices = [ -2 ] # Dummy index!
177
174
  (0...rhs.size).each do |i|
@@ -232,9 +229,7 @@ class Production
232
229
 
233
230
  aVisitor.end_visit_production(self)
234
231
  end
235
-
236
232
  end # class
237
-
238
233
  end # module
239
234
 
240
235
  # End of file
@@ -1,7 +1,6 @@
1
1
 
2
2
 
3
3
  module Sequitur # Module for classes implementing the Sequitur algorithm
4
-
5
4
  # A production reference is a grammar symbol that may appear in the right-hand
6
5
  # side of a production P1 and that refers to a production P2.
7
6
  # Every time a production P2 appears in the left-hand side of
@@ -18,7 +17,6 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
18
17
  # # ... Production reference count is updated...
19
18
  # puts prod.refcount # outputs 1
20
19
  class ProductionRef
21
-
22
20
  # Link to the production to reference.
23
21
  attr_reader(:production)
24
22
 
@@ -111,9 +109,7 @@ class ProductionRef
111
109
  def accept(aVisitor)
112
110
  aVisitor.visit_prod_ref(self)
113
111
  end
114
-
115
112
  end # class
116
-
117
113
  end # module
118
114
 
119
115
  # End of file
@@ -2,12 +2,10 @@ require_relative 'dynamic_grammar'
2
2
 
3
3
 
4
4
  module Sequitur # Module for classes implementing the Sequitur algorithm
5
-
6
5
  # Specialization of the DynamicGrammar class.
7
6
  # A Sequitur grammar is a context-free grammar that is entirely built
8
7
  # from a sequence of input tokens through the Sequitur algorithm.
9
8
  class SequiturGrammar < DynamicGrammar
10
-
11
9
  # Build the grammar from an enumerator of tokens.
12
10
  # @param anEnum [Enumerator] an enumerator that will iterate
13
11
  # over the input tokens.
@@ -152,7 +150,5 @@ class SequiturGrammar < DynamicGrammar
152
150
  return new_prod
153
151
  end
154
152
  end # class
155
-
156
153
  end # module
157
-
158
154
  # End of file
@@ -46,10 +46,10 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
46
46
  # @param aSymbol [Object] The symbol to append.
47
47
  def <<(aSymbol)
48
48
  symbols << aSymbol
49
- if aSymbol.is_a?(ProductionRef)
50
- @memo_references ||= []
51
- @memo_references << aSymbol
52
- end
49
+ return unless aSymbol.is_a?(ProductionRef)
50
+
51
+ @memo_references ||= []
52
+ @memo_references << aSymbol
53
53
  end
54
54
 
55
55
  # Retrieve the element from the sequence at given position.
@@ -71,8 +71,8 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
71
71
  same = symbols == other.symbols
72
72
  when Array
73
73
  same = symbols == other
74
- else
75
- same = false
74
+ else
75
+ same = false
76
76
  end
77
77
 
78
78
  return same
@@ -176,7 +176,5 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
176
176
  @memo_references = nil
177
177
  @lookup_references = nil
178
178
  end
179
-
180
179
  end # class
181
-
182
180
  end # module
@@ -4,13 +4,11 @@ require_relative '../spec_helper'
4
4
  require_relative '../../lib/sequitur/digram'
5
5
 
6
6
  module Sequitur # Re-open the module to get rid of qualified names
7
-
8
7
  describe Digram do
9
8
  let(:two_symbols) { [:b, :c] }
10
9
  let(:production) { double('sample-production') }
11
10
 
12
11
  context 'Standard creation & initialization:' do
13
-
14
12
  it 'should be created with 3 arguments' do
15
13
  instance = Digram.new(:b, :c, production)
16
14
 
@@ -30,11 +28,9 @@ describe Digram do
30
28
  instance1 = Digram.new(:a, :b, production)
31
29
  expect(instance1).not_to be_repeating
32
30
  end
33
-
34
31
  end # context
35
32
 
36
33
  context 'Provided services:' do
37
-
38
34
  it 'should compare itself to another digram' do
39
35
  instance1 = Digram.new(:a, :b, production)
40
36
  same = Digram.new(:a, :b, production)
@@ -45,12 +41,8 @@ describe Digram do
45
41
  expect(instance1).not_to eq(different)
46
42
  expect(same).not_to eq(different)
47
43
  end
48
-
49
44
  end # context
50
-
51
-
52
45
  end # describe
53
-
54
46
  end # module
55
47
 
56
48
  # End of file
@@ -1,159 +1,144 @@
1
- require_relative '../spec_helper'
2
-
3
- # Load the class under test
4
- require_relative '../../lib/sequitur/dynamic_grammar'
5
-
6
- module Sequitur # Re-open the module to get rid of qualified names
7
-
8
- describe DynamicGrammar do
9
- # Factory method. Build a production with the given sequence
10
- # of symbols as its rhs.
11
- def build_production(*symbols)
12
- prod = Production.new
13
- symbols.each { |symb| prod.append_symbol(symb) }
14
- return prod
15
- end
16
-
17
- let(:p_a) { build_production(:a) }
18
- let(:p_b) { build_production(:b) }
19
- let(:p_c) { build_production(:c) }
20
- let(:p_bc) { build_production(p_b, p_c) }
21
-
22
-
23
- context 'Creation & initialization:' do
24
-
25
- it 'should be created without parameter' do
26
- expect { DynamicGrammar.new }.not_to raise_error
27
- end
28
-
29
- it 'should have an empty start/start production' do
30
- expect(subject.start).to be_empty
31
- expect(subject.productions.size).to eq(1)
32
- expect(subject.productions.first).to be_empty
33
- end
34
-
35
- end # context
36
-
37
-
38
- context 'Adding productions to the grammar:' do
39
- it 'should add a simple production' do
40
- subject.add_production(p_a)
41
- expect(subject.productions.size).to eq(2)
42
- expect(subject.productions.last).to eq(p_a)
43
-
44
- # Error: p_b, p_c not in grammar
45
- expect { add_production(p_bc) }.to raise_error(StandardError)
46
-
47
- subject.add_production(p_b)
48
- expect(subject.productions.size).to eq(3)
49
- expect(subject.productions.last).to eq(p_b)
50
-
51
- # Error: p_c not in grammar
52
- expect { add_production(p_bc) }.to raise_error(StandardError)
53
-
54
- subject.add_production(p_c)
55
- expect(subject.productions.size).to eq(4)
56
- expect(subject.productions.last).to eq(p_c)
57
-
58
- subject.add_production(p_bc)
59
- expect(subject.productions.size).to eq(5)
60
- expect(subject.productions.last).to eq(p_bc)
61
- end
62
-
63
- end # context
64
-
65
-
66
- context 'Removing a production from the grammar:' do
67
- it 'should remove an existing production' do
68
- subject.add_production(p_a) # index = 1
69
- subject.add_production(p_b) # index = 2
70
- subject.add_production(p_c) # index = 3
71
- subject.add_production(p_bc) # index = 4
72
- expect(subject.productions.size).to eq(5)
73
-
74
- expect(p_a.refcount).to eq(0)
75
- expect(p_b.refcount).to eq(1)
76
- expect(p_c.refcount).to eq(1)
77
-
78
- subject.remove_production(1) # 1 => p_a
79
- expect(subject.productions.size).to eq(4)
80
- expect(p_b.refcount).to eq(1)
81
- expect(p_c.refcount).to eq(1)
82
- expect(subject.productions).not_to include(p_a)
83
-
84
- subject.remove_production(3) # 3 => p_bc
85
-
86
- expect(subject.productions.size).to eq(3)
87
- expect(p_b.refcount).to eq(0)
88
- expect(p_c.refcount).to eq(0)
89
- expect(subject.productions).not_to include(p_bc)
90
- end
91
-
92
- end # context
93
-
94
- context 'Visiting:' do
95
- it 'should return a visitor' do
96
- expect { subject.visitor }.not_to raise_error
97
- expect(subject.visitor).to be_kind_of(GrammarVisitor)
98
- end
99
-
100
- it 'should accept a visitor' do
101
- subject.add_production(p_a) # index = 1
102
- subject.add_production(p_b) # index = 2
103
- subject.add_production(p_c) # index = 3
104
- subject.add_production(p_bc) # index = 4
105
-
106
- a_visitor = subject.visitor
107
- fake_formatter = double('fake-formatter')
108
- a_visitor.subscribe(fake_formatter)
109
-
110
- expect(fake_formatter).to receive(:before_grammar).with(subject).ordered
111
- expect(fake_formatter).to receive(:before_production)
112
- .with(subject.start).ordered
113
- expect(fake_formatter).to receive(:before_rhs)
114
- .with(subject.start.rhs).ordered
115
- expect(fake_formatter).to receive(:after_rhs)
116
- .with(subject.start.rhs).ordered
117
- expect(fake_formatter).to receive(:after_production).with(subject.start)
118
- expect(fake_formatter).to receive(:before_production).with(p_a)
119
- expect(fake_formatter).to receive(:before_rhs).with(p_a.rhs)
120
- expect(fake_formatter).to receive(:after_rhs).with(p_a.rhs)
121
- expect(fake_formatter).to receive(:after_production).with(p_a)
122
- expect(fake_formatter).to receive(:before_production).with(p_b)
123
- expect(fake_formatter).to receive(:before_rhs).with(p_b.rhs)
124
- expect(fake_formatter).to receive(:after_rhs).with(p_b.rhs)
125
- expect(fake_formatter).to receive(:after_production).with(p_b)
126
- expect(fake_formatter).to receive(:before_production).with(p_c)
127
- expect(fake_formatter).to receive(:before_rhs).with(p_c.rhs)
128
- expect(fake_formatter).to receive(:after_rhs).with(p_c.rhs)
129
- expect(fake_formatter).to receive(:after_production).with(p_c)
130
- expect(fake_formatter).to receive(:before_production).with(p_bc)
131
- expect(fake_formatter).to receive(:before_rhs).with(p_bc.rhs)
132
- expect(fake_formatter).to receive(:after_rhs).with(p_bc.rhs)
133
- expect(fake_formatter).to receive(:after_production).with(p_bc)
134
- expect(fake_formatter).to receive(:after_grammar).with(subject)
135
- subject.send(:accept, a_visitor)
136
- end
137
- end # context
138
-
139
-
140
- context 'Generating a text representation of itself:' do
141
-
142
- it 'should generate a text representation when empty' do
143
- expectation = "#{subject.start.object_id} : ."
144
- expect(subject.to_string).to eq(expectation)
145
- end
146
-
147
- # it 'should generate a text representation of a simple production' do
148
- # instance = SequiturGrammar.new([:a].to_enum)
149
- # expectation = "#{instance.start.object_id} : a."
150
- # expect(instance.to_string).to eq(expectation)
151
- # end
152
-
153
- end # context
154
-
155
- end # describe
156
-
157
- end # module
158
-
159
- # End of file
1
+ require_relative '../spec_helper'
2
+
3
+ # Load the class under test
4
+ require_relative '../../lib/sequitur/dynamic_grammar'
5
+
6
+ module Sequitur # Re-open the module to get rid of qualified names
7
+ describe DynamicGrammar do
8
+ # Factory method. Build a production with the given sequence
9
+ # of symbols as its rhs.
10
+ def build_production(*symbols)
11
+ prod = Production.new
12
+ symbols.each { |symb| prod.append_symbol(symb) }
13
+ return prod
14
+ end
15
+
16
+ let(:p_a) { build_production(:a) }
17
+ let(:p_b) { build_production(:b) }
18
+ let(:p_c) { build_production(:c) }
19
+ let(:p_bc) { build_production(p_b, p_c) }
20
+
21
+
22
+ context 'Creation & initialization:' do
23
+ it 'should be created without parameter' do
24
+ expect { DynamicGrammar.new }.not_to raise_error
25
+ end
26
+
27
+ it 'should have an empty start/start production' do
28
+ expect(subject.start).to be_empty
29
+ expect(subject.productions.size).to eq(1)
30
+ expect(subject.productions.first).to be_empty
31
+ end
32
+ end # context
33
+
34
+
35
+ context 'Adding productions to the grammar:' do
36
+ it 'should add a simple production' do
37
+ subject.add_production(p_a)
38
+ expect(subject.productions.size).to eq(2)
39
+ expect(subject.productions.last).to eq(p_a)
40
+
41
+ # Error: p_b, p_c not in grammar
42
+ expect { add_production(p_bc) }.to raise_error(StandardError)
43
+
44
+ subject.add_production(p_b)
45
+ expect(subject.productions.size).to eq(3)
46
+ expect(subject.productions.last).to eq(p_b)
47
+
48
+ # Error: p_c not in grammar
49
+ expect { add_production(p_bc) }.to raise_error(StandardError)
50
+
51
+ subject.add_production(p_c)
52
+ expect(subject.productions.size).to eq(4)
53
+ expect(subject.productions.last).to eq(p_c)
54
+
55
+ subject.add_production(p_bc)
56
+ expect(subject.productions.size).to eq(5)
57
+ expect(subject.productions.last).to eq(p_bc)
58
+ end
59
+ end # context
60
+
61
+
62
+ context 'Removing a production from the grammar:' do
63
+ it 'should remove an existing production' do
64
+ subject.add_production(p_a) # index = 1
65
+ subject.add_production(p_b) # index = 2
66
+ subject.add_production(p_c) # index = 3
67
+ subject.add_production(p_bc) # index = 4
68
+ expect(subject.productions.size).to eq(5)
69
+
70
+ expect(p_a.refcount).to eq(0)
71
+ expect(p_b.refcount).to eq(1)
72
+ expect(p_c.refcount).to eq(1)
73
+
74
+ subject.remove_production(1) # 1 => p_a
75
+ expect(subject.productions.size).to eq(4)
76
+ expect(p_b.refcount).to eq(1)
77
+ expect(p_c.refcount).to eq(1)
78
+ expect(subject.productions).not_to include(p_a)
79
+
80
+ subject.remove_production(3) # 3 => p_bc
81
+
82
+ expect(subject.productions.size).to eq(3)
83
+ expect(p_b.refcount).to eq(0)
84
+ expect(p_c.refcount).to eq(0)
85
+ expect(subject.productions).not_to include(p_bc)
86
+ end
87
+ end # context
88
+
89
+ context 'Visiting:' do
90
+ it 'should return a visitor' do
91
+ expect { subject.visitor }.not_to raise_error
92
+ expect(subject.visitor).to be_kind_of(GrammarVisitor)
93
+ end
94
+
95
+ it 'should accept a visitor' do
96
+ subject.add_production(p_a) # index = 1
97
+ subject.add_production(p_b) # index = 2
98
+ subject.add_production(p_c) # index = 3
99
+ subject.add_production(p_bc) # index = 4
100
+
101
+ a_visitor = subject.visitor
102
+ fake_formatter = double('fake-formatter')
103
+ a_visitor.subscribe(fake_formatter)
104
+
105
+ expect(fake_formatter).to receive(:before_grammar).with(subject).ordered
106
+ expect(fake_formatter).to receive(:before_production)
107
+ .with(subject.start).ordered
108
+ expect(fake_formatter).to receive(:before_rhs)
109
+ .with(subject.start.rhs).ordered
110
+ expect(fake_formatter).to receive(:after_rhs)
111
+ .with(subject.start.rhs).ordered
112
+ expect(fake_formatter).to receive(:after_production).with(subject.start)
113
+ expect(fake_formatter).to receive(:before_production).with(p_a)
114
+ expect(fake_formatter).to receive(:before_rhs).with(p_a.rhs)
115
+ expect(fake_formatter).to receive(:after_rhs).with(p_a.rhs)
116
+ expect(fake_formatter).to receive(:after_production).with(p_a)
117
+ expect(fake_formatter).to receive(:before_production).with(p_b)
118
+ expect(fake_formatter).to receive(:before_rhs).with(p_b.rhs)
119
+ expect(fake_formatter).to receive(:after_rhs).with(p_b.rhs)
120
+ expect(fake_formatter).to receive(:after_production).with(p_b)
121
+ expect(fake_formatter).to receive(:before_production).with(p_c)
122
+ expect(fake_formatter).to receive(:before_rhs).with(p_c.rhs)
123
+ expect(fake_formatter).to receive(:after_rhs).with(p_c.rhs)
124
+ expect(fake_formatter).to receive(:after_production).with(p_c)
125
+ expect(fake_formatter).to receive(:before_production).with(p_bc)
126
+ expect(fake_formatter).to receive(:before_rhs).with(p_bc.rhs)
127
+ expect(fake_formatter).to receive(:after_rhs).with(p_bc.rhs)
128
+ expect(fake_formatter).to receive(:after_production).with(p_bc)
129
+ expect(fake_formatter).to receive(:after_grammar).with(subject)
130
+ subject.send(:accept, a_visitor)
131
+ end
132
+ end # context
133
+
134
+
135
+ context 'Generating a text representation of itself:' do
136
+ it 'should generate a text representation when empty' do
137
+ expectation = "#{subject.start.object_id} : ."
138
+ expect(subject.to_string).to eq(expectation)
139
+ end
140
+ end # context
141
+ end # describe
142
+ end # module
143
+
144
+ # End of file