rley 0.3.05 → 0.3.06

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29bd8f0b4ab6dacef0a6086f91ccd464b0417aa5
4
- data.tar.gz: ee3d9fde440b5936350b3cfc0779694eac4bc924
3
+ metadata.gz: 1bbd7b9c764c5f24a73b8f3f158e6c25f6f7ccd6
4
+ data.tar.gz: 63676212ceb56eb1b09f511a6fade48abcd7e3ab
5
5
  SHA512:
6
- metadata.gz: cd2d999e9d1534d11106b86139a87570a250ed7f3c7d525e4cc518bc2e023252e097ce4bd2f550a745d113551856765fc4ac7a45e318da640fca3a42f38fef91
7
- data.tar.gz: 63f1f1bef8272d05da2cf35fb7f4030c6c9c6e8d0e666151e95be7867317b946c88d8591025b7fdc0f496d381eca6c164e9217c6f11891a979a2eb02ea6441d5
6
+ metadata.gz: 2a17d1c3447e72f59f4f8268b7e90ccfda098fb0769b73219866d42fa77095e2e06f6bc980e6b0e5928ca1217c9c1eb8b5b973ff12b511fa3327745353caf5bd
7
+ data.tar.gz: e03b4dc4cebf8fca9049e367641248601850398ed77a725ab92e3cb22f2552224dc143a8121d142f0e38522a5cd1dc5ef570341542d0b39845a3ab7b02596a97
@@ -59,7 +59,7 @@ MethodLength:
59
59
  Max: 50
60
60
  CountComments: false
61
61
 
62
- # Avoid modules longer than 500 lines of code
62
+ # Avoid modules longer than 700 lines of code
63
63
  ModuleLength:
64
64
  Max: 700
65
65
 
@@ -1,3 +1,11 @@
1
+ ### 0.3.06 / 2016-11-06
2
+ * [FIX] There were missing links to shared parse forest nodes for ambiguous parses.
3
+ * [NEW] RSpec file `ambiguous_parse_spec.rb` added in order to test the parse forest building for an ambiguous parse.
4
+ * [CHANGE] Attribute `ParseWalkerContext#nterm2start`: previous implementation assumed -wrongly- that for each non terminal there was only one start entry.
5
+ Now this attribute uses nested hashes as data structure in order to disambiguate the mapping.
6
+ * [CHANGE] Method `ParseWalkerFactory#visit_entry` updated to reflect change in the `ParseWalkerContext#nterm2start` attribute.
7
+ * [CHANGE] Method `ParseWalkerFactory#visit_entry` now emits an event if an item entry is re-visited (previously, no such event were generated)
8
+
1
9
  ### 0.3.05 / 2016-11-01
2
10
  * [CHANGE] Code re-styling to please Rubocop 0.45.0: only 2 offences remain (from a few hundreds!)
3
11
 
data/Gemfile CHANGED
@@ -4,6 +4,6 @@ source 'https://rubygems.org'
4
4
  group :development do
5
5
  gem 'rake', '>= 10.0.0'
6
6
  gem 'rspec', '>= 3.5.0'
7
- gem 'simplecov', '>= 0.8.0'
7
+ gem 'simplecov', '>= 0.1.0'
8
8
  gem 'coveralls', '>= 0.7.0'
9
9
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Rley # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.3.05'.freeze
6
+ Version = '0.3.06'.freeze
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = "Ruby implementation of the Earley's parsing algorithm".freeze
@@ -12,7 +12,8 @@ module Rley # This module is used as a namespace
12
12
  :curr_entry, # Parse entry currently being visited
13
13
  :entry_set_index, # Sigma set index of current parse entry
14
14
  :visitees, # The set of already visited parse entries
15
- :nterm2start, # A Hash non-terminal symbol => start entry
15
+ :nterm2start, # Nested hashes. Pairs of first level are of the form:
16
+ # non-terminal symbol => { index(=origin) => start entry }
16
17
  :return_stack, # A stack of parse entries
17
18
  :backtrack_points
18
19
  )
@@ -76,26 +77,42 @@ module Rley # This module is used as a namespace
76
77
  context.entry_set_index = maxIndex
77
78
  context.curr_entry = acceptingEntry
78
79
  context.visitees = Set.new
79
- context.nterm2start = {}
80
+ context.nterm2start = init_nterm2start
80
81
  context.return_stack = []
81
82
  context.backtrack_points = []
82
83
 
83
84
  return context
84
85
  end
86
+
87
+
88
+ # Initialize the non-terminal to start entry mapping
89
+ def init_nterm2start()
90
+ h = Hash.new do |hsh, defval|
91
+ entry, index = defval
92
+ nonterm = entry.vertex.non_terminal
93
+ if hsh.include? nonterm
94
+ pre = hsh[nonterm]
95
+ pre[index] = entry
96
+ else
97
+ hsh[nonterm] = { index => entry }
98
+ end
99
+ end
100
+
101
+ return h
102
+ end
85
103
 
86
104
  # [event, entry, index, vertex]
87
105
  def visit_entry(anEntry, aContext)
88
106
  index = aContext.entry_set_index
89
107
 
90
- if anEntry.start_entry?
91
- aContext.nterm2start[anEntry.vertex.non_terminal] = anEntry
92
- end
108
+ aContext.nterm2start[[anEntry, index]] if anEntry.start_entry?
93
109
 
94
110
  if aContext.visitees.include?(anEntry) # Already visited?...
95
111
  case anEntry.vertex
96
112
  when GFG::EndVertex
97
113
  # Jump to related start entry...
98
- new_entry = aContext.nterm2start[anEntry.vertex.non_terminal]
114
+ pairs = aContext.nterm2start[anEntry.vertex.non_terminal]
115
+ new_entry = pairs[anEntry.origin]
99
116
  aContext.curr_entry = new_entry
100
117
  aContext.entry_set_index = new_entry.origin
101
118
  event = [:revisit, anEntry, index]
@@ -105,7 +122,7 @@ module Rley # This module is used as a namespace
105
122
 
106
123
  when GFG::ItemVertex
107
124
  # Skip item entries while revisiting
108
- event = nil
125
+ event = [:revisit, anEntry, index]
109
126
  else
110
127
  raise NotImplementedError
111
128
  end
@@ -0,0 +1,276 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ require_relative '../../../lib/rley/parser/gfg_earley_parser'
4
+ require_relative '../../../lib/rley/parser/parse_walker_factory'
5
+
6
+ require_relative '../support/grammar_helper'
7
+ require_relative '../support/expectation_helper'
8
+ require_relative '../support/grammar_ambig01_helper'
9
+
10
+ # Load the class under test
11
+ require_relative '../../../lib/rley/parser/parse_forest_builder'
12
+
13
+ module Rley # Open this namespace to avoid module qualifier prefixes
14
+ module Parser
15
+ describe 'Coping with ambiguous grammar' do
16
+ include GrammarHelper # Mix-in with token factory method
17
+ include ExpectationHelper # Mix-in with expectation on parse entry sets
18
+
19
+ # Emit a text representation of the current path.
20
+ def path_to_s()
21
+ text_parts = subject.curr_path.map do |path_element|
22
+ path_element.to_string(0)
23
+ end
24
+ return text_parts.join('/')
25
+ end
26
+
27
+ def next_event(eventType, anEntryText)
28
+ event = @walker.next
29
+ subject.receive_event(*event)
30
+ expect(event[0]).to eq(eventType)
31
+ expect(event[1].to_s).to eq(anEntryText)
32
+ end
33
+
34
+ def expected_curr_parent(anExpectation)
35
+ expect(subject.curr_parent.to_string(0)).to eq(anExpectation)
36
+ end
37
+
38
+ def expected_curr_path(anExpectation)
39
+ expect(path_to_s).to eq(anExpectation)
40
+ end
41
+
42
+ def expected_first_child(anExpectation)
43
+ child = subject.curr_parent.subnodes.first
44
+ expect(child.to_string(0)).to eq(anExpectation)
45
+ end
46
+
47
+ before(:each) do
48
+ factory = ParseWalkerFactory.new
49
+ accept_entry = sentence_result.accepting_entry
50
+ accept_index = sentence_result.chart.last_index
51
+ @walker = factory.build_walker(accept_entry, accept_index)
52
+ end
53
+
54
+ context 'Ambiguous expression' do
55
+ include GrammarAmbig01Helper
56
+
57
+ let(:grammar_ambig01) do
58
+ builder = grammar_ambig01_builder
59
+ builder.grammar
60
+ end
61
+
62
+ let(:expr_tokens) do
63
+ sentence = '2 + 3 * 4'
64
+ tokenizer_ambig01(sentence, grammar_ambig01)
65
+ end
66
+
67
+ let(:sentence_result) do
68
+ parser = Parser::GFGEarleyParser.new(grammar_ambig01)
69
+ parser.parse(expr_tokens)
70
+ end
71
+
72
+ subject { ParseForestBuilder.new(expr_tokens) }
73
+
74
+ it 'should handle walker events' do
75
+ next_event(:visit, 'P. | 0') # Event 1
76
+ expected_curr_path('P[0, 5]')
77
+
78
+ next_event(:visit, 'P => S . | 0') # Event 2
79
+ expected_curr_path('P[0, 5]')
80
+
81
+ next_event(:visit, 'S. | 0') # Event 3
82
+ expected_curr_path('P[0, 5]/S[0, 5]')
83
+
84
+ next_event(:visit, 'S => S * S . | 0') # Event 4
85
+ expected_curr_path('P[0, 5]/S[0, 5]/Alt(S => S * S .)[0, 5]')
86
+
87
+ next_event(:visit, 'S. | 4') # Event 5
88
+ path_prefix = 'P[0, 5]/S[0, 5]/Alt(S => S * S .)[0, 5]'
89
+ expected_curr_path(path_prefix + '/S[4, 5]')
90
+
91
+ next_event(:visit, 'S => L . | 4') # Event 6
92
+ expected_path5 = path_prefix + '/S[4, 5]'
93
+ expect(path_to_s).to eq(expected_path5)
94
+
95
+ next_event(:visit, 'L. | 4') # Event 7
96
+ expected_curr_path(path_prefix + '/S[4, 5]/L[4, 5]')
97
+
98
+ next_event(:visit, 'L => integer . | 4') # Event 8
99
+ expected_curr_path(path_prefix + '/S[4, 5]/L[4, 5]')
100
+ expected_first_child('integer[4, 5]')
101
+
102
+ next_event(:visit, 'L => . integer | 4') # Event 9
103
+ expected_curr_path(path_prefix + '/S[4, 5]/L[4, 5]')
104
+
105
+ next_event(:visit, '.L | 4') # Event 10
106
+ expected_curr_path(path_prefix + '/S[4, 5]')
107
+
108
+ next_event(:visit, 'S => . L | 4') # Event 11
109
+ expected_curr_parent('S[4, 5]')
110
+ expected_curr_path(path_prefix + '/S[4, 5]')
111
+
112
+ next_event(:visit, '.S | 4') # Event 12
113
+ expected_curr_parent('Alt(S => S * S .)[0, 5]')
114
+ expected_curr_path(path_prefix)
115
+
116
+ next_event(:visit, 'S => S * . S | 0') # Event 13
117
+ expected_curr_path(path_prefix)
118
+ expected_first_child('*[3, 4]')
119
+
120
+ next_event(:visit, 'S => S . * S | 0') # Event 14
121
+ expected_curr_path(path_prefix)
122
+
123
+ next_event(:visit, 'S. | 0') # Event 15
124
+ expected_curr_path(path_prefix + '/S[0, 3]')
125
+
126
+ next_event(:visit, 'S => S + S . | 0') # Event 16
127
+ expected_curr_parent('S[0, 3]')
128
+ expected_curr_path(path_prefix + '/S[0, 3]')
129
+
130
+ next_event(:visit, 'S. | 2') # Event 17
131
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]')
132
+
133
+ next_event(:visit, 'S => L . | 2') # Event 18
134
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]')
135
+
136
+ next_event(:visit, 'L. | 2') # Event 19
137
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]/L[2, 3]')
138
+
139
+ next_event(:visit, 'L => integer . | 2') # Event 20
140
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]/L[2, 3]')
141
+ expected_first_child('integer[2, 3]')
142
+
143
+ next_event(:visit, 'L => . integer | 2') # Event 21
144
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]/L[2, 3]')
145
+
146
+ next_event(:visit, '.L | 2') # Event 22
147
+ expected_curr_parent('S[2, 3]')
148
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]')
149
+
150
+ next_event(:visit, 'S => . L | 2') # Event 23
151
+ expected_curr_path(path_prefix + '/S[0, 3]/S[2, 3]')
152
+
153
+ next_event(:visit, '.S | 2') # Event 24
154
+ expected_curr_path(path_prefix + '/S[0, 3]')
155
+
156
+ next_event(:visit, 'S => S + . S | 0') # Event 24
157
+ expected_curr_path(path_prefix + '/S[0, 3]')
158
+ expected_first_child('+[1, 2]')
159
+
160
+ next_event(:visit, 'S => S . + S | 0') # Event 25
161
+ expected_curr_path(path_prefix + '/S[0, 3]')
162
+
163
+ next_event(:visit, 'S. | 0') # Event 27
164
+ expected_curr_parent('S[0, 1]')
165
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]')
166
+
167
+ next_event(:visit, 'S => L . | 0') # Event 28
168
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]')
169
+
170
+ next_event(:visit, 'L. | 0') # Event 29
171
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]/L[0, 1]')
172
+
173
+ next_event(:visit, 'L => integer . | 0') # Event 30
174
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]/L[0, 1]')
175
+ expected_first_child('integer[0, 1]')
176
+
177
+ next_event(:visit, 'L => . integer | 0') # Event 31
178
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]/L[0, 1]')
179
+
180
+ next_event(:visit, '.L | 0') # Event 32
181
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]')
182
+
183
+ next_event(:visit, 'S => . L | 0') # Event 33
184
+ expected_curr_path(path_prefix + '/S[0, 3]/S[0, 1]')
185
+
186
+ next_event(:visit, '.S | 0') # Event 34
187
+ expected_curr_path(path_prefix + '/S[0, 3]')
188
+
189
+ next_event(:visit, 'S => . S + S | 0') # Event 35
190
+ expected_curr_path(path_prefix + '/S[0, 3]')
191
+
192
+ next_event(:revisit, '.S | 0') # REVISIT Event 36
193
+ expected_curr_parent('Alt(S => S * S .)[0, 5]')
194
+ expected_curr_path(path_prefix)
195
+
196
+ next_event(:visit, 'S => . S * S | 0') # Event 37
197
+ expected_curr_path('P[0, 5]/S[0, 5]')
198
+
199
+ next_event(:revisit, '.S | 0') # REVISIT Event 38
200
+ expected_curr_path('P[0, 5]')
201
+
202
+ next_event(:visit, 'P => . S | 0') # Event 39
203
+ expected_curr_path('P[0, 5]')
204
+
205
+ next_event(:visit, '.P | 0') # Event 40
206
+ expected_curr_path('')
207
+
208
+ next_event(:backtrack, 'S. | 0') # BACKTRACK Event 41
209
+
210
+ expected_curr_path('P[0, 5]/S[0, 5]')
211
+
212
+ next_event(:visit, 'S => S + S . | 0') # Event 42
213
+ expected_curr_parent('Alt(S => S + S .)[0, 5]')
214
+ path_prefix = 'P[0, 5]/S[0, 5]/Alt(S => S + S .)[0, 5]'
215
+ expected_curr_path(path_prefix)
216
+
217
+ next_event(:visit, 'S. | 2') # Event 43
218
+ expected_curr_path(path_prefix + '/S[2, 5]')
219
+
220
+ next_event(:visit, 'S => S * S . | 2') # Event 44
221
+ expected_curr_path(path_prefix + '/S[2, 5]')
222
+
223
+ # Up to now everything was running OK.
224
+ # Next steps are going wrong...
225
+
226
+ next_event(:revisit, 'S. | 4') # Event 45
227
+ expected_curr_path(path_prefix + '/S[2, 5]')
228
+ expected_first_child('S[4, 5]')
229
+
230
+ next_event(:visit, 'S => S * . S | 2') # Event 46
231
+ expected_curr_path(path_prefix + '/S[2, 5]')
232
+ expected_first_child('*[3, 4]')
233
+
234
+ next_event(:visit, 'S => S . * S | 2') # Event 47
235
+ expected_curr_path(path_prefix + '/S[2, 5]')
236
+
237
+ next_event(:revisit, 'S. | 2') # Event 48
238
+ expected_curr_path(path_prefix + '/S[2, 5]')
239
+
240
+ next_event(:visit, 'S => . S * S | 2') # Event 49
241
+ expected_curr_path(path_prefix + '/S[2, 5]')
242
+
243
+ next_event(:revisit, '.S | 2') # Event 50
244
+ expected_curr_parent('Alt(S => S + S .)[0, 5]')
245
+ expected_curr_path(path_prefix)
246
+
247
+ # TODO: review previous and next steps...
248
+
249
+ next_event(:revisit, 'S => S + . S | 0') # Event 51
250
+ expected_curr_parent('Alt(S => S + S .)[0, 5]')
251
+ expected_curr_path(path_prefix)
252
+ expected_first_child('+[1, 2]')
253
+
254
+ next_event(:revisit, 'S => S . + S | 0') # Event 52
255
+ expected_curr_path(path_prefix)
256
+
257
+ next_event(:revisit, 'S. | 0') # Event 53
258
+ expected_curr_path('P[0, 5]/S[0, 5]/Alt(S => S + S .)[0, 5]')
259
+
260
+ next_event(:revisit, 'S => . S + S | 0') # Event 54
261
+ expected_curr_path('P[0, 5]/S[0, 5]')
262
+
263
+ next_event(:revisit, '.S | 0') # Event 55
264
+ expected_curr_path('P[0, 5]')
265
+
266
+ next_event(:revisit, 'P => . S | 0') # Event 56
267
+ expected_curr_path('P[0, 5]')
268
+
269
+ next_event(:revisit, '.P | 0') # Event 57
270
+ expected_curr_path('')
271
+ end
272
+ end # context
273
+ end # describe
274
+ end # module
275
+ end # module
276
+ # End of file
@@ -42,13 +42,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
42
42
  parser.parse(sample_tokens)
43
43
  end
44
44
 
45
- let(:walker) do
46
- factory = ParseWalkerFactory.new
47
- accept_entry = sample_result.accepting_entry
48
- accept_index = sample_result.chart.last_index
49
- factory.build_walker(accept_entry, accept_index)
50
- end
51
-
52
45
  subject { ParseForestBuilder.new(sample_tokens) }
53
46
 
54
47
  # Emit a text representation of the current path.
@@ -59,6 +52,25 @@ module Rley # Open this namespace to avoid module qualifier prefixes
59
52
  return text_parts.join('/')
60
53
  end
61
54
 
55
+ def next_event(eventType, anEntryText)
56
+ event = @walker.next
57
+ subject.receive_event(*event)
58
+ expect(event[0]).to eq(eventType)
59
+ expect(event[1].to_s).to eq(anEntryText)
60
+ end
61
+
62
+ def expected_curr_parent(anExpectation)
63
+ expect(subject.curr_parent.to_string(0)).to eq(anExpectation)
64
+ end
65
+
66
+ def expected_curr_path(anExpectation)
67
+ expect(path_to_s).to eq(anExpectation)
68
+ end
69
+
70
+ def expected_first_child(anExpectation)
71
+ child = subject.curr_parent.subnodes.first
72
+ expect(child.to_string(0)).to eq(anExpectation)
73
+ end
62
74
 
63
75
  context 'Initialization:' do
64
76
  it 'should be created with a sequence of tokens' do
@@ -75,355 +87,190 @@ module Rley # Open this namespace to avoid module qualifier prefixes
75
87
  end # context
76
88
 
77
89
  context 'Parse forest construction' do
90
+ before(:each) do
91
+ factory = ParseWalkerFactory.new
92
+ accept_entry = sample_result.accepting_entry
93
+ accept_index = sample_result.chart.last_index
94
+ @walker = factory.build_walker(accept_entry, accept_index)
95
+ end
96
+
78
97
  it 'should initialize the root node' do
79
- first_event = walker.next
80
- subject.receive_event(*first_event)
98
+ next_event(:visit, 'Phi. | 0')
81
99
  forest = subject.forest
82
100
 
83
101
  expect(forest.root.to_string(0)).to eq('Phi[0, 4]')
84
- expect(subject.curr_path).to eq([forest.root])
85
- expect(subject.entry2node[first_event[1]]).to eq(forest.root)
102
+ expected_curr_path('Phi[0, 4]')
86
103
  end
87
104
 
88
105
  it 'should initialize the first child of the root node' do
89
- event1 = walker.next
90
- subject.receive_event(*event1)
91
-
92
- event2 = walker.next
93
- subject.receive_event(*event2)
106
+ next_event(:visit, 'Phi. | 0') # Event 1
107
+ next_event(:visit, 'Phi => S . | 0') # Event 2
108
+ next_event(:visit, 'S. | 0') # Event 3
94
109
 
95
- event3 = walker.next
96
- subject.receive_event(*event3)
97
-
98
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
99
- expected_path3 = 'Phi[0, 4]/S[0, 4]'
100
- expect(path_to_s).to eq(expected_path3)
110
+ expected_curr_path('Phi[0, 4]/S[0, 4]')
101
111
  end
102
112
 
103
113
  it 'should build alternative node when detecting backtrack point' do
104
114
  3.times do
105
- event = walker.next
115
+ event = @walker.next
106
116
  subject.receive_event(*event)
107
117
  end
108
118
 
109
- event4 = walker.next
110
- subject.receive_event(*event4)
111
-
112
- parent_as_text = subject.curr_parent.to_string(0)
113
- expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
114
- expected_path4 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
115
- expect(path_to_s).to eq(expected_path4)
119
+ next_event(:visit, 'S => a T . | 0') # Event 4
120
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]')
116
121
  expect(subject.curr_path[-2].refinement).to eq(:or)
117
122
  end
118
123
 
119
124
  it 'should build token node when scan edge was detected' do
120
125
  4.times do
121
- event = walker.next
126
+ event = @walker.next
122
127
  subject.receive_event(*event)
123
128
  end
124
129
 
125
- event5 = walker.next
126
- subject.receive_event(*event5)
127
- expect(event5[1].to_s).to eq('T. | 1')
128
- expect(subject.curr_parent.to_string(0)).to eq('T[1, 4]')
129
- expected_path5 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]'
130
- expect(path_to_s).to eq(expected_path5)
130
+ next_event(:visit, 'T. | 1') # Event5
131
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]')
131
132
  expect(subject.curr_parent.subnodes).to be_empty
132
133
 
133
- event6 = walker.next
134
- subject.receive_event(*event6)
135
- expect(event6[1].to_s).to eq('T => b b b . | 1')
134
+ next_event(:visit, 'T => b b b . | 1') # Event 6
136
135
  expect(subject.curr_parent.to_string(0)).to eq('T[1, 4]')
137
- expected_path6 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]'
138
- expect(path_to_s).to eq(expected_path6)
136
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]')
139
137
  expect(subject.curr_parent.subnodes.size).to eq(1)
140
- token_event6 = 'b[3, 4]'
141
- child = subject.curr_parent.subnodes.first
142
- expect(child.to_string(0)).to eq(token_event6)
138
+ expected_first_child('b[3, 4]')
143
139
 
144
- event7 = walker.next
145
- subject.receive_event(*event7)
146
- expect(event7[1].to_s).to eq('T => b b . b | 1')
147
- expect(subject.curr_parent.to_string(0)).to eq('T[1, 4]')
148
- expected_path7 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]'
149
- expect(path_to_s).to eq(expected_path7)
140
+ next_event(:visit, 'T => b b . b | 1') # Event 7
141
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]')
150
142
  expect(subject.curr_parent.subnodes.size).to eq(2)
151
- token_event7 = 'b[2, 3]'
152
- child = subject.curr_parent.subnodes.first
153
- expect(child.to_string(0)).to eq(token_event7)
143
+ expected_first_child('b[2, 3]')
154
144
 
155
- event8 = walker.next
156
- subject.receive_event(*event8)
157
- expect(event8[1].to_s).to eq('T => b . b b | 1')
158
- expect(subject.curr_parent.to_string(0)).to eq('T[1, 4]')
159
- expected_path8 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]'
160
- expect(path_to_s).to eq(expected_path8)
145
+ next_event(:visit, 'T => b . b b | 1') # Event 8
146
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]')
161
147
  expect(subject.curr_parent.subnodes.size).to eq(3)
162
- token_event8 = 'b[1, 2]'
163
- child = subject.curr_parent.subnodes.first
164
- expect(child.to_string(0)).to eq(token_event8)
148
+ expected_first_child('b[1, 2]')
165
149
 
166
- event9 = walker.next
167
- subject.receive_event(*event9)
168
- expect(event9[1].to_s).to eq('T => . b b b | 1')
169
- expect(subject.curr_parent.to_string(0)).to eq('T[1, 4]')
170
- expected_path9 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]'
171
- expect(path_to_s).to eq(expected_path9)
172
-
173
- event10 = walker.next
174
- subject.receive_event(*event10)
175
- expect(event10[1].to_s).to eq('.T | 1')
176
- parent_as_text = subject.curr_parent.to_string(0)
177
- expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
178
- expected_path10 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
179
- expect(path_to_s).to eq(expected_path10)
180
-
181
- event11 = walker.next
182
- subject.receive_event(*event11)
183
- expect(event11[1].to_s).to eq('S => a . T | 0')
184
- parent_as_text = subject.curr_parent.to_string(0)
185
- expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
186
- expected_path11 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
187
- expect(path_to_s).to eq(expected_path11)
188
- expect(subject.curr_parent.subnodes.size).to eq(2)
189
- token_event11 = 'a[0, 1]'
190
- child = subject.curr_parent.subnodes.first
191
- expect(child.to_string(0)).to eq(token_event11)
150
+ next_event(:visit, 'T => . b b b | 1') # Event 9
151
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]/T[1, 4]')
152
+
153
+ next_event(:visit, '.T | 1') # Event 10
154
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]')
192
155
 
193
- event12 = walker.next
194
- subject.receive_event(*event12)
195
- expect(event12[1].to_s).to eq('S => . a T | 0')
156
+ next_event(:visit, 'S => a . T | 0') # Event 11
157
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]')
158
+ expect(subject.curr_parent.subnodes.size).to eq(2)
159
+ expected_first_child('a[0, 1]')
196
160
 
161
+ next_event(:visit, 'S => . a T | 0') # Event 12
197
162
  # Alternate node is popped
198
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
199
- expected_path12 = 'Phi[0, 4]/S[0, 4]'
200
- expect(path_to_s).to eq(expected_path12)
201
-
202
- event13 = walker.next
203
- subject.receive_event(*event13)
204
- expect(event13[1].to_s).to eq('.S | 0')
205
- expect(subject.curr_parent.to_string(0)).to eq('Phi[0, 4]')
206
- expected_path13 = 'Phi[0, 4]'
207
- expect(path_to_s).to eq(expected_path13)
208
-
209
- event14 = walker.next
210
- subject.receive_event(*event14)
211
- expect(event14[1].to_s).to eq('Phi => . S | 0')
212
- expect(subject.curr_parent.to_string(0)).to eq('Phi[0, 4]')
213
- expected_path14 = 'Phi[0, 4]'
214
- expect(path_to_s).to eq(expected_path14)
215
-
216
- event15 = walker.next
217
- subject.receive_event(*event15)
218
- expect(event15[1].to_s).to eq('.Phi | 0')
163
+ expected_curr_path('Phi[0, 4]/S[0, 4]')
164
+
165
+ next_event(:visit, '.S | 0') # Event 13
166
+ expected_curr_path('Phi[0, 4]')
167
+
168
+ next_event(:visit, 'Phi => . S | 0') # Event 14
169
+ expected_curr_path('Phi[0, 4]')
170
+
171
+ next_event(:visit, '.Phi | 0') # Event 15
219
172
  expect(path_to_s).to be_empty
220
173
  end
221
174
 
222
175
  it 'should handle backtracking' do
223
176
  15.times do
224
- event = walker.next
177
+ event = @walker.next
225
178
  subject.receive_event(*event)
226
179
  end
227
180
 
228
- event16 = walker.next
229
- subject.receive_event(*event16)
230
- expect(event16[0]).to eq(:backtrack) # Backtrack event!
231
- expect(event16[1].to_s).to eq('S. | 0')
232
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
233
- expected_path16 = 'Phi[0, 4]/S[0, 4]'
234
- expect(path_to_s).to eq(expected_path16)
181
+ # Backtracking is occurring
182
+ next_event(:backtrack, 'S. | 0') # Event 16
183
+ expected_curr_path('Phi[0, 4]/S[0, 4]')
235
184
 
236
185
  # Alternate node should be created
237
- event17 = walker.next
238
- subject.receive_event(*event17)
239
- expect(event17[1].to_s).to eq('S => A T . | 0')
240
- parent_as_text = subject.curr_parent.to_string(0)
241
- expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
242
- expected_path17 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
243
- expect(path_to_s).to eq(expected_path17)
186
+ next_event(:visit, 'S => A T . | 0') # Event 17
187
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]')
244
188
  expect(subject.curr_path[-2].refinement).to eq(:or)
245
189
  end
246
190
 
247
191
  it 'should detect second time visit of an entry' do
248
192
  17.times do
249
- event = walker.next
193
+ event = @walker.next
250
194
  subject.receive_event(*event)
251
195
  end
252
196
 
253
- event18 = walker.next
254
- subject.receive_event(*event18)
255
- expect(event18[0]).to eq(:revisit) # Revisit event!
256
- expect(event18[1].to_s).to eq('T. | 1')
257
- parent_as_text = subject.curr_parent.to_string(0)
258
- expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
259
- expected_path18 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
260
- expect(path_to_s).to eq(expected_path18)
261
-
262
- event19 = walker.next
263
- subject.receive_event(*event19)
264
- expect(event19[1].to_s).to eq('S => A . T | 0')
265
- parent_as_text = subject.curr_parent.to_string(0)
266
- expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
267
- expected_path19 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
268
- expect(path_to_s).to eq(expected_path19)
269
-
270
- event20 = walker.next
271
- subject.receive_event(*event20)
272
- # Next entry is an end entry...
273
- expect(event20[1].to_s).to eq('A. | 0')
274
- expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
275
- expected_path20 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
276
- expect(path_to_s).to eq(expected_path20)
197
+ next_event(:revisit, 'T. | 1') # REVISIT Event 18
198
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]')
277
199
 
200
+ next_event(:visit, 'S => A . T | 0') # Event 19
201
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]')
278
202
 
279
- event21 = walker.next
280
- subject.receive_event(*event21)
281
- expect(event21[1].to_s).to eq('A => a . | 0')
282
- parent_as_text = subject.curr_parent.to_string(0)
283
- expect(parent_as_text).to eq('Alt(A => a .)[0, 1]')
203
+ next_event(:visit, 'A. | 0') # Event 20
204
+ expected_path20 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
205
+ expected_curr_path(expected_path20)
284
206
  path_prefix = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/'
285
- expected_path21 = path_prefix + 'Alt(A => a .)[0, 1]'
286
- expect(path_to_s).to eq(expected_path21)
207
+
208
+ next_event(:visit, 'A => a . | 0') # Event 21
209
+ expected_curr_path(path_prefix + 'Alt(A => a .)[0, 1]')
287
210
  expect(subject.curr_path[-2].refinement).to eq(:or)
288
211
 
289
- event22 = walker.next
290
- subject.receive_event(*event22)
291
- expect(event22[1].to_s).to eq('A => . a | 0')
292
- expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
293
- expected_path22 = expected_path20
294
- expect(path_to_s).to eq(expected_path22)
295
-
296
- event23 = walker.next
297
- subject.receive_event(*event23)
298
- expect(event23[1].to_s).to eq('.A | 0')
299
- parent_as_text = subject.curr_parent.to_string(0)
300
- expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
301
- expected_path23 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
302
- expect(path_to_s).to eq(expected_path23)
303
-
304
- event24 = walker.next
305
- subject.receive_event(*event24)
306
- expect(event24[1].to_s).to eq('S => . A T | 0')
307
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
308
- expected_path24 = 'Phi[0, 4]/S[0, 4]'
309
- expect(path_to_s).to eq(expected_path24)
310
-
311
- event25 = walker.next
312
- subject.receive_event(*event25)
313
- expect(event25[0]).to eq(:revisit) # Revisit event!
314
- expect(event25[1].to_s).to eq('.S | 0')
315
- expect(subject.curr_parent.to_string(0)).to eq('Phi[0, 4]')
316
- expected_path25 = 'Phi[0, 4]'
317
- expect(path_to_s).to eq(expected_path25)
318
-
319
- event26 = walker.next
320
- subject.receive_event(*event26)
321
- expect(event26[0]).to eq(:revisit) # Revisit event!
322
- expect(event26[1].to_s).to eq('.Phi | 0')
323
- expected_path26 = ''
324
- expect(path_to_s).to eq(expected_path26)
212
+ next_event(:visit, 'A => . a | 0') # Event 22
213
+ expected_curr_path(expected_path20)
214
+
215
+ next_event(:visit, '.A | 0') # Event 23
216
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]')
217
+
218
+ next_event(:visit, 'S => . A T | 0') # Event 24
219
+ expected_curr_path('Phi[0, 4]/S[0, 4]')
220
+
221
+ next_event(:revisit, '.S | 0') # REVISIT event 25
222
+ expected_curr_path('Phi[0, 4]')
223
+
224
+ next_event(:revisit, 'Phi => . S | 0') # REVISIT event 26
225
+ expected_curr_path('Phi[0, 4]')
226
+
227
+ next_event(:revisit, '.Phi | 0') # REVISIT event 27
228
+ expected_curr_path('')
325
229
  end
326
230
 
327
- it 'should handle remaining events' do
328
- 26.times do
329
- event = walker.next
231
+ it 'should handle remaining # Events' do
232
+ 27.times do
233
+ event = @walker.next
330
234
  subject.receive_event(*event)
331
235
  end
332
236
 
333
- event27 = walker.next
334
- subject.receive_event(*event27)
335
- expect(event27[0]).to eq(:backtrack) # Backtrack event!
336
- expect(event27[1].to_s).to eq('A. | 0')
337
- expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
338
- expected_path27 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
339
- expect(path_to_s).to eq(expected_path27)
340
-
341
- event28 = walker.next
342
- subject.receive_event(*event28)
343
- expect(event28[0]).to eq(:visit)
344
- expect(event28[1].to_s).to eq('A => B A . | 0')
345
- parent_as_text = subject.curr_parent.to_string(0)
346
- expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
237
+ # Backtracking is occurring
238
+ next_event(:backtrack, 'A. | 0') # BACKTRACK Event 28
239
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]')
240
+
347
241
  path_prefix = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/'
348
- expected_path28 = path_prefix + 'Alt(A => B A .)[0, 1]'
349
- expect(path_to_s).to eq(expected_path28)
350
-
351
- event29 = walker.next
352
- subject.receive_event(*event29)
353
- expect(event29[0]).to eq(:revisit) # Revisit event!
354
- expect(event29[1].to_s).to eq('A. | 0')
355
- parent_as_text = subject.curr_parent.to_string(0)
356
- expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
357
- expected_path29 = path_prefix + 'Alt(A => B A .)[0, 1]'
358
- expect(path_to_s).to eq(expected_path29)
359
-
360
- event30 = walker.next
361
- subject.receive_event(*event30)
362
- expect(event30[0]).to eq(:visit)
363
- expect(event30[1].to_s).to eq('A => B . A | 0')
364
- parent_as_text = subject.curr_parent.to_string(0)
365
- expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
366
- expected_path30 = path_prefix + 'Alt(A => B A .)[0, 1]'
367
- expect(path_to_s).to eq(expected_path30)
368
-
369
- event31 = walker.next
370
- subject.receive_event(*event31)
371
- expect(event31[0]).to eq(:visit)
372
- expect(event31[1].to_s).to eq('B. | 0')
373
- expect(subject.curr_parent.to_string(0)).to eq('B[0, 0]')
374
- expected_path31 = path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]'
375
- expect(path_to_s).to eq(expected_path31)
376
-
377
- event32 = walker.next
378
- subject.receive_event(*event32)
379
- expect(event32[0]).to eq(:visit)
380
- # Empty production!
381
- expect(event32[1].to_s).to eq('B => . | 0')
382
- expect(subject.curr_parent.to_string(0)).to eq('B[0, 0]')
383
- expected_path30 = path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]'
384
- expect(path_to_s).to eq(expected_path30)
385
-
386
- event33 = walker.next
387
- subject.receive_event(*event33)
388
- expect(event33[0]).to eq(:visit)
389
- expect(event33[1].to_s).to eq('.B | 0')
390
- parent_as_text = subject.curr_parent.to_string(0)
391
- expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
392
- expected_path33 = path_prefix + 'Alt(A => B A .)[0, 1]'
393
- expect(path_to_s).to eq(expected_path33)
394
-
395
- event34 = walker.next
396
- subject.receive_event(*event34)
397
- expect(event34[0]).to eq(:visit)
398
- expect(event34[1].to_s).to eq('A => . B A | 0')
399
- expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
400
- path34 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
401
- expect(path_to_s).to eq(path34)
402
-
403
- event35 = walker.next
404
- subject.receive_event(*event35)
405
- expect(event35[0]).to eq(:revisit)
406
- expect(event35[1].to_s).to eq('.A | 0')
407
- parent_as_text = subject.curr_parent.to_string(0)
408
- expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
409
- expected_path35 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
410
- expect(path_to_s).to eq(expected_path35)
411
-
412
- event36 = walker.next
413
- subject.receive_event(*event36)
414
- expect(event36[0]).to eq(:revisit)
415
- expect(event36[1].to_s).to eq('.S | 0')
416
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
417
- expected_path36 = 'Phi[0, 4]/S[0, 4]'
418
- expect(path_to_s).to eq(expected_path36)
419
-
420
- event37 = walker.next
421
- subject.receive_event(*event37)
422
- expect(event37[0]).to eq(:revisit)
423
- expect(event37[1].to_s).to eq('.Phi | 0')
424
- expect(subject.curr_parent.to_string(0)).to eq('Phi[0, 4]')
425
- expected_path37 = 'Phi[0, 4]'
426
- expect(path_to_s).to eq(expected_path37)
242
+
243
+ next_event(:visit, 'A => B A . | 0') # Event 29
244
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]')
245
+
246
+ next_event(:revisit, 'A. | 0') # REVISIT Event 30
247
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]')
248
+
249
+ next_event(:visit, 'A => B . A | 0') # Event 31
250
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]')
251
+
252
+ next_event(:visit, 'B. | 0') # Event 32
253
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]')
254
+
255
+ # Entry with empty production!
256
+ next_event(:visit, 'B => . | 0') # Event 33
257
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]')
258
+ expected_first_child('_[0, 0]')
259
+
260
+ next_event(:visit, '.B | 0') # Event 34
261
+ expected_curr_path(path_prefix + 'Alt(A => B A .)[0, 1]')
262
+
263
+ next_event(:visit, 'A => . B A | 0') # Event 35
264
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]')
265
+
266
+ next_event(:revisit, '.A | 0') # Event 36
267
+ expected_curr_path('Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]')
268
+
269
+ next_event(:revisit, 'S => . A T | 0') # Event 37
270
+ expected_curr_path('Phi[0, 4]/S[0, 4]')
271
+
272
+ next_event(:revisit, '.S | 0') # Event 38
273
+ expected_curr_path('Phi[0, 4]')
427
274
  end
428
275
  end # context
429
276
 
@@ -445,255 +292,112 @@ module Rley # Open this namespace to avoid module qualifier prefixes
445
292
  parser.parse(sentence_tokens)
446
293
  end
447
294
 
448
- let(:walker) do
295
+ before(:each) do
449
296
  factory = ParseWalkerFactory.new
450
297
  accept_entry = sentence_result.accepting_entry
451
298
  accept_index = sentence_result.chart.last_index
452
- factory.build_walker(accept_entry, accept_index)
299
+ @walker = factory.build_walker(accept_entry, accept_index)
453
300
  end
454
301
 
455
302
  subject { ParseForestBuilder.new(sentence_tokens) }
456
303
 
457
304
  it 'should handle walker events' do
458
- event1 = walker.next
459
- subject.receive_event(*event1)
460
- expect(event1[0]).to eq(:visit)
461
- expect(event1[1].to_s).to eq('S. | 0')
462
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
463
- expected_path1 = 'S[0, 5]'
464
- expect(path_to_s).to eq(expected_path1)
465
-
466
- event2 = walker.next
467
- subject.receive_event(*event2)
468
- expect(event2[0]).to eq(:visit)
469
- expect(event2[1].to_s).to eq('S => NP VP . | 0')
470
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
471
- expected_path2 = expected_path1
472
- expect(path_to_s).to eq(expected_path2)
473
-
474
- event3 = walker.next
475
- subject.receive_event(*event3)
476
- expect(event3[0]).to eq(:visit)
477
- expect(event3[1].to_s).to eq('VP. | 1')
478
- expect(subject.curr_parent.to_string(0)).to eq('VP[1, 5]')
479
- expected_path3 = 'S[0, 5]/VP[1, 5]'
480
- expect(path_to_s).to eq(expected_path3)
481
-
482
- event4 = walker.next
483
- subject.receive_event(*event4)
484
- expect(event4[0]).to eq(:visit)
485
- expect(event4[1].to_s).to eq('VP => Verb NP . | 1')
486
- expect(subject.curr_parent.to_string(0)).to eq('VP[1, 5]')
487
- expected_path4 = 'S[0, 5]/VP[1, 5]'
488
- expect(path_to_s).to eq(expected_path4)
489
-
490
- event5 = walker.next
491
- subject.receive_event(*event5)
492
- expect(event5[0]).to eq(:visit)
493
- expect(event5[1].to_s).to eq('NP. | 2')
494
- expect(subject.curr_parent.to_string(0)).to eq('NP[2, 5]')
495
- expected_path5 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
496
- expect(path_to_s).to eq(expected_path5)
497
-
498
- event6 = walker.next
499
- subject.receive_event(*event6)
500
- expect(event6[0]).to eq(:visit)
501
- expect(event6[1].to_s).to eq('NP => Determiner Nominal . | 2')
502
- expect(subject.curr_parent.to_string(0)).to eq('NP[2, 5]')
503
- expected_path6 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
504
- expect(path_to_s).to eq(expected_path6)
505
-
506
- event7 = walker.next
507
- subject.receive_event(*event7)
508
- expect(event7[0]).to eq(:visit)
509
- expect(event7[1].to_s).to eq('Nominal. | 3')
510
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 5]')
511
- expected_path7 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]'
512
- expect(path_to_s).to eq(expected_path7)
513
-
514
- event8 = walker.next
515
- subject.receive_event(*event8)
516
- expect(event8[0]).to eq(:visit)
517
- expect(event8[1].to_s).to eq('Nominal => Nominal Noun . | 3')
518
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 5]')
519
- expected_path8 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]'
520
- expect(path_to_s).to eq(expected_path8)
305
+ next_event(:visit, 'S. | 0') # Event 1
306
+ expected_curr_path('S[0, 5]')
307
+
308
+ next_event(:visit, 'S => NP VP . | 0') # Event2
309
+ expected_curr_path('S[0, 5]')
310
+
311
+ next_event(:visit, 'VP. | 1') # Event 3
312
+ expected_curr_path('S[0, 5]/VP[1, 5]')
313
+
314
+ next_event(:visit, 'VP => Verb NP . | 1') # Event 4
315
+ expected_curr_path('S[0, 5]/VP[1, 5]')
316
+
317
+ next_event(:visit, 'NP. | 2') # Event 5
318
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]')
319
+
320
+
321
+ next_event(:visit, 'NP => Determiner Nominal . | 2') # Event 6
322
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]')
323
+
324
+ next_event(:visit, 'Nominal. | 3') # Event 7
325
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]')
326
+
327
+ next_event(:visit, 'Nominal => Nominal Noun . | 3') # Event 8
328
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]')
521
329
  expect(subject.curr_parent.subnodes.size).to eq(1)
522
- token_event8 = 'Noun[4, 5]'
523
- child = subject.curr_parent.subnodes.first
524
- expect(child.to_string(0)).to eq(token_event8)
525
-
526
- event9 = walker.next
527
- subject.receive_event(*event9)
528
- expect(event9[0]).to eq(:visit)
529
- expect(event9[1].to_s).to eq('Nominal => Nominal . Noun | 3')
530
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 5]')
531
- expected_path9 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]'
532
- expect(path_to_s).to eq(expected_path9)
533
-
534
- event10 = walker.next
535
- subject.receive_event(*event10)
536
- expect(event10[0]).to eq(:visit)
537
- expect(event10[1].to_s).to eq('Nominal. | 3')
538
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
330
+ expected_first_child('Noun[4, 5]')
331
+
332
+
333
+ next_event(:visit, 'Nominal => Nominal . Noun | 3') # Event 9
334
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]')
335
+
336
+
337
+ next_event(:visit, 'Nominal. | 3') # Event 10
539
338
  path10 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
540
- expect(path_to_s).to eq(path10)
339
+ expected_curr_path(path10)
541
340
 
542
- event11 = walker.next
543
- subject.receive_event(*event11)
544
- expect(event11[0]).to eq(:visit)
545
- expect(event11[1].to_s).to eq('Nominal => Noun . | 3')
546
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
341
+ next_event(:visit, 'Nominal => Noun . | 3') # Event11
547
342
  path11 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
548
- expect(path_to_s).to eq(path11)
343
+ expected_curr_path(path11)
549
344
  expect(subject.curr_parent.subnodes.size).to eq(1)
550
- token_event11 = 'Noun[3, 4]'
551
- child = subject.curr_parent.subnodes.first
552
- expect(child.to_string(0)).to eq(token_event11)
345
+ expected_first_child('Noun[3, 4]')
553
346
 
554
- event12 = walker.next
555
- subject.receive_event(*event12)
556
- expect(event12[0]).to eq(:visit)
557
- expect(event12[1].to_s).to eq('Nominal => . Noun | 3')
558
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
347
+ next_event(:visit, 'Nominal => . Noun | 3') # Event 12
559
348
  path12 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
560
- expect(path_to_s).to eq(path12)
561
-
562
- event13 = walker.next
563
- subject.receive_event(*event13)
564
- expect(event13[0]).to eq(:visit)
565
- expect(event13[1].to_s).to eq('.Nominal | 3')
566
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 5]')
567
- expected_path13 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]'
568
- expect(path_to_s).to eq(expected_path13)
569
-
570
- event14 = walker.next
571
- subject.receive_event(*event14)
572
- expect(event14[0]).to eq(:visit)
573
- expect(event14[1].to_s).to eq('Nominal => . Nominal Noun | 3')
574
- expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 5]')
575
- expected_path14 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]'
576
- expect(path_to_s).to eq(expected_path14)
577
-
578
- event15 = walker.next
579
- subject.receive_event(*event15)
580
- expect(event15[0]).to eq(:revisit)
581
- expect(event15[1].to_s).to eq('.Nominal | 3')
582
- expect(subject.curr_parent.to_string(0)).to eq('NP[2, 5]')
583
- expected_path15 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
584
- expect(path_to_s).to eq(expected_path15)
585
-
586
- event16 = walker.next
587
- subject.receive_event(*event16)
588
- expect(event16[0]).to eq(:visit)
589
- expect(event16[1].to_s).to eq('NP => Determiner . Nominal | 2')
590
- expect(subject.curr_parent.to_string(0)).to eq('NP[2, 5]')
591
- expected_path16 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
592
- expect(path_to_s).to eq(expected_path16)
593
- token_event16 = 'Determiner[2, 3]'
594
- child = subject.curr_parent.subnodes.first
595
- expect(child.to_string(0)).to eq(token_event16)
596
-
597
- event17 = walker.next
598
- subject.receive_event(*event17)
599
- expect(event17[0]).to eq(:visit)
600
- expect(event17[1].to_s).to eq('NP => . Determiner Nominal | 2')
601
- expect(subject.curr_parent.to_string(0)).to eq('NP[2, 5]')
602
- expected_path17 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
603
- expect(path_to_s).to eq(expected_path17)
604
-
605
- event18 = walker.next
606
- subject.receive_event(*event18)
607
- expect(event18[0]).to eq(:visit)
608
- expect(event18[1].to_s).to eq('.NP | 2')
609
- expect(subject.curr_parent.to_string(0)).to eq('VP[1, 5]')
610
- expected_path18 = 'S[0, 5]/VP[1, 5]'
611
- expect(path_to_s).to eq(expected_path18)
612
-
613
- event19 = walker.next
614
- subject.receive_event(*event19)
615
- expect(event19[0]).to eq(:visit)
616
- expect(event19[1].to_s).to eq('VP => Verb . NP | 1')
617
- expect(subject.curr_parent.to_string(0)).to eq('VP[1, 5]')
618
- expected_path19 = 'S[0, 5]/VP[1, 5]'
619
- expect(path_to_s).to eq(expected_path19)
620
- token_event19 = 'Verb[1, 2]'
621
- child = subject.curr_parent.subnodes.first
622
- expect(child.to_string(0)).to eq(token_event19)
623
-
624
- event20 = walker.next
625
- subject.receive_event(*event20)
626
- expect(event20[0]).to eq(:visit)
627
- expect(event20[1].to_s).to eq('VP => . Verb NP | 1')
628
- expect(subject.curr_parent.to_string(0)).to eq('VP[1, 5]')
629
- expected_path20 = 'S[0, 5]/VP[1, 5]'
630
- expect(path_to_s).to eq(expected_path20)
631
-
632
- event21 = walker.next
633
- subject.receive_event(*event21)
634
- expect(event21[0]).to eq(:visit)
635
- expect(event21[1].to_s).to eq('.VP | 1')
636
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
637
- expected_path21 = 'S[0, 5]'
638
- expect(path_to_s).to eq(expected_path21)
639
-
640
- event22 = walker.next
641
- subject.receive_event(*event22)
642
- expect(event22[0]).to eq(:visit)
643
- expect(event22[1].to_s).to eq('S => NP . VP | 0')
644
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
645
- expected_path22 = 'S[0, 5]'
646
- expect(path_to_s).to eq(expected_path22)
647
-
648
- event23 = walker.next
649
- subject.receive_event(*event23)
650
- expect(event23[0]).to eq(:visit)
651
- expect(event23[1].to_s).to eq('NP. | 0')
652
- expect(subject.curr_parent.to_string(0)).to eq('NP[0, 1]')
653
- expected_path23 = 'S[0, 5]/NP[0, 1]'
654
- expect(path_to_s).to eq(expected_path23)
655
-
656
- event24 = walker.next
657
- subject.receive_event(*event24)
658
- expect(event24[0]).to eq(:visit)
659
- expect(event24[1].to_s).to eq('NP => Pronoun . | 0')
660
- expect(subject.curr_parent.to_string(0)).to eq('NP[0, 1]')
661
- expected_path24 = 'S[0, 5]/NP[0, 1]'
662
- expect(path_to_s).to eq(expected_path24)
663
- token_event24 = 'Pronoun[0, 1]'
664
- child = subject.curr_parent.subnodes.first
665
- expect(child.to_string(0)).to eq(token_event24)
666
-
667
- event25 = walker.next
668
- subject.receive_event(*event25)
669
- expect(event25[0]).to eq(:visit)
670
- expect(event25[1].to_s).to eq('NP => . Pronoun | 0')
671
- expect(subject.curr_parent.to_string(0)).to eq('NP[0, 1]')
672
- expected_path25 = 'S[0, 5]/NP[0, 1]'
673
- expect(path_to_s).to eq(expected_path25)
674
-
675
- event26 = walker.next
676
- subject.receive_event(*event26)
677
- expect(event26[0]).to eq(:visit)
678
- expect(event26[1].to_s).to eq('.NP | 0')
679
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
680
- expected_path26 = 'S[0, 5]'
681
- expect(path_to_s).to eq(expected_path26)
682
-
683
- event27 = walker.next
684
- subject.receive_event(*event27)
685
- expect(event27[0]).to eq(:visit)
686
- expect(event27[1].to_s).to eq('S => . NP VP | 0')
687
- expect(subject.curr_parent.to_string(0)).to eq('S[0, 5]')
688
- expected_path27 = 'S[0, 5]'
689
- expect(path_to_s).to eq(expected_path27)
690
-
691
- event28 = walker.next
692
- subject.receive_event(*event28)
693
- expect(event28[0]).to eq(:visit)
694
- expect(event28[1].to_s).to eq('.S | 0')
695
- expected_path28 = ''
696
- expect(path_to_s).to eq(expected_path28)
349
+ expected_curr_path(path12)
350
+
351
+ next_event(:visit, '.Nominal | 3') # Event 13
352
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]')
353
+
354
+ next_event(:visit, 'Nominal => . Nominal Noun | 3') # Event 14
355
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]')
356
+
357
+ next_event(:revisit, '.Nominal | 3') # REVISIT Event 15
358
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]')
359
+
360
+ next_event(:visit, 'NP => Determiner . Nominal | 2') # Event 16
361
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]')
362
+ expected_first_child('Determiner[2, 3]')
363
+
364
+ next_event(:visit, 'NP => . Determiner Nominal | 2') # Event 17
365
+ expected_curr_path('S[0, 5]/VP[1, 5]/NP[2, 5]')
366
+
367
+ next_event(:visit, '.NP | 2') # Event 18
368
+ expected_curr_path('S[0, 5]/VP[1, 5]')
369
+
370
+ next_event(:visit, 'VP => Verb . NP | 1') # Event 19
371
+ expected_curr_path('S[0, 5]/VP[1, 5]')
372
+ expected_first_child('Verb[1, 2]')
373
+
374
+ next_event(:visit, 'VP => . Verb NP | 1') # Event 20
375
+ expected_curr_path('S[0, 5]/VP[1, 5]')
376
+
377
+ next_event(:visit, '.VP | 1') # Event 21
378
+ expected_curr_path('S[0, 5]')
379
+
380
+ next_event(:visit, 'S => NP . VP | 0') # Event22
381
+ expected_curr_path('S[0, 5]')
382
+
383
+ next_event(:visit, 'NP. | 0') # Event 23
384
+ expected_curr_path('S[0, 5]/NP[0, 1]')
385
+
386
+ next_event(:visit, 'NP => Pronoun . | 0') # Event 24
387
+ expected_curr_path('S[0, 5]/NP[0, 1]')
388
+ expected_first_child('Pronoun[0, 1]')
389
+
390
+ next_event(:visit, 'NP => . Pronoun | 0') # Event 25
391
+ expected_curr_path('S[0, 5]/NP[0, 1]')
392
+
393
+ next_event(:visit, '.NP | 0') # Event 26
394
+ expected_curr_path('S[0, 5]')
395
+
396
+ next_event(:visit, 'S => . NP VP | 0') # Event 27
397
+ expected_curr_path('S[0, 5]')
398
+
399
+ next_event(:visit, '.S | 0') # Event28
400
+ expected_curr_path('')
697
401
  end
698
402
  end # context
699
403
  end # describe