rley 0.7.00 → 0.7.01
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +51 -34
- data/.travis.yml +10 -9
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +0 -1
- data/appveyor.yml +10 -8
- data/examples/NLP/benchmark_pico_en.rb +3 -2
- data/examples/NLP/engtagger.rb +23 -12
- data/examples/NLP/nano_eng/nano_en_demo.rb +4 -3
- data/examples/NLP/pico_en_demo.rb +3 -2
- data/examples/data_formats/JSON/json_ast_nodes.rb +3 -0
- data/examples/data_formats/JSON/json_demo.rb +1 -0
- data/examples/data_formats/JSON/json_lexer.rb +2 -1
- data/lib/rley/base/dotted_item.rb +2 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/engine.rb +8 -7
- data/lib/rley/gfg/grm_flow_graph.rb +2 -0
- data/lib/rley/gfg/item_vertex.rb +2 -0
- data/lib/rley/gfg/vertex.rb +2 -1
- data/lib/rley/lexical/token.rb +5 -4
- data/lib/rley/parse_forest_visitor.rb +7 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +1 -1
- data/lib/rley/parse_rep/parse_rep_creator.rb +2 -2
- data/lib/rley/parse_rep/parse_tree_builder.rb +1 -0
- data/lib/rley/parse_tree_visitor.rb +2 -0
- data/lib/rley/parser/error_reason.rb +8 -6
- data/lib/rley/parser/gfg_chart.rb +5 -5
- data/lib/rley/parser/gfg_parsing.rb +10 -5
- data/lib/rley/parser/parse_entry_tracker.rb +1 -0
- data/lib/rley/parser/parse_state.rb +2 -1
- data/lib/rley/parser/parse_state_tracker.rb +1 -0
- data/lib/rley/parser/parse_walker_factory.rb +7 -1
- data/lib/rley/ptree/parse_tree_node.rb +1 -0
- data/lib/rley/sppf/parse_forest.rb +9 -7
- data/lib/rley/syntax/grammar.rb +10 -6
- data/lib/rley/syntax/grammar_builder.rb +2 -2
- data/lib/rley/syntax/grm_symbol.rb +1 -0
- data/lib/support/base_tokenizer.rb +10 -96
- data/spec/rley/engine_spec.rb +3 -3
- data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -0
- data/spec/rley/parse_forest_visitor_spec.rb +63 -38
- data/spec/rley/parse_rep/groucho_spec.rb +9 -8
- data/spec/rley/parse_tree_visitor_spec.rb +1 -1
- data/spec/rley/parser/gfg_earley_parser_spec.rb +7 -7
- data/spec/rley/parser/gfg_parsing_spec.rb +1 -3
- data/spec/rley/parser/parse_entry_spec.rb +1 -1
- data/spec/rley/support/expectation_helper.rb +2 -1
- data/spec/rley/support/grammar_ambig01_helper.rb +4 -3
- data/spec/rley/support/grammar_arr_int_helper.rb +5 -4
- data/spec/rley/support/grammar_b_expr_helper.rb +5 -4
- data/spec/rley/support/grammar_helper.rb +2 -2
- data/spec/rley/support/grammar_l0_helper.rb +3 -2
- data/spec/rley/support/grammar_pb_helper.rb +5 -28
- data/spec/support/base_tokenizer_spec.rb +7 -9
- metadata +2 -2
@@ -28,6 +28,7 @@ case cli_options[:format]
|
|
28
28
|
when :minify
|
29
29
|
msg = "minify format works for 'cst' representation only"
|
30
30
|
raise StandardError, msg if tree_rep == :ast
|
31
|
+
|
31
32
|
renderer = JSONMinifier.new($stdout)
|
32
33
|
when :ruby
|
33
34
|
msg = "ruby format works for 'ast' representation only"
|
@@ -67,6 +67,7 @@ class JSONLexer
|
|
67
67
|
end_delimiter = scanner.getch
|
68
68
|
err_msg = 'No closing quotes (") found'
|
69
69
|
raise ScanError.new(err_msg) if end_delimiter.nil?
|
70
|
+
|
70
71
|
token = build_token(value, 'string')
|
71
72
|
|
72
73
|
when /[-0-9]/ # Start character of number literal found
|
@@ -85,7 +86,7 @@ class JSONLexer
|
|
85
86
|
|
86
87
|
return token
|
87
88
|
end
|
88
|
-
|
89
|
+
|
89
90
|
def build_token(lexeme, token)
|
90
91
|
pos = Rley::Lexical::Position.new(lineno, scanner.pos - line_start)
|
91
92
|
Rley::Lexical::Token.new(lexeme, token, pos)
|
@@ -113,8 +113,10 @@ module Rley # This module is used as a namespace
|
|
113
113
|
# @return [Boolean]
|
114
114
|
def successor_of?(another)
|
115
115
|
return false if production != another.production
|
116
|
+
|
116
117
|
to_the_left = prev_position
|
117
118
|
return false if to_the_left.nil?
|
119
|
+
|
118
120
|
return to_the_left == another.position
|
119
121
|
end
|
120
122
|
|
data/lib/rley/constants.rb
CHANGED
data/lib/rley/engine.rb
CHANGED
@@ -30,11 +30,11 @@ module Rley # This module is used as a namespace
|
|
30
30
|
# Rley client code from the lower-level classes.
|
31
31
|
class Engine
|
32
32
|
# @!attribute [r] configuration
|
33
|
-
# @return [EngineConfig] the engine's configuration
|
33
|
+
# @return [EngineConfig] the engine's configuration
|
34
34
|
attr_reader :configuration
|
35
|
-
|
35
|
+
|
36
36
|
# @!attribute [r] grammar
|
37
|
-
# @return [Rley::Syntax::Grammar] the grammar of the language to parse
|
37
|
+
# @return [Rley::Syntax::Grammar] the grammar of the language to parse
|
38
38
|
attr_reader :grammar
|
39
39
|
|
40
40
|
# Constructor.
|
@@ -54,17 +54,17 @@ module Rley # This module is used as a namespace
|
|
54
54
|
# instance = Engine.new
|
55
55
|
# instance.build_grammar do
|
56
56
|
# add_terminals('LBRACKET', 'RBRACKET', 'COMMA', 'INTEGER')
|
57
|
-
# add_production('start' => 'array')
|
57
|
+
# add_production('start' => 'array')
|
58
58
|
# add_production('array' => 'LBRACKET elements RBRACKET')
|
59
59
|
# add_production('array' => 'LBRACKET RBRACKET')
|
60
60
|
# add_production('elements' => 'elements COMMA INTEGER')
|
61
|
-
# add_production('elements' => 'INTEGER')
|
61
|
+
# add_production('elements' => 'INTEGER')
|
62
62
|
# end
|
63
63
|
def build_grammar(&aBlock)
|
64
64
|
builder = Rley::Syntax::GrammarBuilder.new(&aBlock)
|
65
65
|
@grammar = builder.grammar
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# Use the given grammar.
|
69
69
|
# @param aGrammar [Rley::Syntax::Grammar]
|
70
70
|
# @return [Rley::Syntax::Grammar] the grammar of the language to parse.
|
@@ -79,6 +79,7 @@ module Rley # This module is used as a namespace
|
|
79
79
|
tokens = []
|
80
80
|
aTokenizer.each do |a_token|
|
81
81
|
next unless a_token
|
82
|
+
|
82
83
|
term_name = a_token.terminal
|
83
84
|
term_symb = grammar.name2symbol[term_name]
|
84
85
|
a_token.instance_variable_set(:@terminal, term_symb)
|
@@ -88,7 +89,7 @@ module Rley # This module is used as a namespace
|
|
88
89
|
parser.gf_graph.diagnose if configuration.diagnose
|
89
90
|
result = parser.parse(tokens)
|
90
91
|
result.tidy_up!
|
91
|
-
|
92
|
+
|
92
93
|
return result
|
93
94
|
end
|
94
95
|
|
@@ -153,6 +153,7 @@ module Rley # This module is used as a namespace
|
|
153
153
|
if stack.last.done?
|
154
154
|
popped = stack.pop
|
155
155
|
break if stack.empty?
|
156
|
+
|
156
157
|
# puts "Popped!"
|
157
158
|
return_key = popped.in_edge.key.sub(/^CALL/, 'RET')
|
158
159
|
curr_edge = visitee.edges.find { |e| e.key == return_key }
|
@@ -197,6 +198,7 @@ module Rley # This module is used as a namespace
|
|
197
198
|
curr_prod = nil
|
198
199
|
theDottedItems.each_with_index do |d_item, index_item|
|
199
200
|
next unless curr_prod.nil? || curr_prod != d_item.production
|
201
|
+
|
200
202
|
# Another production found...
|
201
203
|
curr_prod = d_item.production
|
202
204
|
if curr_prod.empty?
|
data/lib/rley/gfg/item_vertex.rb
CHANGED
@@ -30,7 +30,9 @@ module Rley # This module is used as a namespace
|
|
30
30
|
def shortcut=(aShortcut)
|
31
31
|
unless aShortcut.kind_of?(ShortcutEdge)
|
32
32
|
raise StandardError, 'Invalid shortcut argument'
|
33
|
+
|
33
34
|
end
|
35
|
+
|
34
36
|
=begin
|
35
37
|
unless next_symbol && next_symbol.kind_of?(Syntax::NonTerminal)
|
36
38
|
raise StandardError, 'Invalid shortcut usage'
|
data/lib/rley/gfg/vertex.rb
CHANGED
@@ -46,7 +46,7 @@ module Rley # This module is used as a namespace
|
|
46
46
|
# @return [String]
|
47
47
|
def selfie()
|
48
48
|
result = "#{self.class.name}:#{object_id}"
|
49
|
-
result << %
|
49
|
+
result << %( label="#{label}")
|
50
50
|
return result
|
51
51
|
end
|
52
52
|
|
@@ -69,6 +69,7 @@ module Rley # This module is used as a namespace
|
|
69
69
|
# unless this method is overridden in subclasses
|
70
70
|
def check_add_edge(anEdge)
|
71
71
|
raise StandardError, 'At most one edge accepted' unless edges.empty?
|
72
|
+
|
72
73
|
return anEdge
|
73
74
|
end
|
74
75
|
|
data/lib/rley/lexical/token.rb
CHANGED
@@ -6,8 +6,8 @@ module Rley # This module is used as a namespace
|
|
6
6
|
"line #{line}, column #{column}"
|
7
7
|
end
|
8
8
|
end
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
|
11
11
|
# In Rley, a (lexical) token is an object created by a lexer (tokenizer)
|
12
12
|
# and passed to the parser. Such token an object is created when a lexer
|
13
13
|
# detects that a sequence of characters(a lexeme) from the input stream
|
@@ -25,8 +25,8 @@ module Rley # This module is used as a namespace
|
|
25
25
|
|
26
26
|
# @return [Syntax::Terminal] Terminal symbol corresponding to the lexeme.
|
27
27
|
attr_reader(:terminal)
|
28
|
-
|
29
|
-
# @return [Position] The position of the lexeme in the source file.
|
28
|
+
|
29
|
+
# @return [Position] The position of the lexeme in the source file.
|
30
30
|
attr_reader(:position)
|
31
31
|
|
32
32
|
# Constructor.
|
@@ -35,6 +35,7 @@ module Rley # This module is used as a namespace
|
|
35
35
|
# The terminal symbol corresponding to the lexeme.
|
36
36
|
def initialize(theLexeme, aTerminal, aPosition)
|
37
37
|
raise 'Internal error: nil terminal symbol detected' if aTerminal.nil?
|
38
|
+
|
38
39
|
@lexeme = theLexeme
|
39
40
|
@terminal = aTerminal
|
40
41
|
@position = aPosition
|
@@ -50,7 +50,7 @@ module Rley # This module is used as a namespace
|
|
50
50
|
@subscribers = []
|
51
51
|
@prime_enum = Prime.instance.each
|
52
52
|
@legs = []
|
53
|
-
@node_accesses = Hash.new { |h, key| h[key] =
|
53
|
+
@node_accesses = Hash.new { |h, key| h[key] = [] }
|
54
54
|
end
|
55
55
|
|
56
56
|
# Add a subscriber for the visit event notifications.
|
@@ -81,9 +81,9 @@ module Rley # This module is used as a namespace
|
|
81
81
|
# @param nonTerminalNd [NonTerminalNode] the node to visit.
|
82
82
|
def visit_nonterminal(nonTerminalNd)
|
83
83
|
broadcast(:before_non_terminal, nonTerminalNd)
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
unless nonTerminalNd.signature_exist?
|
85
|
+
nonTerminalNd.add_edge_signatures(prime_enum)
|
86
|
+
end
|
87
87
|
traverse_children(nonTerminalNd)
|
88
88
|
broadcast(:after_non_terminal, nonTerminalNd)
|
89
89
|
end
|
@@ -122,7 +122,7 @@ module Rley # This module is used as a namespace
|
|
122
122
|
# non-terminal node.
|
123
123
|
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
124
124
|
# def end_visit_nonterminal(aNonTerminalNode)
|
125
|
-
|
125
|
+
# broadcast(:after_non_terminal, aNonTerminalNode)
|
126
126
|
# end
|
127
127
|
|
128
128
|
# Visit event. The visitor has completed the visit of the pforest.
|
@@ -167,6 +167,7 @@ module Rley # This module is used as a namespace
|
|
167
167
|
def broadcast(msg, *args)
|
168
168
|
subscribers.each do |subscr|
|
169
169
|
next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
|
170
|
+
|
170
171
|
subscr.send(msg, *args)
|
171
172
|
end
|
172
173
|
end
|
@@ -187,6 +188,7 @@ module Rley # This module is used as a namespace
|
|
187
188
|
|
188
189
|
def pop_node
|
189
190
|
return if legs.empty?
|
191
|
+
|
190
192
|
legs.pop
|
191
193
|
end
|
192
194
|
end # class
|
@@ -17,7 +17,7 @@ module Rley # This module is used as a namespace
|
|
17
17
|
# @return [Hash{String => Class}, Hash{String => Hash{String => Class}}]
|
18
18
|
# Returned hash contains pairs of the form:
|
19
19
|
# terminal name => Class implementing the terminal tokens
|
20
|
-
# terminal name => Hash with pairs:
|
20
|
+
# terminal name => Hash with pairs: production name => Class
|
21
21
|
def terminal2node()
|
22
22
|
raise NotImplementedError
|
23
23
|
end
|
@@ -28,8 +28,8 @@ module Rley # This module is used as a namespace
|
|
28
28
|
# puts "EVENT #{event[0]} #{event[1]}"
|
29
29
|
a_builder.receive_event(*event)
|
30
30
|
end
|
31
|
-
rescue StopIteration
|
32
|
-
# Do nothing
|
31
|
+
rescue StopIteration
|
32
|
+
# Do nothing: gobble the exception
|
33
33
|
end
|
34
34
|
|
35
35
|
a_builder.done!
|
@@ -15,6 +15,7 @@ module Rley # This module is used as a namespace
|
|
15
15
|
# @param aParseTree [ParseTree] the parse tree to visit.
|
16
16
|
def initialize(aParseTree, aTraversalStrategy = :post_order)
|
17
17
|
raise StandardError if aParseTree.nil?
|
18
|
+
|
18
19
|
@ptree = aParseTree
|
19
20
|
@subscribers = []
|
20
21
|
@traversal = aTraversalStrategy
|
@@ -99,6 +100,7 @@ module Rley # This module is used as a namespace
|
|
99
100
|
def broadcast(msg, *args)
|
100
101
|
subscribers.each do |subscr|
|
101
102
|
next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
|
103
|
+
|
102
104
|
subscr.send(msg, *args)
|
103
105
|
end
|
104
106
|
end
|
@@ -5,7 +5,7 @@ module Rley # Module used as a namespace
|
|
5
5
|
# detected by Rley.
|
6
6
|
class ErrorReason
|
7
7
|
# @!attribute [r] rank
|
8
|
-
# @return [Fixnum] The rank number of the offending input token
|
8
|
+
# @return [Fixnum] The rank number of the offending input token
|
9
9
|
attr_reader(:rank)
|
10
10
|
|
11
11
|
# Constructor
|
@@ -45,27 +45,29 @@ module Rley # Module used as a namespace
|
|
45
45
|
class ExpectationNotMet < ErrorReason
|
46
46
|
# The last input token read when error was detected
|
47
47
|
attr_reader(:last_token)
|
48
|
-
|
48
|
+
|
49
49
|
# The terminal symbols expected when error was occurred
|
50
50
|
attr_reader(:expected_terminals)
|
51
51
|
|
52
52
|
def initialize(aRank, lastToken, expectedTerminals)
|
53
53
|
super(aRank)
|
54
54
|
raise StandardError, 'Internal error: nil token' if lastToken.nil?
|
55
|
+
|
55
56
|
@last_token = lastToken.dup
|
56
57
|
@expected_terminals = expectedTerminals.dup
|
57
58
|
end
|
58
59
|
|
59
60
|
protected
|
60
|
-
|
61
|
+
|
61
62
|
def position()
|
62
63
|
return last_token.position if last_token.respond_to?(:position)
|
64
|
+
|
63
65
|
rank + 1
|
64
66
|
end
|
65
|
-
|
67
|
+
|
66
68
|
# Emit a text explaining the expected terminal symbols
|
67
69
|
def expectations
|
68
|
-
term_names = expected_terminals.map(&:name)
|
70
|
+
term_names = expected_terminals.map(&:name)
|
69
71
|
explain = 'Expected one '
|
70
72
|
explain << if expected_terminals.size > 1
|
71
73
|
"of: ['#{term_names.join("', '")}']"
|
@@ -92,7 +94,7 @@ module Rley # Module used as a namespace
|
|
92
94
|
|
93
95
|
# This parse error occurs when all input tokens were consumed
|
94
96
|
# but the parser still expected one or more tokens from the input.
|
95
|
-
class PrematureInputEnd < ExpectationNotMet
|
97
|
+
class PrematureInputEnd < ExpectationNotMet
|
96
98
|
# Returns the reason's message.
|
97
99
|
def to_s
|
98
100
|
err_msg = "Premature end of input after '#{last_token.lexeme}'"
|
@@ -13,7 +13,7 @@ module Rley # This module is used as a namespace
|
|
13
13
|
attr_reader(:sets)
|
14
14
|
|
15
15
|
# @param aGFGraph [GFG::GrmFlowGraph] The GFG for the grammar in use.
|
16
|
-
def initialize(
|
16
|
+
def initialize(aGFGraph)
|
17
17
|
@sets = [ ParseEntrySet.new ]
|
18
18
|
push_entry(aGFGraph.start_vertex, 0, 0, :start_rule)
|
19
19
|
end
|
@@ -45,7 +45,7 @@ module Rley # This module is used as a namespace
|
|
45
45
|
# Push a parse entry for the chart entry with given index
|
46
46
|
# @param anIndex [Integer] The rank of the token in the input stream.
|
47
47
|
# @return [ParseEntry] the passed parse entry if it is pushed
|
48
|
-
def push_entry(aVertex, anOrigin, anIndex,
|
48
|
+
def push_entry(aVertex, anOrigin, anIndex, reason)
|
49
49
|
# puts "push_entry:"
|
50
50
|
# puts " aVertex #{aVertex.inspect}"
|
51
51
|
# puts " anOrigin: #{anOrigin}"
|
@@ -53,8 +53,9 @@ module Rley # This module is used as a namespace
|
|
53
53
|
# puts " _reason: #{_reason}"
|
54
54
|
new_entry = ParseEntry.new(aVertex, anOrigin)
|
55
55
|
if anIndex == sets.size
|
56
|
-
err_msg = "Internal error: unexpected push reason #{
|
57
|
-
raise StandardError, err_msg if
|
56
|
+
err_msg = "Internal error: unexpected push reason #{reason}"
|
57
|
+
raise StandardError, err_msg if reason != :scan_rule
|
58
|
+
|
58
59
|
add_entry_set
|
59
60
|
end
|
60
61
|
pushed = self[anIndex].push_entry(new_entry)
|
@@ -98,7 +99,6 @@ module Rley # This module is used as a namespace
|
|
98
99
|
def add_entry_set()
|
99
100
|
@sets << ParseEntrySet.new
|
100
101
|
end
|
101
|
-
|
102
102
|
end # class
|
103
103
|
end # module
|
104
104
|
end # module
|
@@ -176,6 +176,7 @@ module Rley # This module is used as a namespace
|
|
176
176
|
# followed the syntax specified by the grammar)
|
177
177
|
def success?()
|
178
178
|
return false if @failure_reason
|
179
|
+
|
179
180
|
return chart.accepting_entry ? true : false
|
180
181
|
end
|
181
182
|
|
@@ -272,6 +273,7 @@ END_MSG
|
|
272
273
|
# Rule: has 1..* antecedents, all of them are exit items
|
273
274
|
antecedents.each do |antec|
|
274
275
|
next if antec.exit_entry?
|
276
|
+
|
275
277
|
msg_prefix = "End vertex parse entry #{consequent}"
|
276
278
|
msg_suffix = " has for antecedent #{antec}"
|
277
279
|
raise StandardError, msg_prefix + msg_suffix
|
@@ -280,16 +282,18 @@ END_MSG
|
|
280
282
|
when Rley::GFG::ItemVertex
|
281
283
|
# Rule: has exactly one antecedent
|
282
284
|
# if antecedents.size > 1
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
285
|
+
# msg_prefix = "Parse entry #{consequent} | #{aPosition}"
|
286
|
+
# msg = " has more than one antecedent:\n"
|
287
|
+
# msg_suffix = antecedents.map(&:to_s).join("\n")
|
288
|
+
# raise(StandardError, msg_prefix + msg + msg_suffix)
|
287
289
|
# end
|
288
290
|
|
289
291
|
when Rley::GFG::StartVertex
|
290
|
-
# Rule: has 0..* antecedents, all of them are
|
292
|
+
# Rule: has 0..* antecedents, all of them are
|
293
|
+
# item vertices but not exit items
|
291
294
|
antecedents.each do |antec|
|
292
295
|
next if antec.dotted_entry? && !antec.end_entry?
|
296
|
+
|
293
297
|
msg_prefix = "Parse entry #{consequent}"
|
294
298
|
msg_suffix = " has for antecedent #{antec}"
|
295
299
|
raise StandardError, msg_prefix + msg_suffix
|
@@ -304,6 +308,7 @@ END_MSG
|
|
304
308
|
# chart entry with given index if it isn't yet in the chart entry.
|
305
309
|
def push_entry(aVertex, anOrigin, aChartIndex, aReason)
|
306
310
|
raise StandardError, 'Vertex may not be nil' if aVertex.nil?
|
311
|
+
|
307
312
|
chart.push_entry(aVertex, anOrigin, aChartIndex, aReason)
|
308
313
|
end
|
309
314
|
|
@@ -26,6 +26,7 @@ module Rley # This module is used as a namespace
|
|
26
26
|
# Write accessor. Set the given parse entry as the current one.
|
27
27
|
def parse_entry=(aParseEntry)
|
28
28
|
raise StandardError, 'Nil parse entry' if aParseEntry.nil?
|
29
|
+
|
29
30
|
@parse_entry = aParseEntry
|
30
31
|
processed_entries[parse_entry] = true
|
31
32
|
end
|
@@ -16,7 +16,7 @@ module Rley # This module is used as a namespace
|
|
16
16
|
def ==(other)
|
17
17
|
return true if object_id == other.object_id
|
18
18
|
|
19
|
-
result = (dotted_rule == other.dotted_rule) &&
|
19
|
+
result = (dotted_rule == other.dotted_rule) &&
|
20
20
|
(origin == other.origin)
|
21
21
|
|
22
22
|
return result
|
@@ -43,6 +43,7 @@ module Rley # This module is used as a namespace
|
|
43
43
|
return false if other == self
|
44
44
|
|
45
45
|
return false unless origin == other.origin
|
46
|
+
|
46
47
|
other_production = other.dotted_rule.production
|
47
48
|
return false unless dotted_rule.production == other_production
|
48
49
|
|
@@ -26,6 +26,7 @@ module Rley # This module is used as a namespace
|
|
26
26
|
# Write accessor. Set the given parse state as the current one.
|
27
27
|
def parse_state=(aParseState)
|
28
28
|
raise StandardError, 'Nil parse state' if aParseState.nil?
|
29
|
+
|
29
30
|
@parse_state = aParseState
|
30
31
|
processed_states[parse_state] = true
|
31
32
|
end
|
@@ -54,6 +54,7 @@ module Rley # This module is used as a namespace
|
|
54
54
|
def build_walker(acceptingEntry, maxIndex, lazyWalk = false)
|
55
55
|
msg = 'Internal error: nil entry argument'
|
56
56
|
raise StandardError, msg if acceptingEntry.nil?
|
57
|
+
|
57
58
|
# Local context for the enumerator
|
58
59
|
ctx = init_context(acceptingEntry, maxIndex, lazyWalk)
|
59
60
|
|
@@ -65,9 +66,12 @@ module Rley # This module is used as a namespace
|
|
65
66
|
receiver << event unless event.nil?
|
66
67
|
|
67
68
|
if ctx.curr_entry.orphan? # No antecedent?...
|
68
|
-
|
69
|
+
msg_prefix = "No antecedent for #{ctx.curr_entry}"
|
70
|
+
msg_suffix = "at rank #{ctx.entry_set_index}"
|
71
|
+
err_msg = msg_prefix + ' ' + msg_suffix
|
69
72
|
raise StandardError, err_msg unless ctx.curr_entry.start_entry?
|
70
73
|
break if ctx.backtrack_points.empty?
|
74
|
+
|
71
75
|
receiver << use_backtrack_point(ctx)
|
72
76
|
receiver << visit_entry(ctx.curr_entry, ctx)
|
73
77
|
end
|
@@ -187,6 +191,7 @@ module Rley # This module is used as a namespace
|
|
187
191
|
# Pop top of stack
|
188
192
|
err_msg = 'Return stack empty!'
|
189
193
|
raise ScriptError, err_msg if aContext.return_stack.empty?
|
194
|
+
|
190
195
|
aContext.return_stack.pop
|
191
196
|
# puts "Pop from return stack matching entry #{new_entry}"
|
192
197
|
elsif traversed_edge.kind_of?(GFG::ScanEdge)
|
@@ -264,6 +269,7 @@ module Rley # This module is used as a namespace
|
|
264
269
|
# to a item vertex
|
265
270
|
def select_calling_entry(aContext)
|
266
271
|
raise ScriptError, 'Empty return stack' if aContext.return_stack.empty?
|
272
|
+
|
267
273
|
# Retrieve top of stack
|
268
274
|
tos = aContext.return_stack.pop
|
269
275
|
tos_dotted_item = tos.vertex.dotted_item
|