dendroid 0.2.00 → 0.2.01

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.
@@ -1,223 +1,250 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../spec_helper'
4
- require_relative '../support/sample_grammars'
5
- require_relative '../../../lib/dendroid/recognizer/recognizer'
6
- require_relative '../../../lib/dendroid/parsing/chart_walker'
7
-
8
- # require_relative '../grm_dsl/base_grm_builder'
9
- # require_relative '../utils/base_tokenizer'
10
- # require_relative '../recognizer/recognizer'
11
- # require_relative 'chart_walker'
12
- # require_relative 'parse_tree_visitor'
13
- # require_relative '../formatters/bracket_notation'
14
- # require_relative '../formatters/ascii_tree'
15
-
16
- RSpec.describe Dendroid::Parsing::ChartWalker do
17
- include SampleGrammars
18
-
19
- def retrieve_success_item(chart, grammar)
20
- last_item_set = chart.item_sets.last
21
- result = nil
22
- last_item_set.items.reverse_each do |itm|
23
- if itm.origin.zero? && itm.dotted_item.completed? && itm.dotted_item.rule.lhs == grammar.start_symbol
24
- result = itm
25
- break
26
- end
27
- end
28
-
29
- result
30
- end
31
-
32
- def recognizer_for(grammar, tokenizer)
33
- Dendroid::Recognizer::Recognizer.new(grammar, tokenizer)
34
- end
35
-
36
- def success_entry(chart, recognizer)
37
- retrieve_success_item(chart, recognizer.grm_analysis.grammar)
38
- end
39
-
40
- context 'Parsing non-ambiguous grammars' do
41
- it 'generates a parse tree for the example from Wikipedia' do
42
- recognizer = recognizer_for(grammar_l1, tokenizer_l1)
43
- chart = recognizer.run('2 + 3 * 4')
44
- walker = described_class.new(chart)
45
- root = walker.walk(success_entry(chart, recognizer))
46
-
47
- expect(root.to_s).to eq('p => s [0, 5]')
48
- expect(root.children.size). to eq(1)
49
- expect(root.children[-1].to_s).to eq('s => s PLUS m [0, 5]')
50
- plus_expr = root.children[-1]
51
- expect(plus_expr.children.size).to eq(3)
52
- expect(plus_expr.children[0].to_s).to eq('s => m [0, 1]')
53
- expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
54
- expect(plus_expr.children[2].to_s).to eq('m => m STAR t [2, 5]')
55
-
56
- operand_plus = plus_expr.children[0]
57
- expect(operand_plus.children.size).to eq(1)
58
- expect(operand_plus.children[0].to_s).to eq('m => t [0, 1]')
59
- expect(operand_plus.children[0].children.size).to eq(1)
60
- expect(operand_plus.children[0].children[0].to_s).to eq('t => INTEGER [0, 1]')
61
- expect(operand_plus.children[0].children[0].children[0].to_s).to eq('INTEGER: 2 [0, 1]')
62
-
63
- expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
64
-
65
- star_expr = plus_expr.children[2]
66
- expect(star_expr.children.size).to eq(3)
67
- expect(star_expr.children[0].to_s).to eq('m => t [2, 3]')
68
- expect(star_expr.children[1].to_s).to eq('STAR [3, 4]')
69
- expect(star_expr.children[2].to_s).to eq('t => INTEGER [4, 5]')
70
-
71
- operand_star = star_expr.children[0]
72
- expect(operand_star.children.size).to eq(1)
73
- expect(operand_star.children[0].to_s).to eq('t => INTEGER [2, 3]')
74
- expect(operand_star.children[0].children[0].to_s).to eq('INTEGER: 3 [2, 3]')
75
-
76
- expect(star_expr.children[2].children.size).to eq(1)
77
- expect(star_expr.children[2].children[0].to_s).to eq('INTEGER: 4 [4, 5]')
78
- end
79
-
80
- it 'generates a parse tree for grammar l10 (with left recursive rule)' do
81
- recognizer = recognizer_for(grammar_l10, tokenizer_l10)
82
- chart = recognizer.run('a a a a a')
83
- walker = described_class.new(chart)
84
- root = walker.walk(success_entry(chart, recognizer))
85
-
86
- expect(root.to_s).to eq('A => A a [0, 5]')
87
- expect(root.children.size). to eq(2)
88
- expect(root.children[0].to_s).to eq('A => A a [0, 4]')
89
- expect(root.children[1].to_s).to eq('a [4, 5]')
90
-
91
- expect(root.children[0].children.size).to eq(2)
92
- expect(root.children[0].children[0].to_s).to eq('A => A a [0, 3]')
93
- expect(root.children[0].children[1].to_s).to eq('a [3, 4]')
94
-
95
- grand_child = root.children[0].children[0]
96
- expect(grand_child.children.size).to eq(2)
97
- expect(grand_child.children[0].to_s).to eq('A => A a [0, 2]')
98
- expect(grand_child.children[1].to_s).to eq('a [2, 3]')
99
-
100
- expect(grand_child.children[0].children.size).to eq(2)
101
- expect(grand_child.children[0].children[0].to_s).to eq('A => A a [0, 1]')
102
- expect(grand_child.children[0].children[1].to_s).to eq('a [1, 2]')
103
-
104
- expect(grand_child.children[0].children[0].children.size).to eq(2)
105
- expect(grand_child.children[0].children[0].children[0].to_s).to eq('_ [0, 0]')
106
- expect(grand_child.children[0].children[0].children[1].to_s).to eq('a [0, 1]')
107
- end
108
-
109
- it 'generates a parse tree for grammar l11 (with right recursive rule)' do
110
- recognizer = recognizer_for(grammar_l11, tokenizer_l11)
111
- chart = recognizer.run('a a a a a')
112
- walker = described_class.new(chart)
113
- root = walker.walk(success_entry(chart, recognizer))
114
-
115
- expect(root.to_s).to eq('A => a A [0, 5]')
116
- expect(root.children.size). to eq(2)
117
- expect(root.children[0].to_s).to eq('a [0, 1]')
118
- expect(root.children[1].to_s).to eq('A => a A [1, 5]')
119
-
120
- expect(root.children[1].children.size).to eq(2)
121
- expect(root.children[1].children[0].to_s).to eq('a [1, 2]')
122
- expect(root.children[1].children[1].to_s).to eq('A => a A [2, 5]')
123
-
124
- grand_child = root.children[1].children[1]
125
- expect(grand_child.children.size).to eq(2)
126
- expect(grand_child.children[0].to_s).to eq('a [2, 3]')
127
- expect(grand_child.children[1].to_s).to eq('A => a A [3, 5]')
128
-
129
- expect(grand_child.children[1].children.size).to eq(2)
130
- expect(grand_child.children[1].children[0].to_s).to eq('a [3, 4]')
131
- expect(grand_child.children[1].children[1].to_s).to eq('A => a A [4, 5]')
132
-
133
- expect(grand_child.children[1].children[1].children.size).to eq(2)
134
- expect(grand_child.children[1].children[1].children[0].to_s).to eq('a [4, 5]')
135
- expect(grand_child.children[1].children[1].children[1].to_s).to eq('_ [5, 5]')
136
- end
137
- end # context
138
-
139
- context 'Parsing ambiguous grammars' do
140
- it "generates a parse forest for the G2 grammar that choked Earley's parsing algorithm" do
141
- recognizer = recognizer_for(grammar_l8, tokenizer_l8)
142
- chart = recognizer.run('x x x x')
143
- walker = described_class.new(chart)
144
- root = walker.walk(success_entry(chart, recognizer))
145
-
146
- expect(root.to_s).to eq('OR: S [0, 4]')
147
- expect(root.children.size). to eq(3)
148
- root.children.each do |child|
149
- expect(child.children.size).to eq(2)
150
- expect(child.to_s).to eq('S => S S [0, 4]')
151
- end
152
- (a, b, c) = root.children
153
-
154
- # Test structure of tree a
155
- (child_a_0, child_a_1) = a.children
156
- expect(child_a_0.to_s).to eq('S => S S [0, 2]')
157
- expect(child_a_1.to_s).to eq('S => S S [2, 4]')
158
- expect(child_a_0.children.size).to eq(2)
159
- (child_a_0_0, child_a_0_1) = child_a_0.children
160
- expect(child_a_0_0.to_s).to eq('S => x [0, 1]')
161
- expect(child_a_0_1.to_s).to eq('S => x [1, 2]')
162
- expect(child_a_0_0.children[0].to_s).to eq('x [0, 1]')
163
- expect(child_a_0_1.children[0].to_s).to eq('x [1, 2]')
164
-
165
- expect(child_a_1.children.size).to eq(2)
166
- (child_a_1_0, child_a_1_1) = child_a_1.children
167
- expect(child_a_1_0.to_s).to eq('S => x [2, 3]')
168
- expect(child_a_1_1.to_s).to eq('S => x [3, 4]')
169
- expect(child_a_1_0.children[0].to_s).to eq('x [2, 3]')
170
- expect(child_a_1_1.children[0].to_s).to eq('x [3, 4]')
171
-
172
- # Test structure of forest b
173
- (child_b_0, child_b_1) = b.children
174
- expect(child_b_0.to_s).to eq('OR: S [0, 3]')
175
- expect(child_b_1.to_s).to eq('S => x [3, 4]')
176
- expect(child_b_1.equal?(child_a_1_1)).to be_truthy # Sharing
177
- expect(child_b_0.children.size).to eq(2)
178
- (child_b_0_0, child_b_0_1) = child_b_0.children
179
- expect(child_b_0_0.to_s).to eq('S => S S [0, 3]')
180
- expect(child_b_0_1.to_s).to eq('S => S S [0, 3]')
181
- expect(child_b_0_0.children.size).to eq(2)
182
- (child_b_0_0_0, child_b_0_0_1) = child_b_0_0.children
183
- expect(child_b_0_0_0.to_s).to eq('S => x [0, 1]')
184
- expect(child_b_0_0_0.equal?(child_a_0_0)).to be_truthy # Sharing
185
- expect(child_b_0_0_1.to_s).to eq('S => S S [1, 3]')
186
- expect(child_b_0_0_1.children.size).to eq(2)
187
- expect(child_b_0_0_1.children[0].to_s).to eq('S => x [1, 2]')
188
- expect(child_b_0_0_1.children[0].equal?(child_a_0_1)).to be_truthy # Sharing
189
- expect(child_b_0_0_1.children[1].to_s).to eq('S => x [2, 3]')
190
- expect(child_b_0_0_1.children[1].equal?(child_a_1_0)).to be_truthy # Sharing
191
-
192
- expect(child_b_0_1.children.size).to eq(2)
193
- (child_b_0_1_0, child_b_0_1_1) = child_b_0_1.children
194
- expect(child_b_0_1_0.to_s).to eq('S => S S [0, 2]')
195
- expect(child_b_0_1_0.equal?(child_a_0)).to be_truthy # Sharing
196
- expect(child_b_0_1_1.to_s).to eq('S => x [2, 3]')
197
- expect(child_b_0_1_1.equal?(child_a_1_0)).to be_truthy # Sharing
198
-
199
- # Test structure of forest c
200
- (child_c_0, child_c_1) = c.children
201
- expect(child_c_0.to_s).to eq('S => x [0, 1]')
202
- expect(child_c_0.equal?(child_a_0_0)).to be_truthy # Sharing
203
- expect(child_c_1.to_s).to eq('OR: S [1, 4]')
204
- expect(child_c_1.children.size).to eq(2)
205
- (child_c_1_0, child_c_1_1) = child_c_1.children
206
- expect(child_c_1_0.to_s).to eq('S => S S [1, 4]')
207
- expect(child_c_1_1.to_s).to eq('S => S S [1, 4]')
208
- expect(child_c_1_0.children.size).to eq(2)
209
- (child_c_1_0_0, child_c_1_0_1) = child_c_1_0.children
210
- expect(child_c_1_0_0.to_s).to eq('S => x [1, 2]')
211
- expect(child_c_1_0_0.equal?(child_a_0_1)).to be_truthy # Sharing
212
- expect(child_c_1_0_1.to_s).to eq('S => S S [2, 4]')
213
- expect(child_c_1_0_1.equal?(child_a_1)).to be_truthy # Sharing
214
- (child_c_1_1_0, child_c_1_1_1) = child_c_1_1.children
215
- expect(child_c_1_1_0.to_s).to eq('S => S S [1, 3]')
216
- expect(child_c_1_1_0.equal?(child_b_0_0_1)).to be_truthy # Sharing
217
- expect(child_c_1_1_1.to_s).to eq('S => x [3, 4]')
218
- expect(child_c_1_1_1.equal?(child_b_1)).to be_truthy # Sharing
219
- end
220
- end # context
221
- end # describe
222
-
223
-
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+ require_relative '../support/sample_grammars'
5
+ require_relative '../../../lib/dendroid/recognizer/recognizer'
6
+ require_relative '../../../lib/dendroid/parsing/chart_walker'
7
+
8
+ # require_relative '../grm_dsl/base_grm_builder'
9
+ # require_relative '../utils/base_tokenizer'
10
+ # require_relative '../recognizer/recognizer'
11
+ # require_relative 'chart_walker'
12
+ # require_relative 'parse_tree_visitor'
13
+ # require_relative '../formatters/bracket_notation'
14
+ # require_relative '../formatters/ascii_tree'
15
+
16
+ RSpec.describe Dendroid::Parsing::ChartWalker do
17
+ include SampleGrammars
18
+
19
+ def retrieve_success_item(chart, grammar)
20
+ last_item_set = chart.item_sets.last
21
+ result = nil
22
+ last_item_set.items.reverse_each do |itm|
23
+ if itm.origin.zero? && itm.dotted_item.completed? && itm.dotted_item.rule.lhs == grammar.start_symbol
24
+ result = itm
25
+ break
26
+ end
27
+ end
28
+
29
+ result
30
+ end
31
+
32
+ def recognizer_for(grammar, tokenizer)
33
+ Dendroid::Recognizer::Recognizer.new(grammar, tokenizer)
34
+ end
35
+
36
+ def success_entry(chart, recognizer)
37
+ retrieve_success_item(chart, recognizer.grm_analysis.grammar)
38
+ end
39
+
40
+ # rubocop: disable Naming/VariableNumber
41
+ context 'Parsing non-ambiguous grammars' do
42
+ it 'generates a parse tree for the example from Wikipedia' do
43
+ recognizer = recognizer_for(grammar_l1, tokenizer_l1)
44
+ chart = recognizer.run('2 + 3 * 4')
45
+ walker = described_class.new(chart)
46
+ root = walker.walk(success_entry(chart, recognizer))
47
+
48
+ expect(root.to_s).to eq('p => s [0, 5]')
49
+ expect(root.children.size).to eq(1)
50
+ expect(root.children[-1].to_s).to eq('s => s PLUS m [0, 5]')
51
+ plus_expr = root.children[-1]
52
+ expect(plus_expr.children.size).to eq(3)
53
+ expect(plus_expr.children[0].to_s).to eq('s => m [0, 1]')
54
+ expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
55
+ expect(plus_expr.children[2].to_s).to eq('m => m STAR t [2, 5]')
56
+
57
+ operand_plus = plus_expr.children[0]
58
+ expect(operand_plus.children.size).to eq(1)
59
+ expect(operand_plus.children[0].to_s).to eq('m => t [0, 1]')
60
+ expect(operand_plus.children[0].children.size).to eq(1)
61
+ expect(operand_plus.children[0].children[0].to_s).to eq('t => INTEGER [0, 1]')
62
+ expect(operand_plus.children[0].children[0].children[0].to_s).to eq('INTEGER: 2 [0, 1]')
63
+
64
+ expect(plus_expr.children[1].to_s).to eq('PLUS [1, 2]')
65
+
66
+ star_expr = plus_expr.children[2]
67
+ expect(star_expr.children.size).to eq(3)
68
+ expect(star_expr.children[0].to_s).to eq('m => t [2, 3]')
69
+ expect(star_expr.children[1].to_s).to eq('STAR [3, 4]')
70
+ expect(star_expr.children[2].to_s).to eq('t => INTEGER [4, 5]')
71
+
72
+ operand_star = star_expr.children[0]
73
+ expect(operand_star.children.size).to eq(1)
74
+ expect(operand_star.children[0].to_s).to eq('t => INTEGER [2, 3]')
75
+ expect(operand_star.children[0].children[0].to_s).to eq('INTEGER: 3 [2, 3]')
76
+
77
+ expect(star_expr.children[2].children.size).to eq(1)
78
+ expect(star_expr.children[2].children[0].to_s).to eq('INTEGER: 4 [4, 5]')
79
+ end
80
+
81
+ it 'generates a parse tree for grammar l10 (with left recursive rule)' do
82
+ recognizer = recognizer_for(grammar_l10, tokenizer_l10)
83
+ chart = recognizer.run('a a a a a')
84
+ walker = described_class.new(chart)
85
+ root = walker.walk(success_entry(chart, recognizer))
86
+
87
+ expect(root.to_s).to eq('A => A a [0, 5]')
88
+ expect(root.children.size).to eq(2)
89
+ expect(root.children[0].to_s).to eq('A => A a [0, 4]')
90
+ expect(root.children[1].to_s).to eq('a [4, 5]')
91
+
92
+ expect(root.children[0].children.size).to eq(2)
93
+ expect(root.children[0].children[0].to_s).to eq('A => A a [0, 3]')
94
+ expect(root.children[0].children[1].to_s).to eq('a [3, 4]')
95
+
96
+ grand_child = root.children[0].children[0]
97
+ expect(grand_child.children.size).to eq(2)
98
+ expect(grand_child.children[0].to_s).to eq('A => A a [0, 2]')
99
+ expect(grand_child.children[1].to_s).to eq('a [2, 3]')
100
+
101
+ expect(grand_child.children[0].children.size).to eq(2)
102
+ expect(grand_child.children[0].children[0].to_s).to eq('A => A a [0, 1]')
103
+ expect(grand_child.children[0].children[1].to_s).to eq('a [1, 2]')
104
+
105
+ expect(grand_child.children[0].children[0].children.size).to eq(2)
106
+ expect(grand_child.children[0].children[0].children[0].to_s).to eq('_ [0, 0]')
107
+ expect(grand_child.children[0].children[0].children[1].to_s).to eq('a [0, 1]')
108
+ end
109
+
110
+ it 'generates a parse tree for grammar l11 (with right recursive rule)' do
111
+ recognizer = recognizer_for(grammar_l11, tokenizer_l11)
112
+ chart = recognizer.run('a a a a a')
113
+ walker = described_class.new(chart)
114
+ root = walker.walk(success_entry(chart, recognizer))
115
+
116
+ expect(root.to_s).to eq('A => a A [0, 5]')
117
+ expect(root.children.size).to eq(2)
118
+ expect(root.children[0].to_s).to eq('a [0, 1]')
119
+ expect(root.children[1].to_s).to eq('A => a A [1, 5]')
120
+
121
+ expect(root.children[1].children.size).to eq(2)
122
+ expect(root.children[1].children[0].to_s).to eq('a [1, 2]')
123
+ expect(root.children[1].children[1].to_s).to eq('A => a A [2, 5]')
124
+
125
+ grand_child = root.children[1].children[1]
126
+ expect(grand_child.children.size).to eq(2)
127
+ expect(grand_child.children[0].to_s).to eq('a [2, 3]')
128
+ expect(grand_child.children[1].to_s).to eq('A => a A [3, 5]')
129
+
130
+ expect(grand_child.children[1].children.size).to eq(2)
131
+ expect(grand_child.children[1].children[0].to_s).to eq('a [3, 4]')
132
+ expect(grand_child.children[1].children[1].to_s).to eq('A => a A [4, 5]')
133
+
134
+ expect(grand_child.children[1].children[1].children.size).to eq(2)
135
+ expect(grand_child.children[1].children[1].children[0].to_s).to eq('a [4, 5]')
136
+ expect(grand_child.children[1].children[1].children[1].to_s).to eq('_ [5, 5]')
137
+ end
138
+ end # context
139
+
140
+ context 'Parsing ambiguous grammars' do
141
+ it "generates a parse forest for the G2 grammar that choked Earley's parsing algorithm" do
142
+ recognizer = recognizer_for(grammar_l8, tokenizer_l8)
143
+ chart = recognizer.run('x x x x')
144
+ walker = described_class.new(chart)
145
+ root = walker.walk(success_entry(chart, recognizer))
146
+
147
+ expect(root.to_s).to eq('OR: S [0, 4]')
148
+ expect(root.children.size).to eq(3)
149
+ root.children.each do |child|
150
+ expect(child.children.size).to eq(2)
151
+ expect(child.to_s).to eq('S => S S [0, 4]')
152
+ end
153
+ (a, b, c) = root.children
154
+
155
+ # Test structure of tree a
156
+ (child_a_0, child_a_1) = a.children
157
+ expect(child_a_0.to_s).to eq('S => S S [0, 2]')
158
+ expect(child_a_1.to_s).to eq('S => S S [2, 4]')
159
+ expect(child_a_0.children.size).to eq(2)
160
+ (child_a_0_0, child_a_0_1) = child_a_0.children
161
+ expect(child_a_0_0.to_s).to eq('S => x [0, 1]')
162
+ expect(child_a_0_1.to_s).to eq('S => x [1, 2]')
163
+ expect(child_a_0_0.children[0].to_s).to eq('x [0, 1]')
164
+ expect(child_a_0_1.children[0].to_s).to eq('x [1, 2]')
165
+
166
+ expect(child_a_1.children.size).to eq(2)
167
+ (child_a_1_0, child_a_1_1) = child_a_1.children
168
+ expect(child_a_1_0.to_s).to eq('S => x [2, 3]')
169
+ expect(child_a_1_1.to_s).to eq('S => x [3, 4]')
170
+ expect(child_a_1_0.children[0].to_s).to eq('x [2, 3]')
171
+ expect(child_a_1_1.children[0].to_s).to eq('x [3, 4]')
172
+
173
+ # Test structure of forest b
174
+ (child_b_0, child_b_1) = b.children
175
+ expect(child_b_0.to_s).to eq('OR: S [0, 3]')
176
+ expect(child_b_1.to_s).to eq('S => x [3, 4]')
177
+ expect(child_b_1.equal?(child_a_1_1)).to be_truthy # Sharing
178
+ expect(child_b_0.children.size).to eq(2)
179
+ (child_b_0_0, child_b_0_1) = child_b_0.children
180
+ expect(child_b_0_0.to_s).to eq('S => S S [0, 3]')
181
+ expect(child_b_0_1.to_s).to eq('S => S S [0, 3]')
182
+ expect(child_b_0_0.children.size).to eq(2)
183
+ (child_b_0_0_0, child_b_0_0_1) = child_b_0_0.children
184
+ expect(child_b_0_0_0.to_s).to eq('S => x [0, 1]')
185
+ expect(child_b_0_0_0.equal?(child_a_0_0)).to be_truthy # Sharing
186
+ expect(child_b_0_0_1.to_s).to eq('S => S S [1, 3]')
187
+ expect(child_b_0_0_1.children.size).to eq(2)
188
+ expect(child_b_0_0_1.children[0].to_s).to eq('S => x [1, 2]')
189
+ expect(child_b_0_0_1.children[0].equal?(child_a_0_1)).to be_truthy # Sharing
190
+ expect(child_b_0_0_1.children[1].to_s).to eq('S => x [2, 3]')
191
+ expect(child_b_0_0_1.children[1].equal?(child_a_1_0)).to be_truthy # Sharing
192
+
193
+ expect(child_b_0_1.children.size).to eq(2)
194
+ (child_b_0_1_0, child_b_0_1_1) = child_b_0_1.children
195
+ expect(child_b_0_1_0.to_s).to eq('S => S S [0, 2]')
196
+ expect(child_b_0_1_0.equal?(child_a_0)).to be_truthy # Sharing
197
+ expect(child_b_0_1_1.to_s).to eq('S => x [2, 3]')
198
+ expect(child_b_0_1_1.equal?(child_a_1_0)).to be_truthy # Sharing
199
+
200
+ # Test structure of forest c
201
+ (child_c_0, child_c_1) = c.children
202
+ expect(child_c_0.to_s).to eq('S => x [0, 1]')
203
+ expect(child_c_0.equal?(child_a_0_0)).to be_truthy # Sharing
204
+ expect(child_c_1.to_s).to eq('OR: S [1, 4]')
205
+ expect(child_c_1.children.size).to eq(2)
206
+ (child_c_1_0, child_c_1_1) = child_c_1.children
207
+ expect(child_c_1_0.to_s).to eq('S => S S [1, 4]')
208
+ expect(child_c_1_1.to_s).to eq('S => S S [1, 4]')
209
+ expect(child_c_1_0.children.size).to eq(2)
210
+ (child_c_1_0_0, child_c_1_0_1) = child_c_1_0.children
211
+ expect(child_c_1_0_0.to_s).to eq('S => x [1, 2]')
212
+ expect(child_c_1_0_0.equal?(child_a_0_1)).to be_truthy # Sharing
213
+ expect(child_c_1_0_1.to_s).to eq('S => S S [2, 4]')
214
+ expect(child_c_1_0_1.equal?(child_a_1)).to be_truthy # Sharing
215
+ (child_c_1_1_0, child_c_1_1_1) = child_c_1_1.children
216
+ expect(child_c_1_1_0.to_s).to eq('S => S S [1, 3]')
217
+ expect(child_c_1_1_0.equal?(child_b_0_0_1)).to be_truthy # Sharing
218
+ expect(child_c_1_1_1.to_s).to eq('S => x [3, 4]')
219
+ expect(child_c_1_1_1.equal?(child_b_1)).to be_truthy # Sharing
220
+ end
221
+
222
+ it "generates a parse forest for example 3 in paper 'SPPF-Style Parsing From Earley Recognisers'" do
223
+ recognizer = recognizer_for(grammar_l7, tokenizer_l7)
224
+ chart = recognizer.run('a a')
225
+ walker = described_class.new(chart)
226
+ root = walker.walk(success_entry(chart, recognizer))
227
+
228
+ expect(root.to_s).to eq('OR: S [0, 2]')
229
+ expect(root.children.size).to eq(2)
230
+ root.children.each do |ch|
231
+ expect(ch.to_s).to eq('S => S T [0, 2]')
232
+ expect(ch.children.size).to eq(2)
233
+ end
234
+ (child_0_0, child_0_1) = root.children[0].children
235
+ expect(child_0_0.to_s).to eq('S => a [0, 1]')
236
+ expect(child_0_1.to_s).to eq('T => a B [1, 2]')
237
+ expect(child_0_1.children.size).to eq(2)
238
+ expect(child_0_1.children[0].to_s).to eq('a [1, 2]')
239
+ expect(child_0_1.children[1].to_s).to eq('_ [2, 2]')
240
+
241
+ (child_1_0, child_1_1) = root.children[1].children
242
+ expect(child_1_0.to_s).to eq('S => a [0, 1]')
243
+ expect(child_1_1.to_s).to eq('T => a [1, 2]')
244
+ expect(child_1_0.equal?(child_0_0)).to be_truthy # Sharing
245
+ expect(child_1_1.children[0].to_s).to eq('a [1, 2]')
246
+ expect(child_1_1.children[0].equal?(child_0_1.children[0])).to be_truthy # Sharing
247
+ end
248
+ end # context
249
+ # rubocop: enable Naming/VariableNumber
250
+ end # describe
@@ -1,36 +1,36 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../spec_helper'
4
- require_relative '../../../lib\dendroid/syntax/terminal'
5
- require_relative '../../../lib/dendroid/lexical/token_position'
6
- require_relative '../../../lib/dendroid/lexical/literal'
7
- require_relative '../../../lib/dendroid/parsing/terminal_node'
8
-
9
- RSpec.describe Dendroid::Parsing::TerminalNode do
10
- let(:ex_source) { '+' }
11
- let(:ex_pos) { Dendroid::Lexical::TokenPosition.new(2, 5) }
12
- let(:ex_terminal) { Dendroid::Syntax::Terminal.new('PLUS') }
13
- let(:plus_token) { Dendroid::Lexical::Token.new(ex_source, ex_pos, ex_terminal) }
14
- let(:plus_node) { described_class.new(ex_terminal, plus_token, 3) }
15
-
16
- let(:int_source) { '2' }
17
- let(:int_symbol) { Dendroid::Syntax::Terminal.new('INTEGER') }
18
- let(:int_token) { Dendroid::Lexical::Literal.new(int_source, ex_pos, int_symbol, 2) }
19
- let(:int_node) { described_class.new(int_symbol, int_token, 5) }
20
-
21
- context 'Initialization:' do
22
- it 'should be initialized with a symbol, terminal and a rank' do
23
- expect { described_class.new(ex_terminal, plus_token, 3) }.not_to raise_error
24
- end
25
- end
26
-
27
- context 'provided services' do
28
- it 'renders a String representation of itself' do
29
- expect(plus_node.to_s).to eq('PLUS [3, 4]')
30
- end
31
-
32
- it 'renders also the token value (if any)' do
33
- expect(int_node.to_s).to eq('INTEGER: 2 [5, 6]')
34
- end
35
- end
36
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+ require_relative '../../../lib\dendroid/syntax/terminal'
5
+ require_relative '../../../lib/dendroid/lexical/token_position'
6
+ require_relative '../../../lib/dendroid/lexical/literal'
7
+ require_relative '../../../lib/dendroid/parsing/terminal_node'
8
+
9
+ RSpec.describe Dendroid::Parsing::TerminalNode do
10
+ let(:ex_source) { '+' }
11
+ let(:ex_pos) { Dendroid::Lexical::TokenPosition.new(2, 5) }
12
+ let(:ex_terminal) { Dendroid::Syntax::Terminal.new('PLUS') }
13
+ let(:plus_token) { Dendroid::Lexical::Token.new(ex_source, ex_pos, ex_terminal) }
14
+ let(:plus_node) { described_class.new(ex_terminal, plus_token, 3) }
15
+
16
+ let(:int_source) { '2' }
17
+ let(:int_symbol) { Dendroid::Syntax::Terminal.new('INTEGER') }
18
+ let(:int_token) { Dendroid::Lexical::Literal.new(int_source, ex_pos, int_symbol, 2) }
19
+ let(:int_node) { described_class.new(int_symbol, int_token, 5) }
20
+
21
+ context 'Initialization:' do
22
+ it 'should be initialized with a symbol, terminal and a rank' do
23
+ expect { described_class.new(ex_terminal, plus_token, 3) }.not_to raise_error
24
+ end
25
+ end
26
+
27
+ context 'provided services' do
28
+ it 'renders a String representation of itself' do
29
+ expect(plus_node.to_s).to eq('PLUS [3, 4]')
30
+ end
31
+
32
+ it 'renders also the token value (if any)' do
33
+ expect(int_node.to_s).to eq('INTEGER: 2 [5, 6]')
34
+ end
35
+ end
36
+ end
@@ -422,7 +422,6 @@ describe Dendroid::Recognizer::Recognizer do
422
422
  comp_expected_actuals(chart, expectations)
423
423
  end
424
424
 
425
-
426
425
  it 'accepts an input with multiple levels of ambiguity' do
427
426
  recognizer = described_class.new(grammar_l8, tokenizer_l8)
428
427
  chart = recognizer.run('x x x x')
@@ -256,9 +256,7 @@ module SampleGrammars
256
256
  declare_terminals('a', 'b')
257
257
 
258
258
  rule 'S' => ['A T', 'a T']
259
- # rule 'S' => 'a T'
260
259
  rule 'A' => ['a', 'B A']
261
- # rule 'A' => 'B A'
262
260
  rule 'B' => ''
263
261
  rule 'T' => 'b b b'
264
262
  end
data/version.txt CHANGED
@@ -1 +1 @@
1
- 0.2.00
1
+ 0.2.01
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dendroid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.00
4
+ version: 0.2.01
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-16 00:00:00.000000000 Z
11
+ date: 2023-12-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: WIP. A Ruby implementation of an Earley parser
14
14
  email: famished.tiger@yahoo.com
@@ -97,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
97
  - !ruby/object:Gem::Version
98
98
  version: '0'
99
99
  requirements: []
100
- rubygems_version: 3.4.10
100
+ rubygems_version: 3.5.1
101
101
  signing_key:
102
102
  specification_version: 4
103
103
  summary: WIP. A Ruby implementation of an Earley parser