rley 0.3.04 → 0.3.05
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,115 +1,113 @@
|
|
1
|
-
module Rley # This module is used as a namespace
|
2
|
-
# A visitor class dedicated in the visit of a parse forest.
|
3
|
-
# It combines the Visitor and Observer patterns.
|
4
|
-
class ParseForestVisitor
|
5
|
-
# Link to the parse forest to visit
|
6
|
-
attr_reader(:pforest)
|
7
|
-
|
8
|
-
# List of objects that subscribed to the visit event notification.
|
9
|
-
attr_reader(:subscribers)
|
10
|
-
|
11
|
-
# A Hash with pairs of the form: Node => node visit data
|
12
|
-
attr_reader(:agenda)
|
13
|
-
|
14
|
-
# Indicates the kind of forest traversal to perform: :post_order, :pre-order
|
15
|
-
attr_reader(:traversal)
|
16
|
-
|
17
|
-
# Build a visitor for the given pforest.
|
18
|
-
# @param aParseForest [ParseForest] the parse tree to visit.
|
19
|
-
def initialize(aParseForest, aTraversalStrategy = :post_order)
|
20
|
-
@pforest = aParseForest
|
21
|
-
@subscribers = []
|
22
|
-
@traversal = aTraversalStrategy
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
traverse_children(aNonTerminalNode)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
# End of file
|
1
|
+
module Rley # This module is used as a namespace
|
2
|
+
# A visitor class dedicated in the visit of a parse forest.
|
3
|
+
# It combines the Visitor and Observer patterns.
|
4
|
+
class ParseForestVisitor
|
5
|
+
# Link to the parse forest to visit
|
6
|
+
attr_reader(:pforest)
|
7
|
+
|
8
|
+
# List of objects that subscribed to the visit event notification.
|
9
|
+
attr_reader(:subscribers)
|
10
|
+
|
11
|
+
# A Hash with pairs of the form: Node => node visit data
|
12
|
+
attr_reader(:agenda)
|
13
|
+
|
14
|
+
# Indicates the kind of forest traversal to perform: :post_order, :pre-order
|
15
|
+
attr_reader(:traversal)
|
16
|
+
|
17
|
+
# Build a visitor for the given pforest.
|
18
|
+
# @param aParseForest [ParseForest] the parse tree to visit.
|
19
|
+
def initialize(aParseForest, aTraversalStrategy = :post_order)
|
20
|
+
@pforest = aParseForest
|
21
|
+
@subscribers = []
|
22
|
+
@traversal = aTraversalStrategy
|
23
|
+
end
|
24
|
+
|
25
|
+
# Add a subscriber for the visit event notifications.
|
26
|
+
# @param aSubscriber [Object]
|
27
|
+
def subscribe(aSubscriber)
|
28
|
+
subscribers << aSubscriber
|
29
|
+
end
|
30
|
+
|
31
|
+
# Remove the given object from the subscription list.
|
32
|
+
# The object won't be notified of visit events.
|
33
|
+
# @param aSubscriber [Object]
|
34
|
+
def unsubscribe(aSubscriber)
|
35
|
+
subscribers.delete_if { |entry| entry == aSubscriber }
|
36
|
+
end
|
37
|
+
|
38
|
+
# The signal to begin the visit of the parse forest.
|
39
|
+
def start()
|
40
|
+
pforest.accept(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Visit event. The visitor is about to visit the pforest.
|
45
|
+
# @param aParseForest [ParseForest] the pforest to visit.
|
46
|
+
def start_visit_pforest(aParseForest)
|
47
|
+
broadcast(:before_pforest, aParseForest)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Visit event. The visitor is about to visit the given non terminal node.
|
52
|
+
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
53
|
+
def visit_nonterminal(aNonTerminalNode)
|
54
|
+
if @traversal == :post_order
|
55
|
+
broadcast(:before_non_terminal, aNonTerminalNode)
|
56
|
+
traverse_children(aNonTerminalNode)
|
57
|
+
else
|
58
|
+
traverse_children(aNonTerminalNode)
|
59
|
+
broadcast(:before_non_terminal, aNonTerminalNode)
|
60
|
+
end
|
61
|
+
broadcast(:after_non_terminal, aNonTerminalNode)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Visit event. The visitor is visiting the
|
65
|
+
# given terminal node.
|
66
|
+
# @param aTerminalNode [TerminalNode] the terminal to visit.
|
67
|
+
def visit_terminal(aTerminalNode)
|
68
|
+
broadcast(:before_terminal, aTerminalNode)
|
69
|
+
broadcast(:after_terminal, aTerminalNode)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Visit event. The visitor has completed its visit of the given
|
74
|
+
# non-terminal node.
|
75
|
+
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
76
|
+
def end_visit_nonterminal(aNonTerminalNode)
|
77
|
+
broadcast(:after_non_terminal, aNonTerminalNode)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Visit event. The visitor has completed the visit of the pforest.
|
81
|
+
# @param aParseForest [ParseForest] the pforest to visit.
|
82
|
+
def end_visit_pforest(aParseForest)
|
83
|
+
broadcast(:after_pforest, aParseForest)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Visit event. The visitor is about to visit the children of a non
|
89
|
+
# terminal node.
|
90
|
+
# @param aParentNode [NonTeminalNode] the (non-terminal) parent node.
|
91
|
+
def traverse_children(aParentNode)
|
92
|
+
children = aParentNode.children
|
93
|
+
broadcast(:before_children, aParentNode, children)
|
94
|
+
|
95
|
+
# Let's proceed with the visit of children
|
96
|
+
children.each { |a_node| a_node.accept(self) }
|
97
|
+
|
98
|
+
broadcast(:after_children, aParentNode, children)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Send a notification to all subscribers.
|
102
|
+
# @param msg [Symbol] event to notify
|
103
|
+
# @param args [Array] arguments of the notification.
|
104
|
+
def broadcast(msg, *args)
|
105
|
+
subscribers.each do |a_subscriber|
|
106
|
+
next unless a_subscriber.respond_to?(msg)
|
107
|
+
a_subscriber.send(msg, *args)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end # class
|
111
|
+
end # module
|
112
|
+
|
113
|
+
# End of file
|
@@ -1,27 +1,27 @@
|
|
1
|
-
require_relative '../syntax/grammar'
|
2
|
-
require_relative 'grm_items_builder'
|
3
|
-
require_relative 'parse_tracer'
|
4
|
-
require_relative 'parsing'
|
5
|
-
|
6
|
-
module Rley # This module is used as a namespace
|
7
|
-
module Parser # This module is used as a namespace
|
8
|
-
# Abstract class for Earley parser.
|
9
|
-
class BaseParser
|
10
|
-
include GrmItemsBuilder # Mix-in
|
11
|
-
|
12
|
-
# The grammar of the language.
|
13
|
-
attr_reader(:grammar)
|
14
|
-
|
15
|
-
# The dotted items/rules for the productions of the grammar
|
16
|
-
attr_reader(:dotted_items)
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(aGrammar)
|
20
|
-
@grammar = aGrammar
|
21
|
-
@dotted_items = build_dotted_items(grammar) # Method from mixin
|
22
|
-
end
|
23
|
-
end # class
|
24
|
-
end # module
|
25
|
-
end # module
|
26
|
-
|
27
|
-
# End of file
|
1
|
+
require_relative '../syntax/grammar'
|
2
|
+
require_relative 'grm_items_builder' # Use mix-in module
|
3
|
+
require_relative 'parse_tracer'
|
4
|
+
require_relative 'parsing'
|
5
|
+
|
6
|
+
module Rley # This module is used as a namespace
|
7
|
+
module Parser # This module is used as a namespace
|
8
|
+
# Abstract class for Earley parser.
|
9
|
+
class BaseParser
|
10
|
+
include GrmItemsBuilder # Mix-in for creating dotted items of grammar
|
11
|
+
|
12
|
+
# The grammar of the language.
|
13
|
+
attr_reader(:grammar)
|
14
|
+
|
15
|
+
# The dotted items/rules for the productions of the grammar
|
16
|
+
attr_reader(:dotted_items)
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(aGrammar)
|
20
|
+
@grammar = aGrammar
|
21
|
+
@dotted_items = build_dotted_items(grammar) # Method from mixin
|
22
|
+
end
|
23
|
+
end # class
|
24
|
+
end # module
|
25
|
+
end # module
|
26
|
+
|
27
|
+
# End of file
|
data/lib/rley/parser/chart.rb
CHANGED
@@ -8,7 +8,7 @@ module Rley # This module is used as a namespace
|
|
8
8
|
class Chart
|
9
9
|
# An array of state sets (one per input token + 1)
|
10
10
|
attr_reader(:state_sets)
|
11
|
-
|
11
|
+
|
12
12
|
# The level of trace details reported on stdout during the parse.
|
13
13
|
# The possible values are:
|
14
14
|
# 0: No trace output (default case)
|
@@ -16,10 +16,10 @@ module Rley # This module is used as a namespace
|
|
16
16
|
# 2: Same as of 1 with the addition of the prediction rules
|
17
17
|
attr_reader(:tracer)
|
18
18
|
|
19
|
-
# @param startItems [Array] A non-empty Array of dotted items for
|
19
|
+
# @param startItems [Array] A non-empty Array of dotted items for
|
20
20
|
# the start symbol.
|
21
21
|
# @param tokenCount [Fixnum] The number of lexemes in the input to parse.
|
22
|
-
# @param aTracer [ParseTracer] A tracer object.
|
22
|
+
# @param aTracer [ParseTracer] A tracer object.
|
23
23
|
def initialize(startItems, tokenCount, aTracer)
|
24
24
|
@tracer = aTracer
|
25
25
|
@state_sets = Array.new(tokenCount + 1) { |_| StateSet.new }
|
@@ -34,7 +34,7 @@ module Rley # This module is used as a namespace
|
|
34
34
|
def start_dotted_rule()
|
35
35
|
return self[0].states.first.dotted_rule
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Return the start (non-terminal) symbol of the grammar.
|
39
39
|
def start_symbol()
|
40
40
|
return state_sets.first.states[0].dotted_rule.lhs
|
@@ -44,16 +44,16 @@ module Rley # This module is used as a namespace
|
|
44
44
|
def [](index)
|
45
45
|
return state_sets[index]
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
# Return the index value of the last non-empty state set.
|
49
49
|
def last_index()
|
50
50
|
first_empty = state_sets.find_index(&:empty?)
|
51
|
-
if first_empty.nil?
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
index = if first_empty.nil?
|
52
|
+
state_sets.size - 1
|
53
|
+
else
|
54
|
+
first_empty.zero? ? 0 : first_empty - 1
|
55
|
+
end
|
56
|
+
|
57
57
|
return index
|
58
58
|
end
|
59
59
|
|
@@ -65,14 +65,14 @@ module Rley # This module is used as a namespace
|
|
65
65
|
case aReason
|
66
66
|
when :start_rule, :prediction
|
67
67
|
tracer.trace_prediction(anIndex, new_state)
|
68
|
-
|
68
|
+
|
69
69
|
when :scanning
|
70
70
|
tracer.trace_scanning(anIndex, new_state)
|
71
|
-
|
71
|
+
|
72
72
|
when :completion
|
73
73
|
tracer.trace_completion(anIndex, new_state)
|
74
74
|
else
|
75
|
-
|
75
|
+
raise NotImplementedError, "Unknown push_state mode #{aReason}"
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end # class
|
@@ -6,7 +6,7 @@ module Rley # This module is used as a namespace
|
|
6
6
|
# The right part consists of symbols that are predicted to match the
|
7
7
|
# input tokens.
|
8
8
|
# The terminology stems from the traditional way to visualize the partition
|
9
|
-
# by using a fat dot character as a separator between the left and right
|
9
|
+
# by using a fat dot character as a separator between the left and right
|
10
10
|
# parts
|
11
11
|
# An item with the dot at the beginning (i.e. before any rhs symbol)
|
12
12
|
# is called a predicted item.
|
@@ -29,7 +29,7 @@ module Rley # This module is used as a namespace
|
|
29
29
|
@production = aProduction
|
30
30
|
@position = valid_position(aPosition)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# Return a String representation of the dotted item.
|
34
34
|
# @return [String]
|
35
35
|
def to_s()
|
@@ -41,68 +41,68 @@ module Rley # This module is used as a namespace
|
|
41
41
|
text_values.insert(position, '.')
|
42
42
|
end
|
43
43
|
suffix = text_values.join(' ')
|
44
|
-
|
44
|
+
|
45
45
|
return prefix + suffix
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
# Return true if the dot position is at the start of the rhs.
|
49
49
|
def at_start?()
|
50
|
-
return position
|
50
|
+
return position.zero? || position == -2
|
51
51
|
end
|
52
52
|
|
53
|
-
# An item with the dot at the beginning is called
|
54
|
-
# predicted item
|
55
|
-
|
53
|
+
# An item with the dot at the beginning is called
|
54
|
+
# predicted item
|
55
|
+
alias predicted_item? at_start?
|
56
56
|
|
57
57
|
# A dotted item is called a reduce item if the dot is at the end.
|
58
58
|
def reduce_item?()
|
59
59
|
return position < 0 # Either -1 or -2
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
# The non-terminal symbol that is on the left-side of the production
|
63
63
|
def lhs()
|
64
64
|
return production.lhs
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
# Return the symbol before the dot.
|
68
68
|
# nil is returned if the dot is at the start of the rhs
|
69
69
|
def prev_symbol()
|
70
70
|
before_position = prev_position
|
71
|
-
if before_position.nil?
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
result = if before_position.nil?
|
72
|
+
nil
|
73
|
+
else
|
74
|
+
production.rhs[before_position]
|
75
|
+
end
|
76
|
+
|
77
77
|
return result
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# Return the symbol after the dot.
|
81
81
|
# nil is returned if the dot is at the end
|
82
82
|
def next_symbol()
|
83
|
-
return
|
83
|
+
return position < 0 ? nil : production.rhs[position]
|
84
84
|
end
|
85
|
-
|
86
|
-
# Calculate the position of the dot if were moved by
|
85
|
+
|
86
|
+
# Calculate the position of the dot if were moved by
|
87
87
|
# one step on the left.
|
88
88
|
def prev_position()
|
89
89
|
case position
|
90
90
|
when -2, 0
|
91
91
|
result = nil
|
92
92
|
when -1
|
93
|
-
result =
|
93
|
+
result = production.rhs.size == 1 ? 0 : production.rhs.size - 1
|
94
94
|
else
|
95
95
|
result = position - 1
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
return result
|
99
99
|
end
|
100
100
|
|
101
101
|
# An item with the dot in front of a terminal is called a shift item
|
102
102
|
def shift_item?()
|
103
|
-
return position
|
103
|
+
return position.zero?
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
# Return true if this dotted item has a dot one place
|
107
107
|
# to the right compared to the dotted item argument.
|
108
108
|
def successor_of?(another)
|
@@ -111,7 +111,7 @@ module Rley # This module is used as a namespace
|
|
111
111
|
return false if to_the_left.nil?
|
112
112
|
return to_the_left == another.position
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
|
116
116
|
private
|
117
117
|
|
@@ -119,16 +119,16 @@ module Rley # This module is used as a namespace
|
|
119
119
|
def valid_position(aPosition)
|
120
120
|
rhs_size = production.rhs.size
|
121
121
|
if aPosition < 0 || aPosition > rhs_size
|
122
|
-
|
122
|
+
raise StandardError, 'Out of bound index'
|
123
123
|
end
|
124
124
|
|
125
|
-
if rhs_size
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
125
|
+
index = if rhs_size.zero?
|
126
|
+
-2 # Minus 2 at start/end of empty production
|
127
|
+
elsif aPosition == rhs_size
|
128
|
+
-1 # Minus 1 at end of non-empty production
|
129
|
+
else
|
130
|
+
aPosition
|
131
|
+
end
|
132
132
|
|
133
133
|
return index
|
134
134
|
end
|