rley 0.4.06 → 0.4.07
Sign up to get free protection for your applications and to get access to all the features.
- 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
|