rley 0.7.03 → 0.7.08
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 +362 -62
- data/.travis.yml +6 -7
- data/CHANGELOG.md +20 -1
- data/LICENSE.txt +1 -1
- data/README.md +6 -7
- data/Rakefile +2 -0
- data/appveyor.yml +2 -4
- data/examples/NLP/benchmark_pico_en.rb +2 -0
- data/examples/NLP/engtagger.rb +193 -188
- data/examples/NLP/nano_eng/nano_en_demo.rb +2 -0
- data/examples/NLP/nano_eng/nano_grammar.rb +7 -5
- data/examples/NLP/pico_en_demo.rb +2 -0
- data/examples/data_formats/JSON/cli_options.rb +3 -1
- data/examples/data_formats/JSON/json_ast_builder.rb +14 -9
- data/examples/data_formats/JSON/json_ast_nodes.rb +14 -21
- data/examples/data_formats/JSON/json_demo.rb +2 -0
- data/examples/data_formats/JSON/json_grammar.rb +4 -2
- data/examples/data_formats/JSON/json_lexer.rb +10 -8
- data/examples/data_formats/JSON/json_minifier.rb +3 -1
- data/examples/general/calc_iter1/calc_ast_builder.rb +15 -10
- data/examples/general/calc_iter1/calc_ast_nodes.rb +25 -37
- data/examples/general/calc_iter1/calc_demo.rb +2 -0
- data/examples/general/calc_iter1/calc_grammar.rb +4 -2
- data/examples/general/calc_iter1/calc_lexer.rb +8 -4
- data/examples/general/calc_iter1/spec/calculator_spec.rb +7 -5
- data/examples/general/calc_iter2/calc_ast_builder.rb +7 -3
- data/examples/general/calc_iter2/calc_ast_nodes.rb +29 -43
- data/examples/general/calc_iter2/calc_demo.rb +2 -0
- data/examples/general/calc_iter2/calc_grammar.rb +5 -3
- data/examples/general/calc_iter2/calc_lexer.rb +13 -10
- data/examples/general/calc_iter2/spec/calculator_spec.rb +28 -26
- data/examples/general/left.rb +4 -2
- data/examples/general/right.rb +4 -2
- data/lib/rley.rb +2 -0
- data/lib/rley/base/base_parser.rb +2 -0
- data/lib/rley/base/dotted_item.rb +38 -41
- data/lib/rley/base/grm_items_builder.rb +2 -0
- data/lib/rley/constants.rb +5 -3
- data/lib/rley/engine.rb +22 -24
- data/lib/rley/formatter/asciitree.rb +6 -4
- data/lib/rley/formatter/base_formatter.rb +2 -0
- data/lib/rley/formatter/bracket_notation.rb +3 -8
- data/lib/rley/formatter/debug.rb +8 -6
- data/lib/rley/formatter/json.rb +4 -2
- data/lib/rley/gfg/call_edge.rb +3 -1
- data/lib/rley/gfg/edge.rb +7 -5
- data/lib/rley/gfg/end_vertex.rb +4 -6
- data/lib/rley/gfg/epsilon_edge.rb +3 -5
- data/lib/rley/gfg/grm_flow_graph.rb +31 -25
- data/lib/rley/gfg/item_vertex.rb +12 -22
- data/lib/rley/gfg/non_terminal_vertex.rb +6 -4
- data/lib/rley/gfg/return_edge.rb +2 -0
- data/lib/rley/gfg/scan_edge.rb +3 -1
- data/lib/rley/gfg/shortcut_edge.rb +4 -2
- data/lib/rley/gfg/start_vertex.rb +6 -8
- data/lib/rley/gfg/vertex.rb +47 -41
- data/lib/rley/lexical/token.rb +3 -1
- data/lib/rley/lexical/token_range.rb +8 -6
- data/lib/rley/parse_forest_visitor.rb +7 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +11 -11
- data/lib/rley/parse_rep/cst_builder.rb +7 -4
- data/lib/rley/parse_rep/parse_forest_builder.rb +36 -25
- data/lib/rley/parse_rep/parse_forest_factory.rb +5 -3
- data/lib/rley/parse_rep/parse_rep_creator.rb +18 -13
- data/lib/rley/parse_rep/parse_tree_builder.rb +15 -15
- data/lib/rley/parse_rep/parse_tree_factory.rb +27 -25
- data/lib/rley/parse_tree_visitor.rb +3 -1
- data/lib/rley/parser/error_reason.rb +9 -8
- data/lib/rley/parser/gfg_chart.rb +54 -22
- data/lib/rley/parser/gfg_earley_parser.rb +3 -1
- data/lib/rley/parser/gfg_parsing.rb +51 -31
- data/lib/rley/parser/parse_entry.rb +29 -33
- data/lib/rley/parser/parse_entry_set.rb +32 -27
- data/lib/rley/parser/parse_entry_tracker.rb +6 -4
- data/lib/rley/parser/parse_state.rb +18 -21
- data/lib/rley/parser/parse_state_tracker.rb +6 -4
- data/lib/rley/parser/parse_tracer.rb +15 -13
- data/lib/rley/parser/parse_walker_factory.rb +28 -29
- data/lib/rley/parser/state_set.rb +11 -10
- data/lib/rley/ptree/non_terminal_node.rb +10 -6
- data/lib/rley/ptree/parse_tree.rb +6 -4
- data/lib/rley/ptree/parse_tree_node.rb +7 -5
- data/lib/rley/ptree/terminal_node.rb +9 -7
- data/lib/rley/rley_error.rb +12 -10
- data/lib/rley/sppf/alternative_node.rb +8 -6
- data/lib/rley/sppf/composite_node.rb +9 -7
- data/lib/rley/sppf/epsilon_node.rb +5 -3
- data/lib/rley/sppf/leaf_node.rb +5 -3
- data/lib/rley/sppf/non_terminal_node.rb +2 -0
- data/lib/rley/sppf/parse_forest.rb +19 -17
- data/lib/rley/sppf/sppf_node.rb +9 -8
- data/lib/rley/sppf/token_node.rb +5 -3
- data/lib/rley/syntax/grammar.rb +7 -5
- data/lib/rley/syntax/grammar_builder.rb +11 -9
- data/lib/rley/syntax/grm_symbol.rb +8 -6
- data/lib/rley/syntax/literal.rb +2 -0
- data/lib/rley/syntax/non_terminal.rb +11 -15
- data/lib/rley/syntax/production.rb +13 -11
- data/lib/rley/syntax/symbol_seq.rb +10 -10
- data/lib/rley/syntax/terminal.rb +6 -5
- data/lib/rley/syntax/verbatim_symbol.rb +5 -3
- data/lib/support/base_tokenizer.rb +23 -20
- data/spec/rley/base/dotted_item_spec.rb +4 -2
- data/spec/rley/base/grm_items_builder_spec.rb +2 -0
- data/spec/rley/engine_spec.rb +47 -9
- data/spec/rley/formatter/asciitree_spec.rb +11 -9
- data/spec/rley/formatter/bracket_notation_spec.rb +16 -14
- data/spec/rley/formatter/debug_spec.rb +4 -2
- data/spec/rley/formatter/json_spec.rb +5 -3
- data/spec/rley/gfg/call_edge_spec.rb +2 -0
- data/spec/rley/gfg/edge_spec.rb +2 -0
- data/spec/rley/gfg/end_vertex_spec.rb +7 -5
- data/spec/rley/gfg/epsilon_edge_spec.rb +2 -0
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -0
- data/spec/rley/gfg/item_vertex_spec.rb +12 -10
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +5 -3
- data/spec/rley/gfg/return_edge_spec.rb +2 -0
- data/spec/rley/gfg/scan_edge_spec.rb +2 -0
- data/spec/rley/gfg/shortcut_edge_spec.rb +3 -1
- data/spec/rley/gfg/start_vertex_spec.rb +7 -5
- data/spec/rley/gfg/vertex_spec.rb +5 -3
- data/spec/rley/lexical/token_range_spec.rb +18 -16
- data/spec/rley/lexical/token_spec.rb +4 -2
- data/spec/rley/parse_forest_visitor_spec.rb +167 -163
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +46 -44
- data/spec/rley/parse_rep/ast_builder_spec.rb +8 -6
- data/spec/rley/parse_rep/cst_builder_spec.rb +7 -5
- data/spec/rley/parse_rep/groucho_spec.rb +25 -25
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +28 -26
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -6
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +4 -2
- data/spec/rley/parse_tree_visitor_spec.rb +12 -8
- data/spec/rley/parser/error_reason_spec.rb +8 -6
- data/spec/rley/parser/gfg_chart_spec.rb +17 -4
- data/spec/rley/parser/gfg_earley_parser_spec.rb +16 -11
- data/spec/rley/parser/gfg_parsing_spec.rb +41 -252
- data/spec/rley/parser/parse_entry_set_spec.rb +2 -0
- data/spec/rley/parser/parse_entry_spec.rb +21 -19
- data/spec/rley/parser/parse_state_spec.rb +7 -5
- data/spec/rley/parser/parse_tracer_spec.rb +16 -14
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -8
- data/spec/rley/parser/state_set_spec.rb +24 -22
- data/spec/rley/ptree/non_terminal_node_spec.rb +7 -3
- data/spec/rley/ptree/parse_tree_node_spec.rb +6 -4
- data/spec/rley/ptree/parse_tree_spec.rb +2 -0
- data/spec/rley/ptree/terminal_node_spec.rb +8 -6
- data/spec/rley/sppf/alternative_node_spec.rb +8 -6
- data/spec/rley/sppf/non_terminal_node_spec.rb +5 -3
- data/spec/rley/sppf/token_node_spec.rb +6 -4
- data/spec/rley/support/ambiguous_grammar_helper.rb +5 -4
- data/spec/rley/support/expectation_helper.rb +2 -0
- data/spec/rley/support/grammar_abc_helper.rb +4 -4
- data/spec/rley/support/grammar_ambig01_helper.rb +6 -5
- data/spec/rley/support/grammar_arr_int_helper.rb +6 -5
- data/spec/rley/support/grammar_b_expr_helper.rb +6 -5
- data/spec/rley/support/grammar_helper.rb +2 -0
- data/spec/rley/support/grammar_l0_helper.rb +15 -16
- data/spec/rley/support/grammar_pb_helper.rb +8 -5
- data/spec/rley/support/grammar_sppf_helper.rb +3 -1
- data/spec/rley/syntax/grammar_builder_spec.rb +7 -5
- data/spec/rley/syntax/grammar_spec.rb +8 -6
- data/spec/rley/syntax/grm_symbol_spec.rb +3 -1
- data/spec/rley/syntax/literal_spec.rb +2 -0
- data/spec/rley/syntax/non_terminal_spec.rb +10 -8
- data/spec/rley/syntax/production_spec.rb +15 -13
- data/spec/rley/syntax/symbol_seq_spec.rb +4 -2
- data/spec/rley/syntax/terminal_spec.rb +7 -5
- data/spec/rley/syntax/verbatim_symbol_spec.rb +3 -1
- data/spec/spec_helper.rb +2 -12
- data/spec/support/base_tokenizer_spec.rb +9 -2
- metadata +21 -63
- data/.simplecov +0 -7
- data/Gemfile +0 -8
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rley # This module is used as a namespace
|
2
4
|
module Parser # This module is used as a namespace
|
3
5
|
# Helper class that keeps track of the parse entries used
|
@@ -38,16 +40,16 @@ module Rley # This module is used as a namespace
|
|
38
40
|
end
|
39
41
|
|
40
42
|
# The dotted item for the current parse entry.
|
41
|
-
def curr_dotted_item
|
43
|
+
def curr_dotted_item
|
42
44
|
parse_entry.dotted_rule
|
43
45
|
end
|
44
46
|
|
45
|
-
def symbol_on_left
|
46
|
-
|
47
|
+
def symbol_on_left
|
48
|
+
curr_dotted_item.prev_symbol
|
47
49
|
end
|
48
50
|
|
49
51
|
# Notification that one begins with the previous entry set
|
50
|
-
def to_prev_entry_set
|
52
|
+
def to_prev_entry_set
|
51
53
|
self.entry_set_index = entry_set_index - 1
|
52
54
|
end
|
53
55
|
end # class
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rley # This module is used as a namespace
|
2
4
|
module Parser # This module is used as a namespace
|
3
5
|
class ParseState
|
@@ -16,26 +18,24 @@ module Rley # This module is used as a namespace
|
|
16
18
|
def ==(other)
|
17
19
|
return true if equal?(other)
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
return result
|
21
|
+
(dotted_rule == other.dotted_rule) &&
|
22
|
+
(origin == other.origin)
|
23
23
|
end
|
24
24
|
|
25
25
|
# Returns true if the dot is at the end of the rhs of the production.
|
26
26
|
# In other words, the complete rhs matches the input.
|
27
|
-
def complete?
|
28
|
-
|
27
|
+
def complete?
|
28
|
+
dotted_rule.reduce_item?
|
29
29
|
end
|
30
30
|
|
31
31
|
# Returns true if the dot is at the start of the rhs of the production.
|
32
|
-
def predicted?
|
33
|
-
|
32
|
+
def predicted?
|
33
|
+
dotted_rule.predicted_item?
|
34
34
|
end
|
35
35
|
|
36
36
|
# Next expected symbol in the production
|
37
|
-
def next_symbol
|
38
|
-
|
37
|
+
def next_symbol
|
38
|
+
dotted_rule.next_symbol
|
39
39
|
end
|
40
40
|
|
41
41
|
# Does this parse state have the 'other' as successor?
|
@@ -48,31 +48,28 @@ module Rley # This module is used as a namespace
|
|
48
48
|
return false unless dotted_rule.production == other_production
|
49
49
|
|
50
50
|
prev_position = other.dotted_rule.prev_position
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
return result
|
51
|
+
if prev_position.nil?
|
52
|
+
false
|
53
|
+
else
|
54
|
+
dotted_rule.position == prev_position
|
55
|
+
end
|
58
56
|
end
|
59
57
|
|
60
58
|
# Give a String representation of itself.
|
61
59
|
# The format of the text representation is
|
62
60
|
# "format of dotted rule" + " | " + origin
|
63
61
|
# @return [String]
|
64
|
-
def to_s
|
65
|
-
|
62
|
+
def to_s
|
63
|
+
dotted_rule.to_s + " | #{origin}"
|
66
64
|
end
|
67
65
|
|
68
|
-
|
69
66
|
private
|
70
67
|
|
71
68
|
# Return the validated dotted item(rule)
|
72
69
|
def valid_dotted_rule(aDottedRule)
|
73
70
|
raise StandardError, 'Dotted item cannot be nil' if aDottedRule.nil?
|
74
71
|
|
75
|
-
|
72
|
+
aDottedRule
|
76
73
|
end
|
77
74
|
end # class
|
78
75
|
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rley # This module is used as a namespace
|
2
4
|
module Parser # This module is used as a namespace
|
3
5
|
# Helper class that keeps track of the parse states used
|
@@ -26,7 +28,7 @@ module Rley # This module is used as a namespace
|
|
26
28
|
# Write accessor. Set the given parse state as the current one.
|
27
29
|
def parse_state=(aParseState)
|
28
30
|
raise StandardError, 'Nil parse state' if aParseState.nil?
|
29
|
-
|
31
|
+
|
30
32
|
@parse_state = aParseState
|
31
33
|
processed_states[parse_state] = true
|
32
34
|
end
|
@@ -38,16 +40,16 @@ module Rley # This module is used as a namespace
|
|
38
40
|
end
|
39
41
|
|
40
42
|
# The dotted item for the current parse state.
|
41
|
-
def curr_dotted_item
|
43
|
+
def curr_dotted_item
|
42
44
|
parse_state.dotted_rule
|
43
45
|
end
|
44
46
|
|
45
|
-
def symbol_on_left
|
47
|
+
def symbol_on_left
|
46
48
|
return curr_dotted_item.prev_symbol
|
47
49
|
end
|
48
50
|
|
49
51
|
# Notification that one begins with the previous state set
|
50
|
-
def to_prev_state_set
|
52
|
+
def to_prev_state_set
|
51
53
|
self.state_set_index = state_set_index - 1
|
52
54
|
end
|
53
55
|
end # class
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ostruct'
|
2
4
|
|
3
5
|
module Rley # This module is used as a namespace
|
@@ -9,9 +11,7 @@ module Rley # This module is used as a namespace
|
|
9
11
|
|
10
12
|
# The trace level
|
11
13
|
attr_reader(:level)
|
12
|
-
|
13
14
|
attr_reader(:lexemes)
|
14
|
-
|
15
15
|
attr_reader(:col_width)
|
16
16
|
|
17
17
|
def initialize(aTraceLevel, anIO, aTokenSequence)
|
@@ -34,8 +34,8 @@ module Rley # This module is used as a namespace
|
|
34
34
|
def trace_scanning(aStatesetIndex, aParseState)
|
35
35
|
return unless level
|
36
36
|
|
37
|
-
scan_picture =
|
38
|
-
org = OpenStruct.new(origin: aStatesetIndex - 1,
|
37
|
+
scan_picture = "[#{'-' * (col_width - 1)}]"
|
38
|
+
org = OpenStruct.new(origin: aStatesetIndex - 1,
|
39
39
|
dotted_rule: aParseState.dotted_rule)
|
40
40
|
trace_diagram(aStatesetIndex, org, scan_picture)
|
41
41
|
end
|
@@ -45,35 +45,36 @@ module Rley # This module is used as a namespace
|
|
45
45
|
|
46
46
|
trace_diagram(aStatesetIndex, aParseState, '>')
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def trace_completion(aStatesetIndex, aParseState)
|
50
50
|
return unless level
|
51
51
|
|
52
|
-
if aStatesetIndex == lexemes.size && aParseState.origin.zero? &&
|
52
|
+
if aStatesetIndex == lexemes.size && aParseState.origin.zero? &&
|
53
53
|
aParseState.complete?
|
54
54
|
picture = '=' * (col_width * lexemes.size - 1)
|
55
55
|
else
|
56
56
|
count = col_width * (aStatesetIndex - aParseState.origin) - 1
|
57
57
|
picture = '-' * count
|
58
58
|
end
|
59
|
-
completion_picture =
|
59
|
+
completion_picture = "[#{picture}#{aParseState.complete? ? ']' : '>'}"
|
60
60
|
trace_diagram(aStatesetIndex, aParseState, completion_picture)
|
61
61
|
end
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
|
-
def emit_tokens
|
65
|
+
def emit_tokens
|
66
66
|
literals = lexemes.map { |lx| "'#{lx}'" }
|
67
|
-
print_if 1,
|
67
|
+
print_if 1, "[#{literals.join(', ')}]\n"
|
68
68
|
end
|
69
69
|
|
70
|
-
def emit_heading
|
70
|
+
def emit_heading
|
71
71
|
longest = lexemes.map(&:length).max
|
72
72
|
@col_width = longest + 3
|
73
73
|
headers = lexemes.map { |l| l.center(col_width - 1, ' ').to_s }
|
74
|
-
print_if 1,
|
74
|
+
print_if 1, "|.#{headers.join('.')}.|\n"
|
75
75
|
end
|
76
76
|
|
77
|
+
# rubocop: disable Style/StringConcatenation
|
77
78
|
def padding(aStatesetIndex, aParseState, aPicture)
|
78
79
|
l_pad_pattern = '.' + ' ' * (col_width - 1)
|
79
80
|
left_padding = l_pad_pattern * [0, aParseState.origin].max
|
@@ -81,6 +82,7 @@ module Rley # This module is used as a namespace
|
|
81
82
|
right_padding = r_pad_pattern * (lexemes.size - aStatesetIndex)
|
82
83
|
return left_padding + aPicture + right_padding
|
83
84
|
end
|
85
|
+
# rubocop: enable Style/StringConcatenation
|
84
86
|
|
85
87
|
def parse_state_str(aStatesetIndex, aParseState)
|
86
88
|
"[#{aParseState.origin}:#{aStatesetIndex}] #{aParseState.dotted_rule}"
|
@@ -89,10 +91,10 @@ module Rley # This module is used as a namespace
|
|
89
91
|
def trace_diagram(aStatesetIndex, aParseState, aPicture)
|
90
92
|
diagram = padding(aStatesetIndex, aParseState, aPicture)
|
91
93
|
prefix = '|'
|
92
|
-
suffix =
|
94
|
+
suffix = "| #{parse_state_str(aStatesetIndex, aParseState)}"
|
93
95
|
trace = prefix + diagram + suffix
|
94
96
|
|
95
|
-
print_if 1, trace
|
97
|
+
print_if 1, "#{trace}\n"
|
96
98
|
end
|
97
99
|
end # class
|
98
100
|
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
2
4
|
require_relative '../gfg/call_edge'
|
3
5
|
require_relative '../gfg/scan_edge'
|
@@ -19,16 +21,13 @@ module Rley # This module is used as a namespace
|
|
19
21
|
# non-terminal symbol => { index(=origin) => start entry }
|
20
22
|
:return_stack, # @return [Array<ParseEntry>] A stack of parse entries
|
21
23
|
:backtrack_points,
|
22
|
-
:lazy_walk # If true and revisit end vertex then jump to start vertex
|
23
|
-
)
|
24
|
-
|
24
|
+
:lazy_walk) # If true and revisit end vertex then jump to start vertex
|
25
25
|
|
26
26
|
WalkerBacktrackpoint = Struct.new(
|
27
27
|
:entry_set_index, # Sigma set index of current parse entry
|
28
28
|
:return_stack, # A stack of parse entries
|
29
29
|
:visitee, # The parse entry being visited
|
30
|
-
:antecedent_index
|
31
|
-
)
|
30
|
+
:antecedent_index)
|
32
31
|
|
33
32
|
# A factory that creates an Enumerator object
|
34
33
|
# that itself walks through a GFGParsing object.
|
@@ -51,6 +50,7 @@ module Rley # This module is used as a namespace
|
|
51
50
|
# @param lazyWalk [Boolean] if true then take some shortcut in re-visits.
|
52
51
|
# @return [Enumerator] yields visit events when walking over the
|
53
52
|
# parse result
|
53
|
+
# rubocop: disable Style/OptionalBooleanParameter
|
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?
|
@@ -58,7 +58,7 @@ module Rley # This module is used as a namespace
|
|
58
58
|
# Local context for the enumerator
|
59
59
|
ctx = init_context(acceptingEntry, maxIndex, lazyWalk)
|
60
60
|
|
61
|
-
|
61
|
+
Enumerator.new do |receiver| # 'receiver' is a Yielder
|
62
62
|
# At this point: current entry == accepting entry
|
63
63
|
|
64
64
|
loop do
|
@@ -68,7 +68,7 @@ module Rley # This module is used as a namespace
|
|
68
68
|
if ctx.curr_entry.orphan? # No antecedent?...
|
69
69
|
msg_prefix = "No antecedent for #{ctx.curr_entry}"
|
70
70
|
msg_suffix = "at rank #{ctx.entry_set_index}"
|
71
|
-
err_msg = msg_prefix
|
71
|
+
err_msg = "#{msg_prefix} #{msg_suffix}"
|
72
72
|
raise StandardError, err_msg unless ctx.curr_entry.start_entry?
|
73
73
|
break if ctx.backtrack_points.empty?
|
74
74
|
|
@@ -82,9 +82,8 @@ module Rley # This module is used as a namespace
|
|
82
82
|
ctx.curr_entry = result.last
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
86
|
-
return walker
|
87
85
|
end
|
86
|
+
# rubocop: enable Style/OptionalBooleanParameter
|
88
87
|
|
89
88
|
private
|
90
89
|
|
@@ -99,12 +98,12 @@ module Rley # This module is used as a namespace
|
|
99
98
|
context.backtrack_points = []
|
100
99
|
context.lazy_walk = lazyWalk
|
101
100
|
|
102
|
-
|
101
|
+
context
|
103
102
|
end
|
104
103
|
|
105
104
|
# Initialize the non-terminal to start entry mapping
|
106
|
-
def init_nterm2start
|
107
|
-
|
105
|
+
def init_nterm2start
|
106
|
+
Hash.new do |hsh, defval|
|
108
107
|
entry, index = defval
|
109
108
|
nonterm = entry.vertex.non_terminal
|
110
109
|
if hsh.include? nonterm
|
@@ -114,11 +113,10 @@ module Rley # This module is used as a namespace
|
|
114
113
|
hsh[nonterm] = { index => entry }
|
115
114
|
end
|
116
115
|
end
|
117
|
-
|
118
|
-
return h
|
119
116
|
end
|
120
117
|
|
121
118
|
# [event, entry, index, vertex]
|
119
|
+
# rubocop: disable Lint/DuplicateBranch
|
122
120
|
def visit_entry(anEntry, aContext)
|
123
121
|
index = aContext.entry_set_index
|
124
122
|
aContext.nterm2start[[anEntry, index]] if anEntry.start_entry?
|
@@ -154,11 +152,12 @@ module Rley # This module is used as a namespace
|
|
154
152
|
event = [:visit, anEntry, index]
|
155
153
|
end
|
156
154
|
|
157
|
-
|
155
|
+
event
|
158
156
|
end
|
157
|
+
# rubocop: enable Lint/DuplicateBranch
|
159
158
|
|
160
159
|
def detect_scan_edge(_ctx)
|
161
|
-
|
160
|
+
nil unless aContext.curr_entry.dotted_entry?
|
162
161
|
end
|
163
162
|
|
164
163
|
# Given the current entry from context object
|
@@ -168,13 +167,11 @@ module Rley # This module is used as a namespace
|
|
168
167
|
entries = []
|
169
168
|
return entries if aContext.curr_entry.orphan?
|
170
169
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
return entries
|
170
|
+
if aContext.curr_entry.antecedents.size == 1
|
171
|
+
antecedent_of(aContext)
|
172
|
+
else
|
173
|
+
select_antecedent(aContext)
|
174
|
+
end
|
178
175
|
end
|
179
176
|
|
180
177
|
# Handle the case of an entry having one antecedent only
|
@@ -203,7 +200,7 @@ module Rley # This module is used as a namespace
|
|
203
200
|
raise NotImplementedError, "edge is a #{traversed_edge.class}"
|
204
201
|
end
|
205
202
|
|
206
|
-
|
203
|
+
events
|
207
204
|
end
|
208
205
|
|
209
206
|
# Handle the case of an entry having multiple antecedents
|
@@ -211,6 +208,7 @@ module Rley # This module is used as a namespace
|
|
211
208
|
case aContext.curr_entry.vertex
|
212
209
|
when GFG::EndVertex
|
213
210
|
# puts "Add backtrack point stack #{aContext.curr_entry}"
|
211
|
+
# aContext.curr_entry.antecedents.each { |antec| puts "\t#{antec}" }
|
214
212
|
bp = add_backtrack_point(aContext)
|
215
213
|
new_entry = bp.visitee.antecedents[bp.antecedent_index]
|
216
214
|
|
@@ -228,7 +226,7 @@ module Rley # This module is used as a namespace
|
|
228
226
|
raise StandardError, 'Internal error'
|
229
227
|
end
|
230
228
|
|
231
|
-
|
229
|
+
[new_entry]
|
232
230
|
end
|
233
231
|
|
234
232
|
def add_backtrack_point(aContext)
|
@@ -239,8 +237,8 @@ module Rley # This module is used as a namespace
|
|
239
237
|
bp.visitee = aContext.curr_entry
|
240
238
|
bp.antecedent_index = 0
|
241
239
|
aContext.backtrack_points << bp
|
242
|
-
|
243
|
-
|
240
|
+
# puts "Backtrack size after addition #{aContext.backtrack_points.size}"
|
241
|
+
bp
|
244
242
|
end
|
245
243
|
|
246
244
|
def use_backtrack_point(aContext)
|
@@ -257,9 +255,10 @@ module Rley # This module is used as a namespace
|
|
257
255
|
aContext.backtrack_points.pop
|
258
256
|
end
|
259
257
|
# puts "Backtracking to #{bp.visitee}"
|
258
|
+
# puts "Backtrack size after backtracking #{aContext.backtrack_points.size}"
|
260
259
|
|
261
260
|
# Emit a backtrack event
|
262
|
-
|
261
|
+
[:backtrack, bp.visitee, aContext.entry_set_index]
|
263
262
|
end
|
264
263
|
|
265
264
|
# From the antecedent of the current parse entry
|
@@ -283,7 +282,7 @@ module Rley # This module is used as a namespace
|
|
283
282
|
new_entry ||= aContext.curr_entry
|
284
283
|
|
285
284
|
# puts "Pop from return stack matching entry #{new_entry}"
|
286
|
-
|
285
|
+
new_entry
|
287
286
|
end
|
288
287
|
end # class
|
289
288
|
end # module
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable' # Delegation
|
2
4
|
|
3
5
|
module Rley # This module is used as a namespace
|
@@ -9,7 +11,7 @@ module Rley # This module is used as a namespace
|
|
9
11
|
# The set of parse states
|
10
12
|
attr_reader(:states)
|
11
13
|
|
12
|
-
def initialize
|
14
|
+
def initialize
|
13
15
|
@states = []
|
14
16
|
end
|
15
17
|
|
@@ -32,7 +34,7 @@ module Rley # This module is used as a namespace
|
|
32
34
|
# @param aSymbol [GrmSymbol] the expected symbol
|
33
35
|
# (=on the right of the dot)
|
34
36
|
def states_expecting(aSymbol)
|
35
|
-
|
37
|
+
states.select { |s| s.dotted_rule.next_symbol == aSymbol }
|
36
38
|
end
|
37
39
|
|
38
40
|
# The list of complete ParseState that have the given non-terminal
|
@@ -45,7 +47,7 @@ module Rley # This module is used as a namespace
|
|
45
47
|
|
46
48
|
# The list of ParseState that involve the given production
|
47
49
|
def states_for(aProduction)
|
48
|
-
|
50
|
+
states.select { |s| s.dotted_rule.production == aProduction }
|
49
51
|
end
|
50
52
|
|
51
53
|
# Retrieve the parse state that is the predecessor of the given one.
|
@@ -53,23 +55,22 @@ module Rley # This module is used as a namespace
|
|
53
55
|
dotted_rule = aPState.dotted_rule
|
54
56
|
raise StandardError, aPState.to_s unless dotted_rule.prev_position
|
55
57
|
|
56
|
-
|
57
|
-
return candidate
|
58
|
+
states.find { |s| s.precedes?(aPState) }
|
58
59
|
end
|
59
60
|
|
60
61
|
# The list of distinct expected terminal symbols. An expected symbol
|
61
62
|
# is on the left of a dot in a parse state of the parse set.
|
62
|
-
def expected_terminals
|
63
|
+
def expected_terminals
|
63
64
|
expecting_terminals = states.select do |s|
|
64
65
|
s.dotted_rule.next_symbol.kind_of?(Rley::Syntax::Terminal)
|
65
66
|
end
|
66
67
|
|
67
68
|
terminals = expecting_terminals.map { |s| s.dotted_rule.next_symbol }
|
68
|
-
|
69
|
+
terminals.uniq
|
69
70
|
end
|
70
71
|
|
71
72
|
# Return an Array of Arrays of ambiguous parse states.
|
72
|
-
def ambiguities
|
73
|
+
def ambiguities
|
73
74
|
complete_states = states.select(&:complete?)
|
74
75
|
return [] if complete_states.size <= 1
|
75
76
|
|
@@ -84,14 +85,14 @@ module Rley # This module is used as a namespace
|
|
84
85
|
ambiguous_groups << a_group if a_group.size > 1
|
85
86
|
end
|
86
87
|
|
87
|
-
|
88
|
+
ambiguous_groups
|
88
89
|
end
|
89
90
|
|
90
91
|
private
|
91
92
|
|
92
93
|
def include?(aState)
|
93
94
|
# TODO: make it better than linear search
|
94
|
-
|
95
|
+
states.include?(aState)
|
95
96
|
end
|
96
97
|
end # class
|
97
98
|
end # module
|