rley 0.4.06 → 0.4.07
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 +22 -13
- data/.travis.yml +8 -7
- data/CHANGELOG.md +9 -0
- data/README.md +9 -10
- data/examples/NLP/mini_en_demo.rb +7 -7
- data/examples/data_formats/JSON/cli_options.rb +5 -6
- data/examples/data_formats/JSON/{JSON_demo.rb → json_demo.rb} +2 -2
- data/examples/data_formats/JSON/{JSON_grammar.rb → json_grammar.rb} +10 -10
- data/examples/data_formats/JSON/{JSON_lexer.rb → json_lexer.rb} +17 -22
- data/examples/data_formats/JSON/{JSON_parser.rb → json_parser.rb} +2 -2
- data/examples/general/calc/calc_demo.rb +1 -1
- data/examples/general/calc/calc_grammar.rb +5 -5
- data/examples/general/calc/calc_lexer.rb +14 -17
- data/examples/general/calc/calc_parser.rb +2 -2
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/formatter/asciitree.rb +15 -16
- data/lib/rley/formatter/bracket_notation.rb +3 -6
- data/lib/rley/formatter/debug.rb +0 -1
- data/lib/rley/formatter/json.rb +0 -1
- data/lib/rley/gfg/grm_flow_graph.rb +11 -10
- data/lib/rley/parse_forest_visitor.rb +0 -3
- data/lib/rley/parse_tree_visitor.rb +0 -3
- data/lib/rley/parser/error_reason.rb +1 -5
- data/lib/rley/parser/gfg_chart.rb +2 -2
- data/lib/rley/parser/gfg_earley_parser.rb +1 -2
- data/lib/rley/parser/gfg_parsing.rb +3 -7
- data/lib/rley/parser/parse_entry.rb +0 -1
- data/lib/rley/parser/parse_entry_set.rb +15 -16
- data/lib/rley/parser/parse_forest_builder.rb +8 -23
- data/lib/rley/parser/parse_state.rb +1 -1
- data/lib/rley/parser/parse_tree_builder.rb +2 -30
- data/lib/rley/parser/parse_tree_factory.rb +1 -1
- data/lib/rley/parser/parse_walker_factory.rb +3 -6
- data/lib/rley/parser/state_set.rb +0 -1
- data/lib/rley/ptree/parse_tree.rb +0 -1
- data/lib/rley/ptree/terminal_node.rb +4 -1
- data/lib/rley/rley_error.rb +1 -1
- data/lib/rley/sppf/composite_node.rb +0 -1
- data/lib/rley/sppf/parse_forest.rb +0 -1
- data/lib/rley/syntax/grammar.rb +5 -9
- data/lib/rley/syntax/grammar_builder.rb +8 -11
- data/lib/rley/syntax/grm_symbol.rb +0 -1
- data/lib/rley/syntax/production.rb +5 -4
- data/lib/rley/tokens/token_range.rb +0 -1
- data/spec/rley/formatter/bracket_notation_spec.rb +3 -1
- data/spec/rley/gfg/grm_flow_graph_spec.rb +15 -46
- data/spec/rley/gfg/item_vertex_spec.rb +1 -1
- data/spec/rley/parse_forest_visitor_spec.rb +1 -1
- data/spec/rley/parse_tree_visitor_spec.rb +2 -2
- data/spec/rley/parser/error_reason_spec.rb +19 -14
- data/spec/rley/parser/gfg_chart_spec.rb +1 -1
- data/spec/rley/parser/gfg_earley_parser_spec.rb +15 -15
- data/spec/rley/parser/gfg_parsing_spec.rb +3 -3
- data/spec/rley/parser/groucho_spec.rb +6 -7
- data/spec/rley/parser/parse_forest_builder_spec.rb +5 -5
- data/spec/rley/parser/parse_forest_factory_spec.rb +5 -5
- data/spec/rley/parser/parse_state_spec.rb +8 -0
- data/spec/rley/parser/parse_tracer_spec.rb +1 -1
- data/spec/rley/parser/parse_tree_builder_spec.rb +26 -29
- data/spec/rley/parser/parse_tree_factory_spec.rb +5 -5
- data/spec/rley/parser/parse_walker_factory_spec.rb +5 -5
- data/spec/rley/ptree/parse_tree_node_spec.rb +2 -2
- data/spec/rley/ptree/terminal_node_spec.rb +1 -1
- data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
- data/spec/rley/support/expectation_helper.rb +0 -1
- data/spec/rley/support/grammar_abc_helper.rb +1 -1
- data/spec/rley/support/grammar_ambig01_helper.rb +2 -3
- data/spec/rley/support/grammar_b_expr_helper.rb +2 -2
- data/spec/rley/support/grammar_l0_helper.rb +7 -8
- data/spec/rley/support/grammar_pb_helper.rb +3 -4
- data/spec/rley/support/grammar_sppf_helper.rb +4 -4
- data/spec/rley/syntax/grammar_builder_spec.rb +5 -4
- data/spec/rley/syntax/grammar_spec.rb +10 -11
- data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
- data/spec/rley/syntax/terminal_spec.rb +1 -1
- metadata +31 -31
@@ -128,7 +128,6 @@ module Rley # This module is used as a namespace
|
|
128
128
|
return true
|
129
129
|
end
|
130
130
|
|
131
|
-
|
132
131
|
# Return true if the parse was successful (= input tokens
|
133
132
|
# followed the syntax specified by the grammar)
|
134
133
|
def success?()
|
@@ -180,11 +179,9 @@ module Rley # This module is used as a namespace
|
|
180
179
|
|
181
180
|
# A notification that the parsing reached an end
|
182
181
|
def done
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
premature_end
|
187
|
-
end
|
182
|
+
# Parse not successful and no reason identified
|
183
|
+
# Assuming that parse failed because of a premature end
|
184
|
+
premature_end unless success? || failure_reason
|
188
185
|
end
|
189
186
|
|
190
187
|
private
|
@@ -232,7 +229,6 @@ module Rley # This module is used as a namespace
|
|
232
229
|
return ParseForestBuilder.new(start_production, full_range)
|
233
230
|
end
|
234
231
|
|
235
|
-
|
236
232
|
# Factory method. Creates and initializes a ParseEntryTracker instance.
|
237
233
|
def new_entry_tracker()
|
238
234
|
instance = ParseEntryTracker.new(chart.last_index)
|
@@ -9,34 +9,34 @@ module Rley # This module is used as a namespace
|
|
9
9
|
# - To know all the parse entries in the set
|
10
10
|
class ParseEntrySet
|
11
11
|
extend Forwardable
|
12
|
-
def_delegators :entries, :empty?, :size, :first, :last, :pop, :each
|
12
|
+
def_delegators :entries, :empty?, :size, :first, :last, :pop, :each
|
13
13
|
|
14
14
|
# The set of parse entries
|
15
15
|
attr_reader :entries
|
16
16
|
|
17
17
|
def initialize()
|
18
18
|
@entries = []
|
19
|
-
@entries4term = Hash.new { |hash, key| hash[key] = [] }
|
19
|
+
@entries4term = Hash.new { |hash, key| hash[key] = [] }
|
20
20
|
@entries4n_term = Hash.new { |hash, key| hash[key] = [] }
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# Access the entry at given position
|
24
24
|
def [](index)
|
25
25
|
return entries[index]
|
26
|
-
end
|
26
|
+
end
|
27
27
|
|
28
28
|
# Returns a Hash with pairs of the form:
|
29
29
|
# terminal symbol => [ parse entry expecting the terminal ]
|
30
30
|
def entries4term(aTerminal)
|
31
31
|
return @entries4term.fetch(aTerminal, [])
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# Returns a Hash with pairs of the form:
|
35
35
|
# non terminal symbol => [ parse entry expecting the non-terminal ]
|
36
36
|
def entries4n_term(aNonTerminal)
|
37
37
|
return @entries4n_term.fetch(aNonTerminal, [])
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# Append the given entry (if it isn't yet in the set)
|
41
41
|
# to the list of parse entries
|
42
42
|
# @param anEntry [ParseEntry] the parse entry to push.
|
@@ -51,27 +51,26 @@ module Rley # This module is used as a namespace
|
|
51
51
|
add_lookup4symbol(anEntry) if expecting
|
52
52
|
result = anEntry
|
53
53
|
end
|
54
|
-
|
55
|
-
return result
|
54
|
+
|
55
|
+
return result
|
56
56
|
end
|
57
57
|
|
58
|
-
|
59
58
|
# Return an Array of Arrays of ambiguous parse entries.
|
60
59
|
def ambiguities()
|
61
60
|
complete_entries = entries.select(&:exit_entry?)
|
62
61
|
return [] if complete_entries.size <= 1
|
63
|
-
|
62
|
+
|
64
63
|
# Group parse entries by lhs symbol and origin
|
65
64
|
groupings = complete_entries.group_by do |entry|
|
66
65
|
entry.vertex.dotted_rule.lhs.object_id.to_s
|
67
66
|
end
|
68
|
-
|
67
|
+
|
69
68
|
# Retain the groups having more than one element.
|
70
69
|
ambiguous_groups = []
|
71
70
|
groupings.each_value do |a_group|
|
72
71
|
ambiguous_groups << a_group if a_group.size > 1
|
73
72
|
end
|
74
|
-
|
73
|
+
|
75
74
|
return ambiguous_groups
|
76
75
|
end
|
77
76
|
|
@@ -79,16 +78,16 @@ module Rley # This module is used as a namespace
|
|
79
78
|
# is on the left of a dot in a parse state of the parse set.
|
80
79
|
def expected_terminals()
|
81
80
|
return @entries4term.keys
|
82
|
-
end
|
83
|
-
|
81
|
+
end
|
82
|
+
|
84
83
|
private
|
85
84
|
|
86
85
|
def add_lookup4symbol(anEntry)
|
87
86
|
symb = anEntry.next_symbol
|
88
87
|
case symb
|
89
88
|
when Syntax::Terminal
|
90
|
-
@entries4term[symb] << anEntry
|
91
|
-
|
89
|
+
@entries4term[symb] << anEntry
|
90
|
+
|
92
91
|
when Syntax::NonTerminal
|
93
92
|
@entries4n_term[symb] << anEntry
|
94
93
|
end
|
@@ -82,11 +82,6 @@ module Rley # This module is used as a namespace
|
|
82
82
|
when :backtrack
|
83
83
|
# Restore path
|
84
84
|
@curr_path = entry2path_to_alt[anEntry].dup
|
85
|
-
# puts "Restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
|
86
|
-
antecedent_index = curr_parent.subnodes.size
|
87
|
-
# puts "Current parent #{curr_parent.to_string(0)}"
|
88
|
-
# puts "Antecedent index #{antecedent_index}"
|
89
|
-
|
90
85
|
|
91
86
|
when :revisit
|
92
87
|
# Retrieve the already existing node corresponding
|
@@ -102,7 +97,6 @@ module Rley # This module is used as a namespace
|
|
102
97
|
end
|
103
98
|
end
|
104
99
|
|
105
|
-
|
106
100
|
def process_item_entry(anEvent, anEntry, anIndex)
|
107
101
|
case anEvent
|
108
102
|
when :visit
|
@@ -150,14 +144,9 @@ module Rley # This module is used as a namespace
|
|
150
144
|
when :backtrack
|
151
145
|
# Restore path
|
152
146
|
@curr_path = entry2path_to_alt[anEntry].dup
|
153
|
-
# puts "Special restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
|
154
|
-
antecedent_index = curr_parent.subnodes.size
|
155
|
-
# puts "Current parent #{curr_parent.to_string(0)}"
|
156
|
-
# puts "Antecedent index #{antecedent_index}"
|
157
|
-
|
158
147
|
create_alternative_node(anEntry)
|
159
148
|
|
160
|
-
|
149
|
+
when :revisit
|
161
150
|
# Retrieve the grammar symbol before the dot (if any)
|
162
151
|
prev_symbol = anEntry.prev_symbol
|
163
152
|
case prev_symbol
|
@@ -181,7 +170,6 @@ module Rley # This module is used as a namespace
|
|
181
170
|
return Rley::SPPF::ParseForest.new(aRootNode)
|
182
171
|
end
|
183
172
|
|
184
|
-
|
185
173
|
# Factory method. Build and return an SPPF non-terminal node.
|
186
174
|
def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
|
187
175
|
non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
|
@@ -193,7 +181,6 @@ module Rley # This module is used as a namespace
|
|
193
181
|
return new_node
|
194
182
|
end
|
195
183
|
|
196
|
-
|
197
184
|
# Add an alternative node to the forest
|
198
185
|
def create_alternative_node(anEntry)
|
199
186
|
vertex = anEntry.vertex
|
@@ -220,7 +207,6 @@ module Rley # This module is used as a namespace
|
|
220
207
|
return candidate
|
221
208
|
end
|
222
209
|
|
223
|
-
|
224
210
|
def create_epsilon_node(anEntry, anIndex)
|
225
211
|
new_node = SPPF::EpsilonNode.new(anIndex)
|
226
212
|
candidate = add_node_to_forest(new_node)
|
@@ -232,19 +218,18 @@ module Rley # This module is used as a namespace
|
|
232
218
|
# Add the given node if not yet present in parse forest
|
233
219
|
def add_node_to_forest(aNode)
|
234
220
|
key_node = aNode.key
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
221
|
+
if forest.include?(key_node)
|
222
|
+
new_node = forest.key2node[key_node]
|
223
|
+
else
|
224
|
+
new_node = aNode
|
225
|
+
forest.key2node[key_node] = new_node
|
226
|
+
# puts "FOREST ADD #{key_node}"
|
227
|
+
end
|
242
228
|
add_subnode(new_node, false)
|
243
229
|
|
244
230
|
return new_node
|
245
231
|
end
|
246
232
|
|
247
|
-
|
248
233
|
# Add the given node as sub-node of current parent node
|
249
234
|
# Optionally add the node to the current path
|
250
235
|
def add_subnode(aNode, addToPath = true)
|
@@ -40,7 +40,7 @@ module Rley # This module is used as a namespace
|
|
40
40
|
|
41
41
|
# Does this parse state have the 'other' as successor?
|
42
42
|
def precedes?(other)
|
43
|
-
return false if
|
43
|
+
return false if other == self
|
44
44
|
|
45
45
|
return false unless origin == other.origin
|
46
46
|
other_production = other.dotted_rule.production
|
@@ -77,7 +77,6 @@ module Rley # This module is used as a namespace
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
|
81
80
|
def process_item_entry(anEvent, anEntry, anIndex)
|
82
81
|
case anEvent
|
83
82
|
when :visit
|
@@ -117,32 +116,8 @@ module Rley # This module is used as a namespace
|
|
117
116
|
curr_path.pop if curr_parent.kind_of?(SPPF::AlternativeNode)
|
118
117
|
end
|
119
118
|
|
120
|
-
when :backtrack
|
121
|
-
|
122
|
-
# @curr_path = entry2path_to_alt[anEntry].dup
|
123
|
-
# # puts "Special restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
|
124
|
-
# antecedent_index = curr_parent.subnodes.size
|
125
|
-
# # puts "Current parent #{curr_parent.to_string(0)}"
|
126
|
-
# # puts "Antecedent index #{antecedent_index}"
|
127
|
-
|
128
|
-
# create_alternative_node(anEntry)
|
129
|
-
|
130
|
-
when :revisit
|
131
|
-
# # Retrieve the grammar symbol before the dot (if any)
|
132
|
-
# prev_symbol = anEntry.prev_symbol
|
133
|
-
# case prev_symbol
|
134
|
-
# when Syntax::Terminal
|
135
|
-
# # Add node without changing current path
|
136
|
-
# create_token_node(anEntry, anIndex)
|
137
|
-
|
138
|
-
# when NilClass # Dot at the beginning of production
|
139
|
-
# if anEntry.vertex.dotted_item.production.empty?
|
140
|
-
# # Empty rhs => create an epsilon node ...
|
141
|
-
# # ... without changing current path
|
142
|
-
# create_epsilon_node(anEntry, anIndex)
|
143
|
-
# end
|
144
|
-
# curr_path.pop if curr_parent.kind_of?(PTree::AlternativeNode)
|
145
|
-
# end
|
119
|
+
# when :backtrack
|
120
|
+
# when :revisit
|
146
121
|
end
|
147
122
|
end
|
148
123
|
|
@@ -151,7 +126,6 @@ module Rley # This module is used as a namespace
|
|
151
126
|
return Rley::PTree::ParseTree.new(aRootNode)
|
152
127
|
end
|
153
128
|
|
154
|
-
|
155
129
|
# Factory method. Build and return an PTree non-terminal node.
|
156
130
|
def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
|
157
131
|
non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
|
@@ -163,7 +137,6 @@ module Rley # This module is used as a namespace
|
|
163
137
|
return new_node
|
164
138
|
end
|
165
139
|
|
166
|
-
|
167
140
|
# Add an alternative node to the tree
|
168
141
|
def create_alternative_node(anEntry)
|
169
142
|
vertex = anEntry.vertex
|
@@ -199,7 +172,6 @@ module Rley # This module is used as a namespace
|
|
199
172
|
return new_node
|
200
173
|
end
|
201
174
|
|
202
|
-
|
203
175
|
# Add the given node as sub-node of current parent node
|
204
176
|
# Optionally add the node to the current path
|
205
177
|
def add_subnode(aNode, addToPath = true)
|
@@ -25,7 +25,6 @@ module Rley # This module is used as a namespace
|
|
25
25
|
:antecedent_index
|
26
26
|
)
|
27
27
|
|
28
|
-
|
29
28
|
# A factory that creates an enumerator
|
30
29
|
# that itself walks through a given parsing graph.
|
31
30
|
# The walker yields visit events.
|
@@ -84,7 +83,6 @@ module Rley # This module is used as a namespace
|
|
84
83
|
return context
|
85
84
|
end
|
86
85
|
|
87
|
-
|
88
86
|
# Initialize the non-terminal to start entry mapping
|
89
87
|
def init_nterm2start()
|
90
88
|
h = Hash.new do |hsh, defval|
|
@@ -139,7 +137,6 @@ module Rley # This module is used as a namespace
|
|
139
137
|
return nil unless aContext.curr_entry.dotted_entry?
|
140
138
|
end
|
141
139
|
|
142
|
-
|
143
140
|
# Given the current entry from context object
|
144
141
|
# Go to the parse entry that is one of its antecedent
|
145
142
|
# The context object is updated
|
@@ -168,7 +165,8 @@ module Rley # This module is used as a namespace
|
|
168
165
|
aContext.return_stack << aContext.curr_entry
|
169
166
|
elsif traversed_edge.kind_of?(GFG::CallEdge)
|
170
167
|
# Pop top of stack
|
171
|
-
|
168
|
+
err_msg = 'Return stack empty!'
|
169
|
+
raise ScriptError, err_msg if aContext.return_stack.empty?
|
172
170
|
aContext.return_stack.pop
|
173
171
|
# puts "Pop from return stack matching entry #{new_entry}"
|
174
172
|
elsif traversed_edge.kind_of?(GFG::ScanEdge)
|
@@ -220,7 +218,6 @@ module Rley # This module is used as a namespace
|
|
220
218
|
return bp
|
221
219
|
end
|
222
220
|
|
223
|
-
|
224
221
|
def use_backtrack_point(aContext)
|
225
222
|
bp = aContext.backtrack_points.last
|
226
223
|
bp.antecedent_index += 1
|
@@ -246,7 +243,7 @@ module Rley # This module is used as a namespace
|
|
246
243
|
# Observation: calling parse entry is an parse entry linked
|
247
244
|
# to a item vertex
|
248
245
|
def select_calling_entry(aContext)
|
249
|
-
|
246
|
+
raise ScriptError, 'Empty return stack' if aContext.return_stack.empty?
|
250
247
|
# Retrieve top of stack
|
251
248
|
tos = aContext.return_stack.pop
|
252
249
|
tos_dotted_item = tos.vertex.dotted_item
|
@@ -35,7 +35,6 @@ module Rley # This module is used as a namespace
|
|
35
35
|
return states.select { |s| s.dotted_rule.next_symbol == aSymbol }
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
38
|
# The list of complete ParseState that have the given non-terminal
|
40
39
|
# symbol as the lhs of their production.
|
41
40
|
def states_rewriting(aNonTerm)
|
@@ -20,7 +20,6 @@ module Rley # This module is used as a namespace
|
|
20
20
|
@root = theRootNode
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
23
|
# Part of the 'visitee' role in the Visitor design pattern.
|
25
24
|
# A visitee is expected to accept the visit from a visitor object
|
26
25
|
# @param aVisitor [ParseTreeVisitor] the visitor object
|
@@ -8,7 +8,10 @@ module Rley # This module is used as a namespace
|
|
8
8
|
|
9
9
|
# aPosition is the position of the token in the input stream.
|
10
10
|
def initialize(aToken, aPos)
|
11
|
-
|
11
|
+
(major, minor) =
|
12
|
+
|
13
|
+
# Use '1.class' trick to support both Integer and Fixnum classes
|
14
|
+
range = aPos.kind_of?(1.class) ? { low: aPos, high: aPos + 1 } : aPos
|
12
15
|
super(aToken.terminal, range)
|
13
16
|
@token = aToken
|
14
17
|
end
|
data/lib/rley/rley_error.rb
CHANGED
@@ -40,7 +40,6 @@ module Rley # This module is used as a namespace
|
|
40
40
|
return @is_ambiguous
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
43
|
# Part of the 'visitee' role in the Visitor design pattern.
|
45
44
|
# A visitee is expected to accept the visit from a visitor object
|
46
45
|
# @param aVisitor [ParseForestVisitor] the visitor object
|
data/lib/rley/syntax/grammar.rb
CHANGED
@@ -88,8 +88,6 @@ module Rley # This module is used as a namespace
|
|
88
88
|
undefined.each { |n_term| n_term.undefined = true }
|
89
89
|
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
91
|
# Mark all non-terminals and production rules as
|
94
92
|
# generative or not.
|
95
93
|
# A production is generative when it can derive a string of terminals.
|
@@ -101,7 +99,7 @@ module Rley # This module is used as a namespace
|
|
101
99
|
curr_marked = []
|
102
100
|
|
103
101
|
# Iterate until no new rule can be marked.
|
104
|
-
|
102
|
+
loop do
|
105
103
|
prev_marked = curr_marked.dup
|
106
104
|
|
107
105
|
rules.each do |a_rule|
|
@@ -123,7 +121,8 @@ module Rley # This module is used as a namespace
|
|
123
121
|
curr_marked << a_rule
|
124
122
|
could_mark_nterm_generative(a_rule)
|
125
123
|
end
|
126
|
-
|
124
|
+
break if prev_marked.size == curr_marked.size
|
125
|
+
end
|
127
126
|
|
128
127
|
# The nonterminals that are not marked yet are non-generative
|
129
128
|
non_terminals.each do |nterm|
|
@@ -151,14 +150,13 @@ module Rley # This module is used as a namespace
|
|
151
150
|
nterm.generative = true
|
152
151
|
all_false = false
|
153
152
|
break
|
154
|
-
|
155
|
-
all_false = false
|
153
|
+
elsif prod.generative?.nil?
|
154
|
+
all_false = false
|
156
155
|
end
|
157
156
|
end
|
158
157
|
nterm.generative = false if all_false
|
159
158
|
end
|
160
159
|
|
161
|
-
|
162
160
|
# For each non-terminal determine whether it is nullable or not.
|
163
161
|
# A nullable nonterminal is a nonterminal that can match an empty string.
|
164
162
|
def compute_nullable()
|
@@ -189,7 +187,6 @@ module Rley # This module is used as a namespace
|
|
189
187
|
end
|
190
188
|
end
|
191
189
|
|
192
|
-
|
193
190
|
# Return the set of nonterminals which have one of their
|
194
191
|
# production rules empty
|
195
192
|
def direct_nullable()
|
@@ -216,7 +213,6 @@ module Rley # This module is used as a namespace
|
|
216
213
|
def rules_for(aNonTerm)
|
217
214
|
rules.select { |a_rule| a_rule.lhs == aNonTerm }
|
218
215
|
end
|
219
|
-
|
220
216
|
end # class
|
221
217
|
end # module
|
222
218
|
end # module
|