rley 0.8.14 → 0.8.15
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 +20 -2
- data/CHANGELOG.md +3 -0
- data/examples/general/calc_iter1/spec/calculator_spec.rb +9 -9
- data/examples/general/calc_iter2/spec/calculator_spec.rb +39 -39
- data/examples/general/recursive_right.rb +2 -2
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/gfg/grm_flow_graph.rb +0 -1
- data/lib/rley/parser/parse_entry_set.rb +0 -1
- data/lib/rley/parser/parse_walker_factory.rb +0 -1
- data/lib/rley/rgn/grammar_builder.rb +0 -2
- data/lib/rley/rgn/tokenizer.rb +1 -1
- data/lib/rley/syntax/base_grammar_builder.rb +0 -1
- data/lib/rley/syntax/grammar.rb +0 -1
- data/spec/rley/base/dotted_item_spec.rb +46 -46
- data/spec/rley/base/grm_items_builder_spec.rb +1 -1
- data/spec/rley/engine_spec.rb +50 -50
- data/spec/rley/formatter/asciitree_spec.rb +8 -8
- data/spec/rley/formatter/bracket_notation_spec.rb +10 -10
- data/spec/rley/formatter/debug_spec.rb +10 -10
- data/spec/rley/formatter/json_spec.rb +6 -7
- data/spec/rley/gfg/call_edge_spec.rb +6 -6
- data/spec/rley/gfg/edge_spec.rb +8 -7
- data/spec/rley/gfg/end_vertex_spec.rb +8 -7
- data/spec/rley/gfg/epsilon_edge_spec.rb +5 -4
- data/spec/rley/gfg/grm_flow_graph_spec.rb +33 -34
- data/spec/rley/gfg/item_vertex_spec.rb +34 -36
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +12 -12
- data/spec/rley/gfg/return_edge_spec.rb +6 -6
- data/spec/rley/gfg/scan_edge_spec.rb +7 -6
- data/spec/rley/gfg/shortcut_edge_spec.rb +15 -15
- data/spec/rley/gfg/start_vertex_spec.rb +8 -8
- data/spec/rley/gfg/vertex_spec.rb +18 -18
- data/spec/rley/lexical/literal_spec.rb +5 -5
- data/spec/rley/lexical/token_range_spec.rb +55 -55
- data/spec/rley/lexical/token_spec.rb +17 -16
- data/spec/rley/parse_forest_visitor_spec.rb +30 -32
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +2 -2
- data/spec/rley/parse_rep/ast_builder_spec.rb +30 -30
- data/spec/rley/parse_rep/cst_builder_spec.rb +85 -85
- data/spec/rley/parse_rep/groucho_spec.rb +23 -23
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +42 -42
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +10 -12
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +10 -15
- data/spec/rley/parse_tree_visitor_spec.rb +43 -46
- data/spec/rley/parser/dangling_else_spec.rb +12 -12
- data/spec/rley/parser/error_reason_spec.rb +37 -37
- data/spec/rley/parser/gfg_chart_spec.rb +27 -29
- data/spec/rley/parser/gfg_earley_parser_spec.rb +55 -56
- data/spec/rley/parser/gfg_parsing_spec.rb +106 -103
- data/spec/rley/parser/parse_entry_set_spec.rb +63 -61
- data/spec/rley/parser/parse_entry_spec.rb +73 -71
- data/spec/rley/parser/parse_walker_factory_spec.rb +14 -15
- data/spec/rley/ptree/non_terminal_node_spec.rb +16 -16
- data/spec/rley/ptree/parse_tree_node_spec.rb +11 -11
- data/spec/rley/ptree/parse_tree_spec.rb +6 -8
- data/spec/rley/ptree/terminal_node_spec.rb +6 -6
- data/spec/rley/rgn/grammar_builder_spec.rb +69 -67
- data/spec/rley/rgn/parser_spec.rb +63 -63
- data/spec/rley/rgn/repetition_node_spec.rb +15 -15
- data/spec/rley/rgn/sequence_node_spec.rb +10 -10
- data/spec/rley/rgn/symbol_node_spec.rb +5 -6
- data/spec/rley/rgn/tokenizer_spec.rb +68 -67
- data/spec/rley/sppf/alternative_node_spec.rb +16 -16
- data/spec/rley/sppf/non_terminal_node_spec.rb +20 -20
- data/spec/rley/sppf/token_node_spec.rb +13 -13
- data/spec/rley/syntax/base_grammar_builder_spec.rb +76 -86
- data/spec/rley/syntax/grammar_spec.rb +40 -78
- data/spec/rley/syntax/grm_symbol_spec.rb +7 -7
- data/spec/rley/syntax/match_closest_spec.rb +8 -8
- data/spec/rley/syntax/non_terminal_spec.rb +25 -25
- data/spec/rley/syntax/production_spec.rb +33 -33
- data/spec/rley/syntax/symbol_seq_spec.rb +27 -27
- data/spec/rley/syntax/terminal_spec.rb +12 -11
- data/spec/support/base_tokenizer_spec.rb +9 -8
- metadata +2 -2
@@ -13,6 +13,9 @@ require_relative '../../../lib/rley/parser/parse_entry'
|
|
13
13
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
14
14
|
module Parser # Open this namespace to avoid module qualifier prefixes
|
15
15
|
describe ParseEntry do
|
16
|
+
# Default instantiation rule
|
17
|
+
subject(:an_entry) { described_class.new(sample_vertex, origin_val) }
|
18
|
+
|
16
19
|
let(:t_a) { Syntax::Terminal.new('A') }
|
17
20
|
let(:t_b) { Syntax::Terminal.new('B') }
|
18
21
|
let(:t_c) { Syntax::Terminal.new('C') }
|
@@ -30,186 +33,185 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
30
33
|
let(:origin_val) { 3 }
|
31
34
|
let(:sample_vertex) { GFG::StartVertex.new(nt_sentence) }
|
32
35
|
let(:vertex2) { double('vertex-mock') }
|
33
|
-
|
34
|
-
subject { ParseEntry.new(sample_vertex, origin_val) }
|
36
|
+
|
35
37
|
|
36
38
|
context 'Initialization:' do
|
37
|
-
it '
|
39
|
+
it 'is created with a vertex and an origin position' do
|
38
40
|
args = [sample_vertex, origin_val]
|
39
|
-
expect {
|
41
|
+
expect { described_class.new(*args) }.not_to raise_error
|
40
42
|
end
|
41
43
|
|
42
|
-
it '
|
44
|
+
it 'complains when the vertex is nil' do
|
43
45
|
err = StandardError
|
44
46
|
msg = 'GFG vertex cannot be nil'
|
45
|
-
expect {
|
47
|
+
expect { described_class.new(nil, 2) }.to raise_error(err, msg)
|
46
48
|
end
|
47
49
|
|
48
|
-
it '
|
49
|
-
expect(
|
50
|
+
it 'knows the vertex' do
|
51
|
+
expect(an_entry.vertex).to eq(sample_vertex)
|
50
52
|
end
|
51
53
|
|
52
|
-
it '
|
53
|
-
expect(
|
54
|
+
it 'knows the origin value' do
|
55
|
+
expect(an_entry.origin).to eq(origin_val)
|
54
56
|
end
|
55
57
|
|
56
|
-
it '
|
57
|
-
expect(
|
58
|
-
expect(
|
58
|
+
it 'has not antecedent at creation' do
|
59
|
+
expect(an_entry.antecedents).to be_empty
|
60
|
+
expect(an_entry).to be_orphan
|
59
61
|
end
|
60
62
|
end # context
|
61
63
|
|
62
64
|
context 'Provided services:' do
|
63
|
-
it '
|
64
|
-
synonym =
|
65
|
-
expect(
|
65
|
+
it 'compares with itself' do
|
66
|
+
synonym = an_entry # Fool Rubocop
|
67
|
+
expect(an_entry == synonym).to be(true)
|
66
68
|
end
|
67
69
|
|
68
|
-
it '
|
69
|
-
equal =
|
70
|
-
expect(
|
70
|
+
it 'compares with another' do
|
71
|
+
equal = described_class.new(sample_vertex, origin_val)
|
72
|
+
expect(an_entry == equal).to be(true)
|
71
73
|
|
72
74
|
# Same vertex, different origin
|
73
|
-
diff_origin =
|
74
|
-
expect(
|
75
|
+
diff_origin = described_class.new(sample_vertex, 2)
|
76
|
+
expect(an_entry == diff_origin).to be(false)
|
75
77
|
|
76
78
|
# Different vertices, same origin
|
77
|
-
diff_vertex =
|
78
|
-
expect(
|
79
|
+
diff_vertex = described_class.new(double('other_sample_vertex'), 3)
|
80
|
+
expect(an_entry == diff_vertex).to be(false)
|
79
81
|
end
|
80
82
|
|
81
|
-
it '
|
82
|
-
expect(
|
83
|
+
it 'knows if the vertex is a start vertex' do
|
84
|
+
expect(an_entry).to be_start_entry
|
83
85
|
|
84
|
-
instance =
|
86
|
+
instance = described_class.new(GFG::EndVertex.new('.NT'), 3)
|
85
87
|
expect(instance).not_to be_start_entry
|
86
88
|
end
|
87
89
|
|
88
|
-
it '
|
89
|
-
expect(
|
90
|
+
it 'knows if the vertex is an end vertex' do
|
91
|
+
expect(an_entry).not_to be_end_entry
|
90
92
|
|
91
|
-
instance =
|
93
|
+
instance = described_class.new(GFG::EndVertex.new('NT.'), 3)
|
92
94
|
expect(instance).to be_end_entry
|
93
95
|
end
|
94
96
|
|
95
|
-
it '
|
96
|
-
expect(
|
97
|
+
it 'knows if the entry is a dotted item vertex' do
|
98
|
+
expect(an_entry).not_to be_dotted_entry
|
97
99
|
|
98
|
-
instance =
|
100
|
+
instance = described_class.new(GFG::ItemVertex.new('P => S.'), 3)
|
99
101
|
expect(instance).to be_dotted_entry
|
100
102
|
end
|
101
103
|
|
102
|
-
it '
|
104
|
+
it 'knows if the vertex is at end of production (if any)' do
|
103
105
|
# Case: start vertex
|
104
|
-
instance1 =
|
106
|
+
instance1 = described_class.new(GFG::StartVertex.new('.NT'), 3)
|
105
107
|
expect(instance1).not_to be_exit_entry
|
106
108
|
|
107
109
|
# Case: end vertex
|
108
|
-
instance2 =
|
110
|
+
instance2 = described_class.new(GFG::EndVertex.new('NT.'), 3)
|
109
111
|
expect(instance2).not_to be_exit_entry
|
110
112
|
|
111
113
|
# Case: item vertex not at end of rhs
|
112
114
|
v1 = double('vertex-not-at-end')
|
113
|
-
|
114
|
-
instance3 =
|
115
|
+
allow(v1).to receive(:complete?).and_return(false)
|
116
|
+
instance3 = described_class.new(v1, 3)
|
115
117
|
expect(instance3).not_to be_exit_entry
|
116
118
|
|
117
119
|
# Case: item vertex at end of rhs
|
118
120
|
v2 = double('vertex-at-end')
|
119
|
-
|
120
|
-
instance4 =
|
121
|
+
allow(v2).to receive(:complete?).and_return(true)
|
122
|
+
instance4 = described_class.new(v2, 3)
|
121
123
|
expect(instance4).to be_exit_entry
|
122
124
|
end
|
123
125
|
|
124
|
-
it '
|
126
|
+
it 'knows if the vertex is at begin of production (if any)' do
|
125
127
|
# Case: start vertex
|
126
|
-
instance1 =
|
128
|
+
instance1 = described_class.new(GFG::StartVertex.new('.NT'), 3)
|
127
129
|
expect(instance1).not_to be_entry_entry
|
128
130
|
|
129
131
|
# Case: end vertex
|
130
|
-
instance2 =
|
132
|
+
instance2 = described_class.new(GFG::EndVertex.new('NT.'), 3)
|
131
133
|
expect(instance2).not_to be_entry_entry
|
132
134
|
|
133
135
|
# Case: item vertex not at begin of rhs
|
134
136
|
d1 = Base::DottedItem.new(sample_prod, 1)
|
135
137
|
v1 = GFG::ItemVertex.new(d1)
|
136
|
-
instance3 =
|
138
|
+
instance3 = described_class.new(v1, 3)
|
137
139
|
expect(instance3).not_to be_entry_entry
|
138
140
|
|
139
141
|
# Case: item vertex at end of rhs
|
140
142
|
d2 = Base::DottedItem.new(sample_prod, 0)
|
141
143
|
v2 = GFG::ItemVertex.new(d2)
|
142
|
-
instance4 =
|
144
|
+
instance4 = described_class.new(v2, 3)
|
143
145
|
expect(instance4).to be_entry_entry
|
144
146
|
end
|
145
147
|
|
146
|
-
it '
|
148
|
+
it 'knows the symbol before the dot (if any)' do
|
147
149
|
# Case: start vertex
|
148
|
-
instance1 =
|
150
|
+
instance1 = described_class.new(GFG::StartVertex.new('.NT'), 3)
|
149
151
|
expect(instance1.prev_symbol).to be_nil
|
150
152
|
|
151
153
|
# Case: end vertex
|
152
|
-
instance2 =
|
154
|
+
instance2 = described_class.new(GFG::EndVertex.new('NT.'), 3)
|
153
155
|
expect(instance2.prev_symbol).to be_nil # Really correct?
|
154
156
|
|
155
157
|
# Case: item vertex not at start of rhs
|
156
158
|
v1 = double('vertex-not-at-start')
|
157
|
-
|
158
|
-
instance3 =
|
159
|
+
allow(v1).to receive(:prev_symbol).and_return('symbol')
|
160
|
+
instance3 = described_class.new(v1, 3)
|
159
161
|
expect(instance3.prev_symbol).to eq('symbol')
|
160
162
|
|
161
163
|
# Case: item vertex at start of rhs
|
162
164
|
v2 = double('vertex-at-start')
|
163
|
-
|
164
|
-
instance4 =
|
165
|
+
allow(v2).to receive(:prev_symbol).and_return(nil)
|
166
|
+
instance4 = described_class.new(v2, 0)
|
165
167
|
expect(instance4.prev_symbol).to be_nil
|
166
168
|
end
|
167
169
|
|
168
|
-
it '
|
170
|
+
it 'knows the next expected symbol (if any)' do
|
169
171
|
# Case: start vertex
|
170
|
-
instance1 =
|
172
|
+
instance1 = described_class.new(GFG::StartVertex.new('.NT'), 3)
|
171
173
|
expect(instance1.next_symbol).to be_nil
|
172
174
|
|
173
175
|
# Case: end vertex
|
174
|
-
instance2 =
|
176
|
+
instance2 = described_class.new(GFG::EndVertex.new('NT.'), 3)
|
175
177
|
expect(instance2.next_symbol).to be_nil
|
176
178
|
|
177
179
|
# Case: item vertex not at end of rhs
|
178
180
|
v1 = double('vertex-not-at-end')
|
179
|
-
|
180
|
-
instance3 =
|
181
|
+
allow(v1).to receive(:next_symbol).and_return('symbol')
|
182
|
+
instance3 = described_class.new(v1, 3)
|
181
183
|
expect(instance3.next_symbol).to eq('symbol')
|
182
184
|
|
183
185
|
# Case: item vertex at end of rhs
|
184
186
|
v2 = double('vertex-at-end')
|
185
|
-
|
186
|
-
instance4 =
|
187
|
+
allow(v2).to receive(:next_symbol).and_return(nil)
|
188
|
+
instance4 = described_class.new(v2, 3)
|
187
189
|
expect(instance4.next_symbol).to be_nil
|
188
190
|
end
|
189
191
|
|
190
|
-
it '
|
191
|
-
antecedent =
|
192
|
-
|
193
|
-
expect(
|
194
|
-
expect(
|
192
|
+
it 'accepts antecedents' do
|
193
|
+
antecedent = described_class.new(vertex2, origin_val)
|
194
|
+
an_entry.add_antecedent(antecedent)
|
195
|
+
expect(an_entry.antecedents).to eql([antecedent])
|
196
|
+
expect(an_entry).not_to be_orphan
|
195
197
|
end
|
196
198
|
|
197
|
-
it '
|
199
|
+
it 'knows its text representation' do
|
198
200
|
expected = '.sentence | 3'
|
199
|
-
expect(
|
201
|
+
expect(an_entry.to_s).to eq(expected)
|
200
202
|
end
|
201
203
|
|
202
|
-
it '
|
203
|
-
|
204
|
+
it 'is be inspectable' do
|
205
|
+
an_entry.add_antecedent(an_entry) # Cheat for the good cause...
|
204
206
|
# expected = '.sentence | 3'
|
205
207
|
prefix = /^#<Rley::Parser::ParseEntry:\d+ @vertex/
|
206
|
-
expect(
|
208
|
+
expect(an_entry.inspect).to match(prefix)
|
207
209
|
pattern = /@vertex=<Rley::GFG::StartVertex:\d+ label=\.sentence/
|
208
|
-
expect(
|
210
|
+
expect(an_entry.inspect).to match(pattern)
|
209
211
|
pattern2 = /@origin=3 @antecedents=\[/
|
210
|
-
expect(
|
212
|
+
expect(an_entry.inspect).to match(pattern2)
|
211
213
|
suffix = /<Rley::GFG::StartVertex:\d+ label=\.sentence> @origin=3\]>$/
|
212
|
-
expect(
|
214
|
+
expect(an_entry.inspect).to match(suffix)
|
213
215
|
end
|
214
216
|
end # context
|
215
217
|
end # describe
|
@@ -11,7 +11,6 @@ require_relative '../../../lib/rley/parser/gfg_earley_parser'
|
|
11
11
|
# Load the class under test
|
12
12
|
require_relative '../../../lib/rley/parser/parse_walker_factory'
|
13
13
|
|
14
|
-
|
15
14
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
16
15
|
module Parser
|
17
16
|
describe ParseWalkerFactory do
|
@@ -40,6 +39,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
40
39
|
expect(index).to eq(expectations[2])
|
41
40
|
end
|
42
41
|
|
42
|
+
subject(:a_factory) { described_class.new }
|
43
|
+
|
43
44
|
let(:sample_grammar) do
|
44
45
|
# Grammar based on paper from Elisabeth Scott
|
45
46
|
# "SPPF=Style Parsing From Earley Recognizers" in
|
@@ -69,31 +70,29 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
69
70
|
|
70
71
|
let(:accept_entry) { sample_result.accepting_entry }
|
71
72
|
let(:accept_index) { sample_result.chart.last_index }
|
72
|
-
subject { ParseWalkerFactory.new }
|
73
|
-
|
74
73
|
|
75
74
|
context 'Initialization:' do
|
76
|
-
it '
|
77
|
-
expect {
|
75
|
+
it 'is created without argument' do
|
76
|
+
expect { described_class.new }.not_to raise_error
|
78
77
|
end
|
79
78
|
end # context
|
80
79
|
|
81
80
|
context 'Parse graph traversal:' do
|
82
|
-
it '
|
81
|
+
it 'creates an Enumerator as a walker' do
|
83
82
|
entry = accept_entry
|
84
83
|
index = accept_index
|
85
|
-
expect(
|
84
|
+
expect(a_factory.build_walker(entry, index)).to be_a(Enumerator)
|
86
85
|
end
|
87
86
|
|
88
|
-
it '
|
89
|
-
walker =
|
87
|
+
it 'returns the accepting parse entry in the first place' do
|
88
|
+
walker = a_factory.build_walker(accept_entry, accept_index, false)
|
90
89
|
first_event = walker.next
|
91
90
|
expectations = [:visit, sample_result.accepting_entry, 4]
|
92
91
|
event_expectations(first_event, expectations)
|
93
92
|
end
|
94
93
|
|
95
|
-
it '
|
96
|
-
walker =
|
94
|
+
it 'traverses the parse graph backwards' do
|
95
|
+
walker = a_factory.build_walker(accept_entry, accept_index, false)
|
97
96
|
event1 = walker.next
|
98
97
|
expectations = [:visit, 'Phi. | 0', 4]
|
99
98
|
event_expectations(event1, expectations)
|
@@ -295,8 +294,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
295
294
|
end
|
296
295
|
|
297
296
|
|
298
|
-
it '
|
299
|
-
walker =
|
297
|
+
it 'traverses lazily the parse graph backwards' do
|
298
|
+
walker = a_factory.build_walker(accept_entry, accept_index, true)
|
300
299
|
|
301
300
|
17.times { walker.next }
|
302
301
|
|
@@ -397,8 +396,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
397
396
|
event_expectations(event40, expectations)
|
398
397
|
end
|
399
398
|
|
400
|
-
it '
|
401
|
-
walker =
|
399
|
+
it 'raises an exception at end of visit' do
|
400
|
+
walker = a_factory.build_walker(accept_entry, accept_index, true)
|
402
401
|
40.times { walker.next }
|
403
402
|
|
404
403
|
expect { walker.next }.to raise_error(StopIteration)
|
@@ -15,16 +15,16 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
15
15
|
return Lexical::TokenRange.new(low: low, high: high)
|
16
16
|
end
|
17
17
|
|
18
|
+
subject(:a_node) { described_class.new(sample_symbol, sample_range) }
|
19
|
+
|
18
20
|
let(:sample_symbol) do
|
19
21
|
OpenStruct.new(name: 'VP')
|
20
22
|
end
|
21
23
|
let(:sample_range) { range(0, 3) }
|
22
24
|
|
23
|
-
subject { NonTerminalNode.new(sample_symbol, sample_range) }
|
24
|
-
|
25
25
|
context 'Initialization:' do
|
26
|
-
it "
|
27
|
-
expect(
|
26
|
+
it "doesn't have subnodes yet" do
|
27
|
+
expect(a_node.subnodes).to be_empty
|
28
28
|
end
|
29
29
|
end # context
|
30
30
|
|
@@ -34,36 +34,36 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
34
34
|
return OpenStruct.new(lexeme: aLexeme, terminal: terminal)
|
35
35
|
end
|
36
36
|
|
37
|
-
it '
|
37
|
+
it 'accepts the addition of subnodes' do
|
38
38
|
child1 = double('first_child')
|
39
39
|
child2 = double('second_child')
|
40
40
|
child3 = double('third_child')
|
41
|
-
expect {
|
42
|
-
|
43
|
-
|
44
|
-
expect(
|
41
|
+
expect { a_node.add_subnode(child1) }.not_to raise_error
|
42
|
+
a_node.add_subnode(child2)
|
43
|
+
a_node.add_subnode(child3)
|
44
|
+
expect(a_node.subnodes).to eq([child3, child2, child1])
|
45
45
|
end
|
46
46
|
|
47
47
|
# rubocop: disable Naming/VariableNumber
|
48
|
-
it '
|
48
|
+
it 'provides a text representation of itself' do
|
49
49
|
# Case 1: no child
|
50
50
|
expected_text = 'VP[0, 3]'
|
51
|
-
expect(
|
51
|
+
expect(a_node.to_string(0)).to eq(expected_text)
|
52
52
|
|
53
53
|
# Case 2: with subnodes
|
54
54
|
verb = build_token('catch', 'Verb')
|
55
55
|
child_1_1 = TerminalNode.new(verb, range(0, 1))
|
56
56
|
np = OpenStruct.new(name: 'NP')
|
57
|
-
child_1_2 =
|
57
|
+
child_1_2 = described_class.new(np, range(1, 3))
|
58
58
|
det = build_token('that', 'Determiner')
|
59
59
|
child_2_1 = TerminalNode.new(det, range(1, 2))
|
60
60
|
nominal = OpenStruct.new(name: 'Nominal')
|
61
|
-
child_2_2 =
|
61
|
+
child_2_2 = described_class.new(nominal, range(2, 3))
|
62
62
|
noun = build_token('bus', 'Noun')
|
63
63
|
child_3_1 = TerminalNode.new(noun, range(2, 3))
|
64
64
|
# We reverse the sequence of subnode addition
|
65
|
-
|
66
|
-
|
65
|
+
a_node.add_subnode(child_1_2)
|
66
|
+
a_node.add_subnode(child_1_1)
|
67
67
|
child_1_2.add_subnode(child_2_2)
|
68
68
|
child_1_2.add_subnode(child_2_1)
|
69
69
|
child_2_2.add_subnode(child_3_1)
|
@@ -75,7 +75,7 @@ VP[0, 3]
|
|
75
75
|
+- Nominal[2, 3]
|
76
76
|
+- Noun[2, 3]: 'bus'
|
77
77
|
SNIPPET
|
78
|
-
expect(
|
78
|
+
expect(a_node.to_string(0)).to eq(expected_text.chomp)
|
79
79
|
end
|
80
80
|
# rubocop: enable Naming/VariableNumber
|
81
81
|
end # context
|
@@ -8,30 +8,30 @@ require_relative '../../../lib/rley/ptree/parse_tree_node'
|
|
8
8
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
9
9
|
module PTree # Open this namespace to avoid module qualifier prefixes
|
10
10
|
describe ParseTreeNode do
|
11
|
+
subject(:a_node) { described_class.new(sample_symbol, sample_range) }
|
12
|
+
|
11
13
|
let(:sample_symbol) { double('fake-symbol') }
|
12
14
|
let(:sample_range) { { low: 0, high: 5 } }
|
13
15
|
|
14
|
-
subject { ParseTreeNode.new(sample_symbol, sample_range) }
|
15
|
-
|
16
16
|
context 'Initialization:' do
|
17
|
-
it '
|
17
|
+
it 'is created with a symbol and a range' do
|
18
18
|
args = [sample_symbol, sample_range]
|
19
|
-
expect {
|
19
|
+
expect { described_class.new(*args) }.not_to raise_error
|
20
20
|
end
|
21
21
|
|
22
|
-
it '
|
23
|
-
expect(
|
22
|
+
it 'knows its symbol' do
|
23
|
+
expect(a_node.symbol).to eq(sample_symbol)
|
24
24
|
end
|
25
25
|
|
26
|
-
it '
|
27
|
-
expect(
|
26
|
+
it 'knows its range' do
|
27
|
+
expect(a_node.range).to eq(sample_range)
|
28
28
|
end
|
29
29
|
end # context
|
30
30
|
|
31
|
-
context '
|
32
|
-
it '
|
31
|
+
context 'Provided services:' do
|
32
|
+
it 'assigns undefined range bounds' do
|
33
33
|
partial_range = { low: 0 } # High bound left undefined
|
34
|
-
instance =
|
34
|
+
instance = described_class.new(sample_symbol, partial_range)
|
35
35
|
|
36
36
|
another = { low: 1, high: 4 } # High bound is specified
|
37
37
|
instance.range = another
|
@@ -13,6 +13,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
13
13
|
describe ParseTree do
|
14
14
|
include GrammarABCHelper # Mix-in module with builder for grammar abc
|
15
15
|
|
16
|
+
subject(:ptree) { described_class.new(sample_root) }
|
17
|
+
|
16
18
|
let(:sample_grammar) do
|
17
19
|
builder = grammar_abc_builder
|
18
20
|
builder.grammar
|
@@ -22,17 +24,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
22
24
|
let(:sample_range) { { low: 0, high: 5 } }
|
23
25
|
let(:sample_root) { ParseTreeNode.new(sample_prod.lhs, sample_range) }
|
24
26
|
|
25
|
-
subject do
|
26
|
-
ParseTree.new(sample_root)
|
27
|
-
end
|
28
|
-
|
29
27
|
context 'Initialization:' do
|
30
|
-
it '
|
31
|
-
expect {
|
28
|
+
it 'is created with a root node' do
|
29
|
+
expect { described_class.new(sample_root) }.not_to raise_error
|
32
30
|
end
|
33
31
|
|
34
|
-
it '
|
35
|
-
its_root =
|
32
|
+
it 'knows its root node' do
|
33
|
+
its_root = ptree.root
|
36
34
|
expect(its_root.symbol.name).to eq('S')
|
37
35
|
expect(its_root.range).to eq(sample_range)
|
38
36
|
end
|
@@ -9,24 +9,24 @@ require_relative '../../../lib/rley/ptree/terminal_node'
|
|
9
9
|
module Rley # Open this namespace to avoid module qualifier prefixes
|
10
10
|
module PTree # Open this namespace to avoid module qualifier prefixes
|
11
11
|
describe TerminalNode do
|
12
|
+
subject(:a_node) { described_class.new(sample_token, sample_range) }
|
13
|
+
|
12
14
|
let(:sample_symbol) { OpenStruct.new(name: 'Noun') }
|
13
15
|
let(:sample_token) do
|
14
16
|
OpenStruct.new(lexeme: 'world', terminal: sample_symbol)
|
15
17
|
end
|
16
18
|
let(:sample_range) { double('fake-range') }
|
17
19
|
|
18
|
-
subject { TerminalNode.new(sample_token, sample_range) }
|
19
|
-
|
20
20
|
context 'Initialization:' do
|
21
|
-
it '
|
22
|
-
expect(
|
21
|
+
it 'is bound to a token' do
|
22
|
+
expect(a_node.token).to eq(sample_token)
|
23
23
|
end
|
24
24
|
end # context
|
25
25
|
|
26
26
|
context 'Provided services:' do
|
27
|
-
it '
|
27
|
+
it 'provides a text representation of itself' do
|
28
28
|
expected_text = "Noun[?, ?]: 'world'"
|
29
|
-
expect(
|
29
|
+
expect(a_node.to_string(0)).to eq(expected_text)
|
30
30
|
end
|
31
31
|
end # context
|
32
32
|
end # describe
|