rley 0.3.04 → 0.3.05
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 +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
|