rley 0.3.04 → 0.3.05
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 +7 -3
- data/CHANGELOG.md +3 -0
- data/Rakefile +30 -30
- data/examples/parsers/parsing_L0.rb +1 -1
- data/examples/parsers/parsing_L1.rb +1 -1
- data/examples/parsers/parsing_abc.rb +1 -1
- data/examples/parsers/parsing_ambig.rb +1 -1
- data/examples/parsers/parsing_another.rb +1 -1
- data/examples/parsers/parsing_b_expr.rb +1 -1
- data/examples/parsers/parsing_err_expr.rb +1 -1
- data/examples/parsers/parsing_groucho.rb +1 -1
- data/examples/parsers/parsing_right_recursive.rb +1 -1
- data/examples/parsers/parsing_tricky.rb +1 -1
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/formatter/base_formatter.rb +0 -2
- data/lib/rley/formatter/debug.rb +0 -2
- data/lib/rley/formatter/json.rb +1 -3
- data/lib/rley/gfg/call_edge.rb +31 -30
- data/lib/rley/gfg/edge.rb +22 -23
- data/lib/rley/gfg/end_vertex.rb +22 -24
- data/lib/rley/gfg/epsilon_edge.rb +20 -21
- data/lib/rley/gfg/grm_flow_graph.rb +39 -39
- data/lib/rley/gfg/item_vertex.rb +16 -17
- data/lib/rley/gfg/non_terminal_vertex.rb +3 -4
- data/lib/rley/gfg/return_edge.rb +32 -31
- data/lib/rley/gfg/scan_edge.rb +25 -26
- data/lib/rley/gfg/shortcut_edge.rb +25 -26
- data/lib/rley/gfg/start_vertex.rb +0 -2
- data/lib/rley/gfg/vertex.rb +8 -8
- data/lib/rley/parse_forest_visitor.rb +113 -115
- data/lib/rley/parse_tree_visitor.rb +0 -2
- data/lib/rley/parser/base_parser.rb +27 -27
- data/lib/rley/parser/chart.rb +14 -14
- data/lib/rley/parser/dotted_item.rb +33 -33
- data/lib/rley/parser/earley_parser.rb +6 -6
- data/lib/rley/parser/gfg_chart.rb +8 -15
- data/lib/rley/parser/gfg_earley_parser.rb +15 -13
- data/lib/rley/parser/gfg_parsing.rb +26 -22
- data/lib/rley/parser/grm_items_builder.rb +3 -2
- data/lib/rley/parser/parse_entry.rb +3 -9
- data/lib/rley/parser/parse_entry_set.rb +14 -19
- data/lib/rley/parser/parse_entry_tracker.rb +56 -56
- data/lib/rley/parser/parse_forest_builder.rb +215 -214
- data/lib/rley/parser/parse_forest_factory.rb +57 -56
- data/lib/rley/parser/parse_state.rb +8 -11
- data/lib/rley/parser/parse_state_tracker.rb +56 -56
- data/lib/rley/parser/parse_tracer.rb +3 -3
- data/lib/rley/parser/parse_tree_builder.rb +10 -10
- data/lib/rley/parser/parse_walker_factory.rb +30 -33
- data/lib/rley/parser/parsing.rb +8 -8
- data/lib/rley/parser/state_set.rb +23 -26
- data/lib/rley/ptree/non_terminal_node.rb +1 -1
- data/lib/rley/ptree/token_range.rb +2 -2
- data/lib/rley/sppf/alternative_node.rb +32 -34
- data/lib/rley/sppf/composite_node.rb +27 -27
- data/lib/rley/sppf/epsilon_node.rb +26 -27
- data/lib/rley/sppf/leaf_node.rb +11 -12
- data/lib/rley/sppf/non_terminal_node.rb +37 -38
- data/lib/rley/sppf/sppf_node.rb +1 -1
- data/lib/rley/sppf/token_node.rb +29 -29
- data/lib/rley/syntax/grammar.rb +1 -3
- data/lib/rley/syntax/grammar_builder.rb +8 -8
- data/lib/rley/syntax/non_terminal.rb +2 -4
- data/lib/rley/syntax/production.rb +3 -3
- data/lib/rley/syntax/symbol_seq.rb +1 -1
- data/spec/rley/gfg/call_edge_spec.rb +50 -51
- data/spec/rley/gfg/edge_spec.rb +33 -33
- data/spec/rley/gfg/end_vertex_spec.rb +26 -27
- data/spec/rley/gfg/epsilon_edge_spec.rb +25 -25
- data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -1
- data/spec/rley/gfg/item_vertex_spec.rb +3 -4
- data/spec/rley/gfg/return_edge_spec.rb +51 -51
- data/spec/rley/gfg/scan_edge_spec.rb +32 -30
- data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
- data/spec/rley/gfg/vertex_spec.rb +3 -3
- data/spec/rley/parse_forest_visitor_spec.rb +239 -238
- data/spec/rley/parser/dotted_item_spec.rb +1 -1
- data/spec/rley/parser/earley_parser_spec.rb +16 -16
- data/spec/rley/parser/gfg_earley_parser_spec.rb +30 -31
- data/spec/rley/parser/gfg_parsing_spec.rb +11 -10
- data/spec/rley/parser/grm_items_builder_spec.rb +2 -2
- data/spec/rley/parser/parse_entry_set_spec.rb +4 -4
- data/spec/rley/parser/parse_entry_spec.rb +0 -2
- data/spec/rley/parser/parse_forest_builder_spec.rb +82 -57
- data/spec/rley/parser/parse_forest_factory_spec.rb +84 -82
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -9
- data/spec/rley/parser/parsing_spec.rb +0 -1
- data/spec/rley/sppf/alternative_node_spec.rb +2 -2
- data/spec/rley/sppf/non_terminal_node_spec.rb +0 -1
- data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
- data/spec/rley/support/expectation_helper.rb +37 -36
- data/spec/rley/support/grammar_abc_helper.rb +17 -17
- data/spec/rley/support/grammar_b_expr_helper.rb +40 -39
- data/spec/rley/support/grammar_helper.rb +2 -1
- data/spec/rley/support/{grammar_L0_helper.rb → grammar_l0_helper.rb} +82 -81
- data/spec/rley/support/grammar_sppf_helper.rb +24 -25
- data/spec/rley/syntax/grammar_spec.rb +1 -1
- metadata +2 -2
@@ -188,13 +188,13 @@ module Rley # This module is used as a namespace
|
|
188
188
|
term_names = terminals.map(&:name)
|
189
189
|
err_msg = "Syntax error at or near token #{pos}"
|
190
190
|
err_msg << ">>>#{lexeme_at_pos}<<<:\nExpected "
|
191
|
-
if terminals.size > 1
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
191
|
+
err_msg << if terminals.size > 1
|
192
|
+
"one of: ['#{term_names.join("', '")}'],"
|
193
|
+
else
|
194
|
+
": #{term_names[0]},"
|
195
|
+
end
|
196
196
|
err_msg << " found a '#{aParsing.tokens[pos - 1].terminal.name}'"
|
197
|
-
|
197
|
+
raise StandardError, err_msg + ' instead.'
|
198
198
|
end
|
199
199
|
end # class
|
200
200
|
end # module
|
@@ -27,13 +27,6 @@ module Rley # This module is used as a namespace
|
|
27
27
|
push_entry(aGFGraph.start_vertex, 0, 0, :start_rule)
|
28
28
|
end
|
29
29
|
|
30
|
-
# The dotted item/rule used to seed the parse chart.
|
31
|
-
# It corresponds to the start production and a dot placed
|
32
|
-
# at the beginning of the rhs
|
33
|
-
# def start_dotted_rule()
|
34
|
-
# return self[0].entries.first.dotted_rule
|
35
|
-
# end
|
36
|
-
|
37
30
|
# Return the start (non-terminal) symbol of the grammar.
|
38
31
|
def start_symbol()
|
39
32
|
return sets.first.entries[0].vertex.non_terminal
|
@@ -47,11 +40,11 @@ module Rley # This module is used as a namespace
|
|
47
40
|
# Return the index value of the last non-empty entry set.
|
48
41
|
def last_index()
|
49
42
|
first_empty = sets.find_index(&:empty?)
|
50
|
-
if first_empty.nil?
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
index = if first_empty.nil?
|
44
|
+
sets.size - 1
|
45
|
+
else
|
46
|
+
first_empty.zero? ? 0 : first_empty - 1
|
47
|
+
end
|
55
48
|
|
56
49
|
return index
|
57
50
|
end
|
@@ -71,7 +64,7 @@ module Rley # This module is used as a namespace
|
|
71
64
|
when :completion
|
72
65
|
tracer.trace_completion(anIndex, new_entry)
|
73
66
|
else
|
74
|
-
|
67
|
+
raise NotImplementedError, "Unknown push_entry mode #{aReason}"
|
75
68
|
end
|
76
69
|
end
|
77
70
|
|
@@ -92,9 +85,9 @@ module Rley # This module is used as a namespace
|
|
92
85
|
# Retrieve all the end entries (i.e. of the form
|
93
86
|
last_entries = sets[last_index].entries.select(&:end_entry?)
|
94
87
|
|
95
|
-
# ... now find the end vertex for start symbol and with origin at zero
|
88
|
+
# ... now find the end vertex for start symbol and with origin at zero.
|
96
89
|
success_entries = last_entries.select do |entry|
|
97
|
-
entry.origin
|
90
|
+
entry.origin.zero? && entry.vertex.non_terminal == start_symbol
|
98
91
|
end
|
99
92
|
|
100
93
|
return success_entries.first
|
@@ -6,7 +6,6 @@ module Rley # This module is used as a namespace
|
|
6
6
|
module Parser # This module is used as a namespace
|
7
7
|
# Implementation of a parser that uses the Earley parsing algorithm.
|
8
8
|
class GFGEarleyParser < BaseParser
|
9
|
-
|
10
9
|
# The Grammar Flow graph for the given grammar
|
11
10
|
attr_reader :gf_graph
|
12
11
|
|
@@ -48,7 +47,8 @@ module Rley # This module is used as a namespace
|
|
48
47
|
return result
|
49
48
|
end
|
50
49
|
|
51
|
-
private
|
50
|
+
private
|
51
|
+
|
52
52
|
# Let the current sigma set be the ith parse entry set.
|
53
53
|
# This method is invoked when an entry is added to the parse entry set
|
54
54
|
# and is of the form [A => alpha . B beta, k].
|
@@ -77,8 +77,8 @@ private
|
|
77
77
|
end
|
78
78
|
|
79
79
|
# This method must be invoked when an entry is added to a parse entry set
|
80
|
-
# and is of the form [B => γ ., k] (the dot is at the end of the
|
81
|
-
# Then entry [B., k] is added to the current entry set.
|
80
|
+
# and is of the form [B => γ ., k] (the dot is at the end of the
|
81
|
+
# production. Then entry [B., k] is added to the current entry set.
|
82
82
|
# Gist: for an entry corresponding to a reduced production, add an entry
|
83
83
|
# for each exit edge in the graph.
|
84
84
|
def exit_rule(aParsing, anEntry, aPosition, aTracer)
|
@@ -100,13 +100,15 @@ private
|
|
100
100
|
end
|
101
101
|
|
102
102
|
# Given that the terminal t is at the specified position,
|
103
|
-
# Locate all entries in the current sigma set that expect t:
|
103
|
+
# Locate all entries in the current sigma set that expect t:
|
104
|
+
# [A => α . t γ, i]
|
104
105
|
# and allow them to cross the edge, adding the node on the back side
|
105
106
|
# of the edge as an entry to the next sigma set:
|
106
107
|
# add an entry to the next sigma set [A => α t . γ, i]
|
107
108
|
def scan_rule(aParsing, aPosition, aTracer)
|
108
109
|
if aTracer.level > 1
|
109
|
-
|
110
|
+
prefix = "Chart[#{aPosition}] Scan rule applied upon "
|
111
|
+
puts prefix + aParsing.tokens[aPosition].to_s
|
110
112
|
end
|
111
113
|
aParsing.scan_rule(aPosition)
|
112
114
|
end
|
@@ -124,16 +126,16 @@ private
|
|
124
126
|
term_names = terminals.map(&:name)
|
125
127
|
err_msg = "Syntax error at or near token #{pos}"
|
126
128
|
err_msg << ">>>#{lexeme_at_pos}<<<:\nExpected "
|
127
|
-
if terminals.size > 1
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
err_msg << if terminals.size > 1
|
130
|
+
"one of: ['#{term_names.join("', '")}'],"
|
131
|
+
else
|
132
|
+
": #{term_names[0]},"
|
133
|
+
end
|
132
134
|
err_msg << " found a '#{aParsing.tokens[pos - 1].terminal.name}'"
|
133
|
-
|
135
|
+
raise StandardError, err_msg + ' instead.'
|
134
136
|
end
|
135
137
|
end # class
|
136
138
|
end # module
|
137
139
|
end # module
|
138
140
|
|
139
|
-
# End of file
|
141
|
+
# End of file
|
@@ -15,9 +15,11 @@ module Rley # This module is used as a namespace
|
|
15
15
|
# The sequence of input token to parse
|
16
16
|
attr_reader(:tokens)
|
17
17
|
|
18
|
-
# A Hash with pairs of the form:
|
19
|
-
#
|
20
|
-
#
|
18
|
+
# A Hash with pairs of the form:
|
19
|
+
# parse entry => [ antecedent parse entries ]
|
20
|
+
# It associates to a every parse entry its antecedent(s), that is,
|
21
|
+
# the parse entry/ies that causes the key parse entry to be created
|
22
|
+
# with one the gfg rules
|
21
23
|
attr_reader(:antecedence)
|
22
24
|
|
23
25
|
# @param aTracer [ParseTracer] An object that traces the parsing.
|
@@ -42,7 +44,8 @@ module Rley # This module is used as a namespace
|
|
42
44
|
def call_rule(anEntry, aPosition)
|
43
45
|
next_symbol = anEntry.next_symbol
|
44
46
|
start_vertex = gf_graph.start_vertex_for[next_symbol]
|
45
|
-
|
47
|
+
pos = aPosition
|
48
|
+
apply_rule(anEntry, start_vertex, pos, pos, :call_rule)
|
46
49
|
end
|
47
50
|
|
48
51
|
# Let the current sigma set be the ith parse entry set.
|
@@ -62,8 +65,8 @@ module Rley # This module is used as a namespace
|
|
62
65
|
end
|
63
66
|
|
64
67
|
# This method must be invoked when an entry is added to a parse entry set
|
65
|
-
# and is of the form [B => γ ., k] (the dot is at the end of the
|
66
|
-
# Then entry [B., k] is added to the current entry set.
|
68
|
+
# and is of the form [B => γ ., k] (the dot is at the end of the
|
69
|
+
# production. Then entry [B., k] is added to the current entry set.
|
67
70
|
# Gist: for an entry corresponding to a reduced production, add an entry
|
68
71
|
# for each exit edge in the graph.
|
69
72
|
def exit_rule(anEntry, aPosition)
|
@@ -86,12 +89,15 @@ module Rley # This module is used as a namespace
|
|
86
89
|
expecting_nterm_k.each do |ntry|
|
87
90
|
# Get the vertices after the expected non-terminal
|
88
91
|
vertex_after_terminal = ntry.vertex.shortcut.successor
|
89
|
-
|
92
|
+
origin = ntry.origin
|
93
|
+
pos = aPosition
|
94
|
+
apply_rule(anEntry, vertex_after_terminal, origin, pos, :end_rule)
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
93
98
|
# Given that the terminal t is at the specified position,
|
94
|
-
# Locate all entries in the current sigma set that expect t:
|
99
|
+
# Locate all entries in the current sigma set that expect t:
|
100
|
+
# [A => α . t γ, i]
|
95
101
|
# and allow them to cross the edge, adding the node on the back side
|
96
102
|
# of the edge as an entry to the next sigma set:
|
97
103
|
# add an entry to the next sigma set [A => α t . γ, i]
|
@@ -108,7 +114,9 @@ module Rley # This module is used as a namespace
|
|
108
114
|
# Get the vertices after the expected terminal
|
109
115
|
ntry.vertex.edges.each do |an_edge|
|
110
116
|
vertex_after_terminal = an_edge.successor
|
111
|
-
|
117
|
+
origin = ntry.origin
|
118
|
+
pos = aPosition + 1
|
119
|
+
apply_rule(ntry, vertex_after_terminal, origin, pos, :scan_rule)
|
112
120
|
end
|
113
121
|
end
|
114
122
|
end
|
@@ -117,18 +125,16 @@ module Rley # This module is used as a namespace
|
|
117
125
|
# Return true if the parse was successful (= input tokens
|
118
126
|
# followed the syntax specified by the grammar)
|
119
127
|
def success?()
|
120
|
-
return chart.accepting_entry
|
128
|
+
return chart.accepting_entry ? true : false
|
121
129
|
end
|
122
130
|
|
123
131
|
# Return true if there are more than one complete state
|
124
132
|
# for the same lhs and same origin in any state set.
|
125
133
|
def ambiguous?()
|
126
134
|
found = chart.sets.find { |set| !set.ambiguities.empty? }
|
127
|
-
return !
|
135
|
+
return !found.nil?
|
128
136
|
end
|
129
137
|
|
130
|
-
|
131
|
-
|
132
138
|
# Factory method. Builds a ParseForest from the parse result.
|
133
139
|
# @return [ParseForest]
|
134
140
|
def parse_forest()
|
@@ -152,7 +158,6 @@ module Rley # This module is used as a namespace
|
|
152
158
|
return chart.accepting_entry
|
153
159
|
end
|
154
160
|
|
155
|
-
|
156
161
|
private
|
157
162
|
|
158
163
|
# Raise an exception to indicate a syntax error.
|
@@ -165,13 +170,13 @@ module Rley # This module is used as a namespace
|
|
165
170
|
term_names = expected.map(&:name)
|
166
171
|
err_msg = "Syntax error at or near token #{aPosition + 1}"
|
167
172
|
err_msg << ">>>#{lexeme_at_pos}<<<:\nExpected "
|
168
|
-
if expected.size > 1
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
+
err_msg << if expected.size > 1
|
174
|
+
"one of: ['#{term_names.join("', '")}'],"
|
175
|
+
else
|
176
|
+
": #{term_names[0]},"
|
177
|
+
end
|
173
178
|
err_msg << " found a '#{actual.name}'"
|
174
|
-
|
179
|
+
raise StandardError, err_msg + ' instead.'
|
175
180
|
end
|
176
181
|
|
177
182
|
def apply_rule(antecedentEntry, aVertex, anOrigin, aPosition, aRuleId)
|
@@ -183,7 +188,7 @@ module Rley # This module is used as a namespace
|
|
183
188
|
# Push a parse entry (vertex + origin) to the
|
184
189
|
# chart entry with given index if it isn't yet in the chart entry.
|
185
190
|
def push_entry(aVertex, anOrigin, aChartIndex, aReason)
|
186
|
-
|
191
|
+
raise StandardError, 'Vertex may not be nil' if aVertex.nil?
|
187
192
|
chart.push_entry(aVertex, anOrigin, aChartIndex, aReason)
|
188
193
|
end
|
189
194
|
|
@@ -202,7 +207,6 @@ module Rley # This module is used as a namespace
|
|
202
207
|
|
203
208
|
return instance
|
204
209
|
end
|
205
|
-
|
206
210
|
end # class
|
207
211
|
end # module
|
208
212
|
end # module
|
@@ -9,7 +9,7 @@ module Rley # This module is used as a namespace
|
|
9
9
|
items = []
|
10
10
|
aGrammar.rules.each do |prod|
|
11
11
|
rhs_size = prod.rhs.size
|
12
|
-
if rhs_size
|
12
|
+
if rhs_size.zero?
|
13
13
|
items << DottedItem.new(prod, 0)
|
14
14
|
else
|
15
15
|
items += (0..rhs_size).map { |i| DottedItem.new(prod, i) }
|
@@ -20,4 +20,5 @@ module Rley # This module is used as a namespace
|
|
20
20
|
end
|
21
21
|
end # module
|
22
22
|
end # module
|
23
|
-
end # module
|
23
|
+
end # module
|
24
|
+
# End of file
|
@@ -4,7 +4,6 @@ require_relative '../gfg/item_vertex'
|
|
4
4
|
|
5
5
|
module Rley # This module is used as a namespace
|
6
6
|
module Parser # This module is used as a namespace
|
7
|
-
|
8
7
|
# Responsibilities:
|
9
8
|
# - To know whether the vertex is a start, end or item vertex
|
10
9
|
# - To know the next symbol to expect
|
@@ -34,12 +33,7 @@ module Rley # This module is used as a namespace
|
|
34
33
|
def ==(other)
|
35
34
|
return true if object_id == other.object_id
|
36
35
|
|
37
|
-
|
38
|
-
result = true
|
39
|
-
else
|
40
|
-
result = false
|
41
|
-
end
|
42
|
-
|
36
|
+
result = (vertex == other.vertex) && (origin == other.origin)
|
43
37
|
return result
|
44
38
|
end
|
45
39
|
|
@@ -137,7 +131,7 @@ module Rley # This module is used as a namespace
|
|
137
131
|
|
138
132
|
# Return the validated GFG vertex
|
139
133
|
def valid_vertex(aVertex)
|
140
|
-
|
134
|
+
raise StandardError, 'GFG vertex cannot be nil' if aVertex.nil?
|
141
135
|
|
142
136
|
return aVertex
|
143
137
|
end
|
@@ -145,4 +139,4 @@ module Rley # This module is used as a namespace
|
|
145
139
|
end # module
|
146
140
|
end # module
|
147
141
|
|
148
|
-
# End of file
|
142
|
+
# End of file
|
@@ -14,14 +14,6 @@ module Rley # This module is used as a namespace
|
|
14
14
|
# The set of parse entries
|
15
15
|
attr_reader :entries
|
16
16
|
|
17
|
-
# A Hash with pairs of the form:
|
18
|
-
# terminal symbol => [ parse entry expecting the terminal ]
|
19
|
-
#attr_reader :entries4term
|
20
|
-
|
21
|
-
# A Hash with pairs of the form:
|
22
|
-
# non terminal symbol => [ parse entry expecting the non-terminal ]
|
23
|
-
# attr_reader :entries4n_term
|
24
|
-
|
25
17
|
def initialize()
|
26
18
|
@entries = []
|
27
19
|
@entries4term = Hash.new { |hash, key| hash[key] = [] }
|
@@ -33,10 +25,14 @@ module Rley # This module is used as a namespace
|
|
33
25
|
return entries[index]
|
34
26
|
end
|
35
27
|
|
28
|
+
# Returns a Hash with pairs of the form:
|
29
|
+
# terminal symbol => [ parse entry expecting the terminal ]
|
36
30
|
def entries4term(aTerminal)
|
37
31
|
return @entries4term.fetch(aTerminal, [])
|
38
32
|
end
|
39
33
|
|
34
|
+
# Returns a Hash with pairs of the form:
|
35
|
+
# non terminal symbol => [ parse entry expecting the non-terminal ]
|
40
36
|
def entries4n_term(aNonTerminal)
|
41
37
|
return @entries4n_term.fetch(aNonTerminal, [])
|
42
38
|
end
|
@@ -49,8 +45,6 @@ module Rley # This module is used as a namespace
|
|
49
45
|
match = entries.find { |entry| entry == anEntry }
|
50
46
|
if match
|
51
47
|
result = match
|
52
|
-
#if entries.include?(anEntry) # TODO: check performance
|
53
|
-
# result = false
|
54
48
|
else
|
55
49
|
@entries << anEntry
|
56
50
|
expecting = anEntry.next_symbol
|
@@ -64,12 +58,12 @@ module Rley # This module is used as a namespace
|
|
64
58
|
|
65
59
|
# Return an Array of Arrays of ambiguous parse entries.
|
66
60
|
def ambiguities()
|
67
|
-
complete_entries = entries.select
|
61
|
+
complete_entries = entries.select(&:exit_entry?)
|
68
62
|
return [] if complete_entries.size <= 1
|
69
63
|
|
70
64
|
# Group parse entries by lhs symbol and origin
|
71
65
|
groupings = complete_entries.group_by do |entry|
|
72
|
-
|
66
|
+
entry.vertex.dotted_rule.lhs.object_id.to_s
|
73
67
|
end
|
74
68
|
|
75
69
|
# Retain the groups having more than one element.
|
@@ -87,18 +81,19 @@ module Rley # This module is used as a namespace
|
|
87
81
|
return @entries4term.keys
|
88
82
|
end
|
89
83
|
|
90
|
-
private
|
84
|
+
private
|
85
|
+
|
91
86
|
def add_lookup4symbol(anEntry)
|
92
87
|
symb = anEntry.next_symbol
|
93
88
|
case symb
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
89
|
+
when Syntax::Terminal
|
90
|
+
@entries4term[symb] << anEntry
|
91
|
+
|
92
|
+
when Syntax::NonTerminal
|
93
|
+
@entries4n_term[symb] << anEntry
|
99
94
|
end
|
100
95
|
end
|
101
96
|
end # class
|
102
97
|
end # module
|
103
98
|
end # module
|
104
|
-
# End of file
|
99
|
+
# End of file
|
@@ -1,56 +1,56 @@
|
|
1
|
-
module Rley # This module is used as a namespace
|
2
|
-
module Parser # This module is used as a namespace
|
3
|
-
# Helper class that keeps track of the parse entries used
|
4
|
-
# while a Parsing instance is constructing a parse forest.
|
5
|
-
class ParseEntryTracker
|
6
|
-
# The index of the current entry set
|
7
|
-
attr_reader(:entry_set_index)
|
8
|
-
|
9
|
-
# The current parse entry
|
10
|
-
attr_reader(:parse_entry)
|
11
|
-
|
12
|
-
# The already processed entries from current entry set
|
13
|
-
attr_reader(:processed_entries)
|
14
|
-
|
15
|
-
# Constructor.
|
16
|
-
def initialize(aEntrySetIndex)
|
17
|
-
self.entry_set_index = aEntrySetIndex
|
18
|
-
end
|
19
|
-
|
20
|
-
# Write accessor. Sets the value of the entry set index
|
21
|
-
def entry_set_index=(anIndex)
|
22
|
-
@entry_set_index = anIndex
|
23
|
-
@processed_entries = {}
|
24
|
-
end
|
25
|
-
|
26
|
-
# Write accessor. Set the given parse entry as the current one.
|
27
|
-
def parse_entry=(aParseEntry)
|
28
|
-
|
29
|
-
@parse_entry = aParseEntry
|
30
|
-
processed_entries[parse_entry] = true
|
31
|
-
end
|
32
|
-
|
33
|
-
# Take the first provided entry that wasn't processed yet.
|
34
|
-
def select_entry(theEntrys)
|
35
|
-
a_entry = theEntrys.find { |st| !processed_entries.include?(st) }
|
36
|
-
self.parse_entry = a_entry
|
37
|
-
end
|
38
|
-
|
39
|
-
# The dotted item for the current parse entry.
|
40
|
-
def curr_dotted_item()
|
41
|
-
parse_entry.dotted_rule
|
42
|
-
end
|
43
|
-
|
44
|
-
def symbol_on_left()
|
45
|
-
return curr_dotted_item.prev_symbol
|
46
|
-
end
|
47
|
-
|
48
|
-
# Notification that one begins with the previous entry set
|
49
|
-
def to_prev_entry_set()
|
50
|
-
self.entry_set_index = entry_set_index - 1
|
51
|
-
end
|
52
|
-
end # class
|
53
|
-
end # module
|
54
|
-
end # module
|
55
|
-
|
56
|
-
# End of file
|
1
|
+
module Rley # This module is used as a namespace
|
2
|
+
module Parser # This module is used as a namespace
|
3
|
+
# Helper class that keeps track of the parse entries used
|
4
|
+
# while a Parsing instance is constructing a parse forest.
|
5
|
+
class ParseEntryTracker
|
6
|
+
# The index of the current entry set
|
7
|
+
attr_reader(:entry_set_index)
|
8
|
+
|
9
|
+
# The current parse entry
|
10
|
+
attr_reader(:parse_entry)
|
11
|
+
|
12
|
+
# The already processed entries from current entry set
|
13
|
+
attr_reader(:processed_entries)
|
14
|
+
|
15
|
+
# Constructor.
|
16
|
+
def initialize(aEntrySetIndex)
|
17
|
+
self.entry_set_index = aEntrySetIndex
|
18
|
+
end
|
19
|
+
|
20
|
+
# Write accessor. Sets the value of the entry set index
|
21
|
+
def entry_set_index=(anIndex)
|
22
|
+
@entry_set_index = anIndex
|
23
|
+
@processed_entries = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# Write accessor. Set the given parse entry as the current one.
|
27
|
+
def parse_entry=(aParseEntry)
|
28
|
+
raise StandardError, 'Nil parse entry' if aParseEntry.nil?
|
29
|
+
@parse_entry = aParseEntry
|
30
|
+
processed_entries[parse_entry] = true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Take the first provided entry that wasn't processed yet.
|
34
|
+
def select_entry(theEntrys)
|
35
|
+
a_entry = theEntrys.find { |st| !processed_entries.include?(st) }
|
36
|
+
self.parse_entry = a_entry
|
37
|
+
end
|
38
|
+
|
39
|
+
# The dotted item for the current parse entry.
|
40
|
+
def curr_dotted_item()
|
41
|
+
parse_entry.dotted_rule
|
42
|
+
end
|
43
|
+
|
44
|
+
def symbol_on_left()
|
45
|
+
return curr_dotted_item.prev_symbol
|
46
|
+
end
|
47
|
+
|
48
|
+
# Notification that one begins with the previous entry set
|
49
|
+
def to_prev_entry_set()
|
50
|
+
self.entry_set_index = entry_set_index - 1
|
51
|
+
end
|
52
|
+
end # class
|
53
|
+
end # module
|
54
|
+
end # module
|
55
|
+
|
56
|
+
# End of file
|