rley 0.3.05 → 0.3.06

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