rley 0.7.08 → 0.8.03
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 +29 -5
- data/CHANGELOG.md +28 -4
- data/README.md +4 -5
- data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
- data/examples/NLP/nano_eng/nano_grammar.rb +18 -18
- data/examples/data_formats/JSON/json_ast_builder.rb +9 -18
- data/examples/data_formats/JSON/json_demo.rb +1 -2
- data/examples/data_formats/JSON/json_grammar.rb +11 -11
- data/examples/general/calc_iter1/calc_grammar.rb +5 -4
- data/examples/general/calc_iter2/calc_grammar.rb +9 -9
- data/examples/general/left.rb +1 -1
- data/examples/general/right.rb +1 -1
- data/lib/rley/base/dotted_item.rb +5 -0
- data/lib/rley/base/grm_items_builder.rb +6 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/engine.rb +2 -2
- data/lib/rley/interface.rb +16 -0
- data/lib/rley/notation/all_notation_nodes.rb +4 -0
- data/lib/rley/notation/ast_builder.rb +185 -0
- data/lib/rley/notation/ast_node.rb +44 -0
- data/lib/rley/notation/ast_visitor.rb +115 -0
- data/lib/rley/notation/grammar.rb +49 -0
- data/lib/rley/notation/grammar_builder.rb +505 -0
- data/lib/rley/notation/grouping_node.rb +23 -0
- data/lib/rley/notation/parser.rb +56 -0
- data/lib/rley/notation/sequence_node.rb +35 -0
- data/lib/rley/notation/symbol_node.rb +29 -0
- data/lib/rley/notation/tokenizer.rb +180 -0
- data/lib/rley/parse_rep/ast_base_builder.rb +44 -0
- data/lib/rley/parser/gfg_chart.rb +101 -6
- data/lib/rley/parser/gfg_earley_parser.rb +1 -1
- data/lib/rley/parser/gfg_parsing.rb +5 -3
- data/lib/rley/parser/parse_entry_set.rb +1 -1
- data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +53 -15
- data/lib/rley/syntax/grm_symbol.rb +1 -1
- data/lib/rley/syntax/match_closest.rb +43 -0
- data/lib/rley/syntax/production.rb +6 -0
- data/lib/rley.rb +1 -1
- data/spec/rley/engine_spec.rb +6 -6
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
- data/spec/rley/notation/grammar_builder_spec.rb +302 -0
- data/spec/rley/notation/parser_spec.rb +183 -0
- data/spec/rley/notation/tokenizer_spec.rb +364 -0
- data/spec/rley/parse_rep/ast_builder_spec.rb +0 -1
- data/spec/rley/parse_rep/groucho_spec.rb +1 -1
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +1 -1
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +2 -2
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +1 -1
- data/spec/rley/parser/dangling_else_spec.rb +447 -0
- data/spec/rley/parser/gfg_earley_parser_spec.rb +118 -10
- data/spec/rley/parser/gfg_parsing_spec.rb +2 -1
- data/spec/rley/parser/parse_walker_factory_spec.rb +2 -2
- data/spec/rley/support/ambiguous_grammar_helper.rb +2 -2
- data/spec/rley/support/grammar_abc_helper.rb +2 -2
- data/spec/rley/support/grammar_ambig01_helper.rb +2 -2
- data/spec/rley/support/grammar_arr_int_helper.rb +2 -2
- data/spec/rley/support/grammar_b_expr_helper.rb +2 -2
- data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
- data/spec/rley/support/grammar_l0_helper.rb +2 -2
- data/spec/rley/support/grammar_pb_helper.rb +2 -2
- data/spec/rley/support/grammar_sppf_helper.rb +2 -2
- data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +29 -11
- data/spec/rley/syntax/match_closest_spec.rb +46 -0
- data/spec/rley/syntax/production_spec.rb +4 -0
- metadata +29 -14
- data/lib/rley/parser/parse_state.rb +0 -78
- data/lib/rley/parser/parse_state_tracker.rb +0 -59
- data/lib/rley/parser/state_set.rb +0 -100
- data/spec/rley/parser/parse_state_spec.rb +0 -125
- data/spec/rley/parser/parse_tracer_spec.rb +0 -200
- data/spec/rley/parser/state_set_spec.rb +0 -130
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper'
|
4
|
+
|
5
|
+
require_relative '../../../lib/rley/syntax/terminal'
|
6
|
+
require_relative '../../../lib/rley/syntax/non_terminal'
|
7
|
+
require_relative '../../../lib/rley/syntax/symbol_seq'
|
8
|
+
|
9
|
+
# Load the class under test
|
10
|
+
require_relative '../../../lib/rley/syntax/production'
|
11
|
+
|
12
|
+
# Load the class under test
|
13
|
+
require_relative '../../../lib/rley/syntax/match_closest'
|
14
|
+
|
15
|
+
module Rley # Open this namespace to avoid module qualifier prefixes
|
16
|
+
module Syntax # Open this namespace to avoid module qualifier prefixes
|
17
|
+
describe MatchClosest do
|
18
|
+
# 'stmt' => 'IF boolean THEN stmt ELSE stmt'
|
19
|
+
let(:boolean) { NonTerminal.new('boolean') }
|
20
|
+
let(:stmt) { NonTerminal.new('stmt') }
|
21
|
+
let(:if_t) { Terminal.new('IF') }
|
22
|
+
let(:then_t) { Terminal.new('THEN') }
|
23
|
+
let(:else_t) { Terminal.new('ELSE') }
|
24
|
+
let(:sequence) { [if_t, boolean, then_t, stmt, else_t, stmt] }
|
25
|
+
let(:prod) { Production.new(stmt, sequence) }
|
26
|
+
|
27
|
+
subject { MatchClosest.new(prod.rhs.members, 4, 'IF') }
|
28
|
+
|
29
|
+
context 'Initialization:' do
|
30
|
+
it 'should be created with an symbol seq., an indice and a name' do
|
31
|
+
expect { MatchClosest.new(prod.rhs.members, 4, 'IF') }.not_to raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should know the index argument' do
|
35
|
+
expect(subject.idx_symbol).to eq(4) # ELSE at position 4
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should know the name of preceding symbol to pair with' do
|
39
|
+
expect(subject.closest_symb).to eq('IF')
|
40
|
+
end
|
41
|
+
end # context
|
42
|
+
end # describe
|
43
|
+
end # module
|
44
|
+
end # module
|
45
|
+
|
46
|
+
# End of file
|
@@ -43,6 +43,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
43
43
|
expect(subject.body).to eq(sequence)
|
44
44
|
end
|
45
45
|
|
46
|
+
it 'should be free from constraints at start' do
|
47
|
+
expect(subject.constraints).to be_empty
|
48
|
+
end
|
49
|
+
|
46
50
|
it 'should know whether its rhs is empty' do
|
47
51
|
expect(subject).not_to be_empty
|
48
52
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rley
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.03
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -136,8 +136,20 @@ files:
|
|
136
136
|
- lib/rley/gfg/shortcut_edge.rb
|
137
137
|
- lib/rley/gfg/start_vertex.rb
|
138
138
|
- lib/rley/gfg/vertex.rb
|
139
|
+
- lib/rley/interface.rb
|
139
140
|
- lib/rley/lexical/token.rb
|
140
141
|
- lib/rley/lexical/token_range.rb
|
142
|
+
- lib/rley/notation/all_notation_nodes.rb
|
143
|
+
- lib/rley/notation/ast_builder.rb
|
144
|
+
- lib/rley/notation/ast_node.rb
|
145
|
+
- lib/rley/notation/ast_visitor.rb
|
146
|
+
- lib/rley/notation/grammar.rb
|
147
|
+
- lib/rley/notation/grammar_builder.rb
|
148
|
+
- lib/rley/notation/grouping_node.rb
|
149
|
+
- lib/rley/notation/parser.rb
|
150
|
+
- lib/rley/notation/sequence_node.rb
|
151
|
+
- lib/rley/notation/symbol_node.rb
|
152
|
+
- lib/rley/notation/tokenizer.rb
|
141
153
|
- lib/rley/parse_forest_visitor.rb
|
142
154
|
- lib/rley/parse_rep/ast_base_builder.rb
|
143
155
|
- lib/rley/parse_rep/cst_builder.rb
|
@@ -154,11 +166,8 @@ files:
|
|
154
166
|
- lib/rley/parser/parse_entry.rb
|
155
167
|
- lib/rley/parser/parse_entry_set.rb
|
156
168
|
- lib/rley/parser/parse_entry_tracker.rb
|
157
|
-
- lib/rley/parser/parse_state.rb
|
158
|
-
- lib/rley/parser/parse_state_tracker.rb
|
159
169
|
- lib/rley/parser/parse_tracer.rb
|
160
170
|
- lib/rley/parser/parse_walker_factory.rb
|
161
|
-
- lib/rley/parser/state_set.rb
|
162
171
|
- lib/rley/ptree/non_terminal_node.rb
|
163
172
|
- lib/rley/ptree/parse_tree.rb
|
164
173
|
- lib/rley/ptree/parse_tree_node.rb
|
@@ -172,10 +181,11 @@ files:
|
|
172
181
|
- lib/rley/sppf/parse_forest.rb
|
173
182
|
- lib/rley/sppf/sppf_node.rb
|
174
183
|
- lib/rley/sppf/token_node.rb
|
184
|
+
- lib/rley/syntax/base_grammar_builder.rb
|
175
185
|
- lib/rley/syntax/grammar.rb
|
176
|
-
- lib/rley/syntax/grammar_builder.rb
|
177
186
|
- lib/rley/syntax/grm_symbol.rb
|
178
187
|
- lib/rley/syntax/literal.rb
|
188
|
+
- lib/rley/syntax/match_closest.rb
|
179
189
|
- lib/rley/syntax/non_terminal.rb
|
180
190
|
- lib/rley/syntax/production.rb
|
181
191
|
- lib/rley/syntax/symbol_seq.rb
|
@@ -203,6 +213,9 @@ files:
|
|
203
213
|
- spec/rley/gfg/vertex_spec.rb
|
204
214
|
- spec/rley/lexical/token_range_spec.rb
|
205
215
|
- spec/rley/lexical/token_spec.rb
|
216
|
+
- spec/rley/notation/grammar_builder_spec.rb
|
217
|
+
- spec/rley/notation/parser_spec.rb
|
218
|
+
- spec/rley/notation/tokenizer_spec.rb
|
206
219
|
- spec/rley/parse_forest_visitor_spec.rb
|
207
220
|
- spec/rley/parse_rep/ambiguous_parse_spec.rb
|
208
221
|
- spec/rley/parse_rep/ast_builder_spec.rb
|
@@ -212,16 +225,14 @@ files:
|
|
212
225
|
- spec/rley/parse_rep/parse_forest_factory_spec.rb
|
213
226
|
- spec/rley/parse_rep/parse_tree_factory_spec.rb
|
214
227
|
- spec/rley/parse_tree_visitor_spec.rb
|
228
|
+
- spec/rley/parser/dangling_else_spec.rb
|
215
229
|
- spec/rley/parser/error_reason_spec.rb
|
216
230
|
- spec/rley/parser/gfg_chart_spec.rb
|
217
231
|
- spec/rley/parser/gfg_earley_parser_spec.rb
|
218
232
|
- spec/rley/parser/gfg_parsing_spec.rb
|
219
233
|
- spec/rley/parser/parse_entry_set_spec.rb
|
220
234
|
- spec/rley/parser/parse_entry_spec.rb
|
221
|
-
- spec/rley/parser/parse_state_spec.rb
|
222
|
-
- spec/rley/parser/parse_tracer_spec.rb
|
223
235
|
- spec/rley/parser/parse_walker_factory_spec.rb
|
224
|
-
- spec/rley/parser/state_set_spec.rb
|
225
236
|
- spec/rley/ptree/non_terminal_node_spec.rb
|
226
237
|
- spec/rley/ptree/parse_tree_node_spec.rb
|
227
238
|
- spec/rley/ptree/parse_tree_spec.rb
|
@@ -236,13 +247,15 @@ files:
|
|
236
247
|
- spec/rley/support/grammar_arr_int_helper.rb
|
237
248
|
- spec/rley/support/grammar_b_expr_helper.rb
|
238
249
|
- spec/rley/support/grammar_helper.rb
|
250
|
+
- spec/rley/support/grammar_int_seq_helper.rb
|
239
251
|
- spec/rley/support/grammar_l0_helper.rb
|
240
252
|
- spec/rley/support/grammar_pb_helper.rb
|
241
253
|
- spec/rley/support/grammar_sppf_helper.rb
|
242
|
-
- spec/rley/syntax/
|
254
|
+
- spec/rley/syntax/base_grammar_builder_spec.rb
|
243
255
|
- spec/rley/syntax/grammar_spec.rb
|
244
256
|
- spec/rley/syntax/grm_symbol_spec.rb
|
245
257
|
- spec/rley/syntax/literal_spec.rb
|
258
|
+
- spec/rley/syntax/match_closest_spec.rb
|
246
259
|
- spec/rley/syntax/non_terminal_spec.rb
|
247
260
|
- spec/rley/syntax/production_spec.rb
|
248
261
|
- spec/rley/syntax/symbol_seq_spec.rb
|
@@ -299,16 +312,17 @@ test_files:
|
|
299
312
|
- spec/rley/gfg/vertex_spec.rb
|
300
313
|
- spec/rley/lexical/token_range_spec.rb
|
301
314
|
- spec/rley/lexical/token_spec.rb
|
315
|
+
- spec/rley/notation/grammar_builder_spec.rb
|
316
|
+
- spec/rley/notation/parser_spec.rb
|
317
|
+
- spec/rley/notation/tokenizer_spec.rb
|
318
|
+
- spec/rley/parser/dangling_else_spec.rb
|
302
319
|
- spec/rley/parser/error_reason_spec.rb
|
303
320
|
- spec/rley/parser/gfg_chart_spec.rb
|
304
321
|
- spec/rley/parser/gfg_earley_parser_spec.rb
|
305
322
|
- spec/rley/parser/gfg_parsing_spec.rb
|
306
323
|
- spec/rley/parser/parse_entry_set_spec.rb
|
307
324
|
- spec/rley/parser/parse_entry_spec.rb
|
308
|
-
- spec/rley/parser/parse_state_spec.rb
|
309
|
-
- spec/rley/parser/parse_tracer_spec.rb
|
310
325
|
- spec/rley/parser/parse_walker_factory_spec.rb
|
311
|
-
- spec/rley/parser/state_set_spec.rb
|
312
326
|
- spec/rley/parse_forest_visitor_spec.rb
|
313
327
|
- spec/rley/parse_rep/ambiguous_parse_spec.rb
|
314
328
|
- spec/rley/parse_rep/ast_builder_spec.rb
|
@@ -325,10 +339,11 @@ test_files:
|
|
325
339
|
- spec/rley/sppf/alternative_node_spec.rb
|
326
340
|
- spec/rley/sppf/non_terminal_node_spec.rb
|
327
341
|
- spec/rley/sppf/token_node_spec.rb
|
328
|
-
- spec/rley/syntax/
|
342
|
+
- spec/rley/syntax/base_grammar_builder_spec.rb
|
329
343
|
- spec/rley/syntax/grammar_spec.rb
|
330
344
|
- spec/rley/syntax/grm_symbol_spec.rb
|
331
345
|
- spec/rley/syntax/literal_spec.rb
|
346
|
+
- spec/rley/syntax/match_closest_spec.rb
|
332
347
|
- spec/rley/syntax/non_terminal_spec.rb
|
333
348
|
- spec/rley/syntax/production_spec.rb
|
334
349
|
- spec/rley/syntax/symbol_seq_spec.rb
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module Parser # This module is used as a namespace
|
5
|
-
class ParseState
|
6
|
-
attr_reader(:dotted_rule)
|
7
|
-
|
8
|
-
# the position in the input that matches the beginning of the rhs
|
9
|
-
# of the production.
|
10
|
-
attr_reader(:origin)
|
11
|
-
|
12
|
-
def initialize(aDottedRule, theOrigin)
|
13
|
-
@dotted_rule = valid_dotted_rule(aDottedRule)
|
14
|
-
@origin = theOrigin
|
15
|
-
end
|
16
|
-
|
17
|
-
# Equality comparison. A parse state behaves as a value object.
|
18
|
-
def ==(other)
|
19
|
-
return true if equal?(other)
|
20
|
-
|
21
|
-
(dotted_rule == other.dotted_rule) &&
|
22
|
-
(origin == other.origin)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Returns true if the dot is at the end of the rhs of the production.
|
26
|
-
# In other words, the complete rhs matches the input.
|
27
|
-
def complete?
|
28
|
-
dotted_rule.reduce_item?
|
29
|
-
end
|
30
|
-
|
31
|
-
# Returns true if the dot is at the start of the rhs of the production.
|
32
|
-
def predicted?
|
33
|
-
dotted_rule.predicted_item?
|
34
|
-
end
|
35
|
-
|
36
|
-
# Next expected symbol in the production
|
37
|
-
def next_symbol
|
38
|
-
dotted_rule.next_symbol
|
39
|
-
end
|
40
|
-
|
41
|
-
# Does this parse state have the 'other' as successor?
|
42
|
-
def precedes?(other)
|
43
|
-
return false if other == self
|
44
|
-
|
45
|
-
return false unless origin == other.origin
|
46
|
-
|
47
|
-
other_production = other.dotted_rule.production
|
48
|
-
return false unless dotted_rule.production == other_production
|
49
|
-
|
50
|
-
prev_position = other.dotted_rule.prev_position
|
51
|
-
if prev_position.nil?
|
52
|
-
false
|
53
|
-
else
|
54
|
-
dotted_rule.position == prev_position
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Give a String representation of itself.
|
59
|
-
# The format of the text representation is
|
60
|
-
# "format of dotted rule" + " | " + origin
|
61
|
-
# @return [String]
|
62
|
-
def to_s
|
63
|
-
dotted_rule.to_s + " | #{origin}"
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
# Return the validated dotted item(rule)
|
69
|
-
def valid_dotted_rule(aDottedRule)
|
70
|
-
raise StandardError, 'Dotted item cannot be nil' if aDottedRule.nil?
|
71
|
-
|
72
|
-
aDottedRule
|
73
|
-
end
|
74
|
-
end # class
|
75
|
-
end # module
|
76
|
-
end # module
|
77
|
-
|
78
|
-
# End of file
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rley # This module is used as a namespace
|
4
|
-
module Parser # This module is used as a namespace
|
5
|
-
# Helper class that keeps track of the parse states used
|
6
|
-
# while a Parsing instance is constructing a parse tree.
|
7
|
-
class ParseStateTracker
|
8
|
-
# The index of the current state set
|
9
|
-
attr_reader(:state_set_index)
|
10
|
-
|
11
|
-
# The current parse state
|
12
|
-
attr_reader(:parse_state)
|
13
|
-
|
14
|
-
# The already processed states from current state set
|
15
|
-
attr_reader(:processed_states)
|
16
|
-
|
17
|
-
# Constructor. Refined variant of the inherited constructor.
|
18
|
-
def initialize(aStateSetIndex)
|
19
|
-
self.state_set_index = aStateSetIndex
|
20
|
-
end
|
21
|
-
|
22
|
-
# Write accessor. Sets the value of the state set index
|
23
|
-
def state_set_index=(anIndex)
|
24
|
-
@state_set_index = anIndex
|
25
|
-
@processed_states = {}
|
26
|
-
end
|
27
|
-
|
28
|
-
# Write accessor. Set the given parse state as the current one.
|
29
|
-
def parse_state=(aParseState)
|
30
|
-
raise StandardError, 'Nil parse state' if aParseState.nil?
|
31
|
-
|
32
|
-
@parse_state = aParseState
|
33
|
-
processed_states[parse_state] = true
|
34
|
-
end
|
35
|
-
|
36
|
-
# Take the first provided state that wasn't processed yet.
|
37
|
-
def select_state(theStates)
|
38
|
-
a_state = theStates.find { |st| !processed_states.include?(st) }
|
39
|
-
self.parse_state = a_state
|
40
|
-
end
|
41
|
-
|
42
|
-
# The dotted item for the current parse state.
|
43
|
-
def curr_dotted_item
|
44
|
-
parse_state.dotted_rule
|
45
|
-
end
|
46
|
-
|
47
|
-
def symbol_on_left
|
48
|
-
return curr_dotted_item.prev_symbol
|
49
|
-
end
|
50
|
-
|
51
|
-
# Notification that one begins with the previous state set
|
52
|
-
def to_prev_state_set
|
53
|
-
self.state_set_index = state_set_index - 1
|
54
|
-
end
|
55
|
-
end # class
|
56
|
-
end # module
|
57
|
-
end # module
|
58
|
-
|
59
|
-
# End of file
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'forwardable' # Delegation
|
4
|
-
|
5
|
-
module Rley # This module is used as a namespace
|
6
|
-
module Parser # This module is used as a namespace
|
7
|
-
class StateSet
|
8
|
-
extend Forwardable
|
9
|
-
def_delegators :states, :empty?, :size, :first, :each
|
10
|
-
|
11
|
-
# The set of parse states
|
12
|
-
attr_reader(:states)
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@states = []
|
16
|
-
end
|
17
|
-
|
18
|
-
# Append the given state (if it isn't yet in the set)
|
19
|
-
# to the list of states
|
20
|
-
# @param aState [ParseState] the state to push.
|
21
|
-
# @return [TrueClass/FalseClass] true when the state is really added
|
22
|
-
def push_state(aState)
|
23
|
-
if include?(aState)
|
24
|
-
result = false
|
25
|
-
else
|
26
|
-
@states << aState
|
27
|
-
result = true
|
28
|
-
end
|
29
|
-
|
30
|
-
return result
|
31
|
-
end
|
32
|
-
|
33
|
-
# The list of ParseState that expect the given symbol.
|
34
|
-
# @param aSymbol [GrmSymbol] the expected symbol
|
35
|
-
# (=on the right of the dot)
|
36
|
-
def states_expecting(aSymbol)
|
37
|
-
states.select { |s| s.dotted_rule.next_symbol == aSymbol }
|
38
|
-
end
|
39
|
-
|
40
|
-
# The list of complete ParseState that have the given non-terminal
|
41
|
-
# symbol as the lhs of their production.
|
42
|
-
def states_rewriting(aNonTerm)
|
43
|
-
return states.select do |s|
|
44
|
-
(s.dotted_rule.production.lhs == aNonTerm) && s.complete?
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# The list of ParseState that involve the given production
|
49
|
-
def states_for(aProduction)
|
50
|
-
states.select { |s| s.dotted_rule.production == aProduction }
|
51
|
-
end
|
52
|
-
|
53
|
-
# Retrieve the parse state that is the predecessor of the given one.
|
54
|
-
def predecessor_state(aPState)
|
55
|
-
dotted_rule = aPState.dotted_rule
|
56
|
-
raise StandardError, aPState.to_s unless dotted_rule.prev_position
|
57
|
-
|
58
|
-
states.find { |s| s.precedes?(aPState) }
|
59
|
-
end
|
60
|
-
|
61
|
-
# The list of distinct expected terminal symbols. An expected symbol
|
62
|
-
# is on the left of a dot in a parse state of the parse set.
|
63
|
-
def expected_terminals
|
64
|
-
expecting_terminals = states.select do |s|
|
65
|
-
s.dotted_rule.next_symbol.kind_of?(Rley::Syntax::Terminal)
|
66
|
-
end
|
67
|
-
|
68
|
-
terminals = expecting_terminals.map { |s| s.dotted_rule.next_symbol }
|
69
|
-
terminals.uniq
|
70
|
-
end
|
71
|
-
|
72
|
-
# Return an Array of Arrays of ambiguous parse states.
|
73
|
-
def ambiguities
|
74
|
-
complete_states = states.select(&:complete?)
|
75
|
-
return [] if complete_states.size <= 1
|
76
|
-
|
77
|
-
# Group parse state by lhs symbol and origin
|
78
|
-
groupings = complete_states.group_by do |st|
|
79
|
-
st.dotted_rule.lhs.object_id.to_s
|
80
|
-
end
|
81
|
-
|
82
|
-
# Retain the groups having more than one element.
|
83
|
-
ambiguous_groups = []
|
84
|
-
groupings.each_value do |a_group|
|
85
|
-
ambiguous_groups << a_group if a_group.size > 1
|
86
|
-
end
|
87
|
-
|
88
|
-
ambiguous_groups
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def include?(aState)
|
94
|
-
# TODO: make it better than linear search
|
95
|
-
states.include?(aState)
|
96
|
-
end
|
97
|
-
end # class
|
98
|
-
end # module
|
99
|
-
end # module
|
100
|
-
# End of file
|
@@ -1,125 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../../spec_helper'
|
4
|
-
|
5
|
-
require_relative '../../../lib/rley/syntax/terminal'
|
6
|
-
require_relative '../../../lib/rley/syntax/non_terminal'
|
7
|
-
require_relative '../../../lib/rley/syntax/production'
|
8
|
-
require_relative '../../../lib/rley/base/dotted_item'
|
9
|
-
|
10
|
-
# Load the class under test
|
11
|
-
require_relative '../../../lib/rley/parser/parse_state'
|
12
|
-
|
13
|
-
module Rley # Open this namespace to avoid module qualifier prefixes
|
14
|
-
module Parser # Open this namespace to avoid module qualifier prefixes
|
15
|
-
describe ParseState do
|
16
|
-
let(:t_a) { Syntax::Terminal.new('A') }
|
17
|
-
let(:t_b) { Syntax::Terminal.new('B') }
|
18
|
-
let(:t_c) { Syntax::Terminal.new('C') }
|
19
|
-
let(:nt_sentence) { Syntax::NonTerminal.new('sentence') }
|
20
|
-
|
21
|
-
let(:sample_prod) do
|
22
|
-
Syntax::Production.new(nt_sentence, [t_a, t_b, t_c])
|
23
|
-
end
|
24
|
-
|
25
|
-
let(:other_prod) do
|
26
|
-
Syntax::Production.new(nt_sentence, [t_a])
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:empty_prod) do
|
30
|
-
Syntax::Production.new(nt_sentence, [])
|
31
|
-
end
|
32
|
-
|
33
|
-
let(:origin_val) { 3 }
|
34
|
-
let(:dotted_rule) { Base::DottedItem.new(sample_prod, 2) }
|
35
|
-
let(:other_dotted_rule) { double('mock-dotted-item') }
|
36
|
-
|
37
|
-
# Default instantiation rule
|
38
|
-
subject { ParseState.new(dotted_rule, origin_val) }
|
39
|
-
|
40
|
-
context 'Initialization:' do
|
41
|
-
it 'should be created with a dotted item and a origin position' do
|
42
|
-
args = [dotted_rule, origin_val]
|
43
|
-
expect { ParseState.new(*args) }.not_to raise_error
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should complain when the dotted rule is nil' do
|
47
|
-
err = StandardError
|
48
|
-
msg = 'Dotted item cannot be nil'
|
49
|
-
expect { ParseState.new(nil, 2) }.to raise_error(err, msg)
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should know the related dotted rule' do
|
53
|
-
expect(subject.dotted_rule).to eq(dotted_rule)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should know the origin value' do
|
57
|
-
expect(subject.origin).to eq(origin_val)
|
58
|
-
end
|
59
|
-
end # context
|
60
|
-
|
61
|
-
context 'Provided services:' do
|
62
|
-
def new_parse_state(aProd, aRank, aVal)
|
63
|
-
item = Base::DottedItem.new(aProd, aRank)
|
64
|
-
ParseState.new(item, aVal)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should compare with itself' do
|
68
|
-
synonym = subject # Fool Rubocop
|
69
|
-
expect(subject == synonym).to eq(true)
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should compare with another' do
|
73
|
-
equal = ParseState.new(dotted_rule, origin_val)
|
74
|
-
expect(subject == equal).to eq(true)
|
75
|
-
|
76
|
-
# Same dotted_rule, different origin
|
77
|
-
diff_origin = ParseState.new(dotted_rule, 2)
|
78
|
-
expect(subject == diff_origin).to eq(false)
|
79
|
-
|
80
|
-
# Different dotted item, same origin
|
81
|
-
diff_rule = ParseState.new(other_dotted_rule, 3)
|
82
|
-
expect(subject == diff_rule).to eq(false)
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'should know if the parsing is at the start of the production' do
|
86
|
-
expect(subject).not_to be_predicted
|
87
|
-
at_start = Base::DottedItem.new(sample_prod, 0)
|
88
|
-
|
89
|
-
instance = ParseState.new(at_start, 0)
|
90
|
-
expect(instance).to be_predicted
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'should know if the parsing reached the end of the production' do
|
94
|
-
expect(subject).not_to be_complete
|
95
|
-
at_end = Base::DottedItem.new(sample_prod, 3)
|
96
|
-
|
97
|
-
instance = ParseState.new(at_end, 2)
|
98
|
-
expect(instance).to be_complete
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'should know the next expected symbol' do
|
102
|
-
expect(subject.next_symbol).to eq(t_c)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should know whether another instance follows this one' do
|
106
|
-
expect(subject.precedes?(subject)).to eq(false)
|
107
|
-
state1 = new_parse_state(sample_prod, 1, origin_val)
|
108
|
-
expect(state1.precedes?(subject)).to eq(true)
|
109
|
-
state0 = new_parse_state(sample_prod, 0, origin_val)
|
110
|
-
expect(state0.precedes?(state1)).to eq(true)
|
111
|
-
expect(state0.precedes?(subject)).to eq(false)
|
112
|
-
state3 = new_parse_state(sample_prod, 3, origin_val)
|
113
|
-
expect(state3.precedes?(state0)).to eq(false)
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should know its text representation' do
|
117
|
-
expected = 'sentence => A B . C | 3'
|
118
|
-
expect(subject.to_s).to eq(expected)
|
119
|
-
end
|
120
|
-
end # context
|
121
|
-
end # describe
|
122
|
-
end # module
|
123
|
-
end # module
|
124
|
-
|
125
|
-
# End of file
|