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 +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -1
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/parser/parse_walker_factory.rb +24 -7
- data/spec/rley/parser/ambiguous_parse_spec.rb +276 -0
- data/spec/rley/parser/parse_forest_builder_spec.rb +230 -526
- data/spec/rley/parser/parse_walker_factory_spec.rb +29 -17
- data/spec/rley/support/grammar_ambig01_helper.rb +41 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bbd7b9c764c5f24a73b8f3f158e6c25f6f7ccd6
|
4
|
+
data.tar.gz: 63676212ceb56eb1b09f511a6fade48abcd7e3ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a17d1c3447e72f59f4f8268b7e90ccfda098fb0769b73219866d42fa77095e2e06f6bc980e6b0e5928ca1217c9c1eb8b5b973ff12b511fa3327745353caf5bd
|
7
|
+
data.tar.gz: e03b4dc4cebf8fca9049e367641248601850398ed77a725ab92e3cb22f2552224dc143a8121d142f0e38522a5cd1dc5ef570341542d0b39845a3ab7b02596a97
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -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
data/lib/rley/constants.rb
CHANGED
@@ -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, #
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
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
|
-
|
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
|
-
|
110
|
-
|
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
|
-
|
126
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
145
|
-
|
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
|
-
|
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
|
-
|
156
|
-
|
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
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
194
|
-
|
195
|
-
expect(
|
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
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
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
|
-
|
229
|
-
|
230
|
-
|
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
|
-
|
238
|
-
|
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
|
-
|
254
|
-
|
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
|
-
|
280
|
-
|
281
|
-
|
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
|
-
|
286
|
-
|
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
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
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
|
328
|
-
|
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
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
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
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
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
|
-
|
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
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
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
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
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
|
-
|
339
|
+
expected_curr_path(path10)
|
541
340
|
|
542
|
-
|
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
|
-
|
343
|
+
expected_curr_path(path11)
|
549
344
|
expect(subject.curr_parent.subnodes.size).to eq(1)
|
550
|
-
|
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
|
-
|
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
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
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
|