rley 0.2.15 → 0.3.00

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/rley/constants.rb +1 -1
  4. data/lib/rley/gfg/call_edge.rb +30 -0
  5. data/lib/rley/gfg/edge.rb +4 -0
  6. data/lib/rley/gfg/end_vertex.rb +1 -1
  7. data/lib/rley/gfg/epsilon_edge.rb +0 -4
  8. data/lib/rley/gfg/grm_flow_graph.rb +32 -7
  9. data/lib/rley/gfg/item_vertex.rb +71 -25
  10. data/lib/rley/gfg/non_terminal_vertex.rb +10 -1
  11. data/lib/rley/gfg/return_edge.rb +31 -0
  12. data/lib/rley/gfg/scan_edge.rb +2 -1
  13. data/lib/rley/gfg/shortcut_edge.rb +26 -0
  14. data/lib/rley/gfg/start_vertex.rb +2 -2
  15. data/lib/rley/gfg/vertex.rb +27 -1
  16. data/lib/rley/parse_forest_visitor.rb +115 -0
  17. data/lib/rley/parser/base_parser.rb +27 -0
  18. data/lib/rley/parser/dotted_item.rb +11 -0
  19. data/lib/rley/parser/earley_parser.rb +3 -15
  20. data/lib/rley/parser/gfg_chart.rb +106 -0
  21. data/lib/rley/parser/gfg_earley_parser.rb +139 -0
  22. data/lib/rley/parser/gfg_parsing.rb +384 -0
  23. data/lib/rley/parser/parse_entry.rb +148 -0
  24. data/lib/rley/parser/parse_entry_set.rb +104 -0
  25. data/lib/rley/parser/parse_entry_tracker.rb +56 -0
  26. data/lib/rley/parser/parse_forest_builder.rb +229 -0
  27. data/lib/rley/parser/parse_forest_factory.rb +54 -0
  28. data/lib/rley/parser/parse_walker_factory.rb +237 -0
  29. data/lib/rley/ptree/token_range.rb +14 -1
  30. data/lib/rley/sppf/alternative_node.rb +34 -0
  31. data/lib/rley/sppf/composite_node.rb +27 -0
  32. data/lib/rley/sppf/epsilon_node.rb +27 -0
  33. data/lib/rley/sppf/leaf_node.rb +12 -0
  34. data/lib/rley/sppf/non_terminal_node.rb +38 -0
  35. data/lib/rley/sppf/parse_forest.rb +48 -0
  36. data/lib/rley/sppf/sppf_node.rb +24 -0
  37. data/lib/rley/sppf/token_node.rb +29 -0
  38. data/lib/rley/syntax/grammar_builder.rb +16 -12
  39. data/lib/rley/syntax/grm_symbol.rb +6 -0
  40. data/lib/rley/syntax/terminal.rb +5 -0
  41. data/spec/rley/gfg/call_edge_spec.rb +51 -0
  42. data/spec/rley/gfg/end_vertex_spec.rb +1 -0
  43. data/spec/rley/gfg/grm_flow_graph_spec.rb +24 -2
  44. data/spec/rley/gfg/item_vertex_spec.rb +75 -6
  45. data/spec/rley/gfg/non_terminal_vertex_spec.rb +14 -0
  46. data/spec/rley/gfg/return_edge_spec.rb +51 -0
  47. data/spec/rley/gfg/shortcut_edge_spec.rb +43 -0
  48. data/spec/rley/gfg/vertex_spec.rb +52 -37
  49. data/spec/rley/parse_forest_visitor_spec.rb +238 -0
  50. data/spec/rley/parser/dotted_item_spec.rb +29 -8
  51. data/spec/rley/parser/gfg_chart_spec.rb +138 -0
  52. data/spec/rley/parser/gfg_earley_parser_spec.rb +918 -0
  53. data/spec/rley/parser/gfg_parsing_spec.rb +565 -0
  54. data/spec/rley/parser/parse_entry_set_spec.rb +179 -0
  55. data/spec/rley/parser/parse_entry_spec.rb +208 -0
  56. data/spec/rley/parser/parse_forest_builder_spec.rb +382 -0
  57. data/spec/rley/parser/parse_forest_factory_spec.rb +81 -0
  58. data/spec/rley/parser/parse_walker_factory_spec.rb +235 -0
  59. data/spec/rley/parser/state_set_spec.rb +4 -0
  60. data/spec/rley/sppf/alternative_node_spec.rb +72 -0
  61. data/spec/rley/sppf/antecedence_graph.rb +87 -0
  62. data/spec/rley/sppf/forest_representation.rb +136 -0
  63. data/spec/rley/sppf/gfg_representation.rb +111 -0
  64. data/spec/rley/sppf/non_terminal_node_spec.rb +64 -0
  65. data/spec/rley/support/ambiguous_grammar_helper.rb +36 -36
  66. data/spec/rley/support/expectation_helper.rb +36 -0
  67. data/spec/rley/support/grammar_helper.rb +28 -0
  68. data/spec/rley/support/grammar_sppf_helper.rb +25 -0
  69. data/spec/rley/syntax/grammar_builder_spec.rb +5 -0
  70. data/spec/rley/syntax/non_terminal_spec.rb +4 -0
  71. data/spec/rley/syntax/terminal_spec.rb +4 -0
  72. metadata +58 -2
@@ -0,0 +1,48 @@
1
+ require_relative 'token_node'
2
+ require_relative 'non_terminal_node'
3
+
4
+ module Rley # This module is used as a namespace
5
+ module SPPF # This module is used as a namespace
6
+ # TODO change comment
7
+ # A parse tree (a.k.a. concrete syntax tree) is a tree-based representation
8
+ # for the parse that corresponds to the input text. In a parse tree,
9
+ # a node corresponds to a grammar symbol used during the parsing:
10
+ # - a leaf node maps to a terminal symbol occurring in
11
+ # the input, and
12
+ # - a intermediate node maps to a non-terminal node reduced
13
+ # during the parse.
14
+ # The root node corresponds to the main/start symbol of the grammar.
15
+ class ParseForest
16
+ # The root node of the forest
17
+ attr_reader(:root)
18
+
19
+ # A Hash with pairs of the kind node key => node
20
+ attr_reader(:key2node)
21
+
22
+ # @param theRootNode [ParseForestNode] The root node of the parse tree.
23
+ def initialize(theRootNode)
24
+ @root = theRootNode
25
+ @key2node = {}
26
+ end
27
+
28
+ # Returns true if the given node is present in the forest.
29
+ def include?(aNode)
30
+ return key2node.include?(aNode)
31
+ end
32
+
33
+
34
+ # Part of the 'visitee' role in the Visitor design pattern.
35
+ # A visitee is expected to accept the visit from a visitor object
36
+ # @param aVisitor [ParseForestVisitor] the visitor object
37
+ def accept(aVisitor)
38
+ aVisitor.start_visit_pforest(self)
39
+
40
+ # Let's proceed with the visit of nodes
41
+ root.accept(aVisitor) if root
42
+
43
+ aVisitor.end_visit_pforest(self)
44
+ end
45
+ end # class
46
+ end # module
47
+ end # module
48
+ # End of file
@@ -0,0 +1,24 @@
1
+ require_relative '../ptree/token_range'
2
+
3
+ module Rley # This module is used as a namespace
4
+ module SPPF # This module is used as a namespace
5
+ # Abstract class. The generalization for all kinds of nodes
6
+ # occurring in a shared packed parse forest.
7
+ class SPPFNode
8
+
9
+ # A range of indices for tokens matching this node.
10
+ attr_reader(:range)
11
+
12
+ def initialize(aRange)
13
+ @range = PTree::TokenRange.new(aRange)
14
+ end
15
+
16
+ # Return the origin (= lower bound of the range
17
+ # = position of first token matched by the symbol)
18
+ def origin()
19
+ return range.low
20
+ end
21
+ end # class
22
+ end # module
23
+ end # module
24
+ # End of file
@@ -0,0 +1,29 @@
1
+ require_relative 'leaf_node'
2
+
3
+ module Rley # This module is used as a namespace
4
+ module SPPF # This module is used as a namespace
5
+ # A node in a parse forest that matches exactly one
6
+ # token from the input
7
+ class TokenNode < LeafNode
8
+ attr_reader(:token)
9
+
10
+ # aPosition is the position of the token in the input stream.
11
+ def initialize(aToken, aPosition)
12
+ range = {low: aPosition, high: aPosition + 1}
13
+ super(range)
14
+ @token = aToken
15
+ end
16
+
17
+ # Emit a (formatted) string representation of the node.
18
+ # Mainly used for diagnosis/debugging purposes.
19
+ def to_string(indentation)
20
+ return "#{token.terminal.name}#{range.to_string(indentation)}"
21
+ end
22
+
23
+ def key()
24
+ @key ||= to_string(0)
25
+ end
26
+ end # class
27
+ end # module
28
+ end # module
29
+ # End of file
@@ -67,21 +67,25 @@ module Rley # This module is used as a namespace
67
67
  end
68
68
 
69
69
  # Given the grammar symbols and productions added to the builder,
70
- # build the resulting grammar.
70
+ # build the resulting grammar (if not yet done).
71
71
  def grammar()
72
- fail StandardError, 'No symbol found for grammar' if symbols.empty?
73
- if productions.empty?
74
- fail StandardError, 'No production found for grammar'
72
+ unless @grammar
73
+ fail StandardError, 'No symbol found for grammar' if symbols.empty?
74
+ if productions.empty?
75
+ fail StandardError, 'No production found for grammar'
76
+ end
77
+
78
+ # Check that each non-terminal appears at least once in lhs.
79
+ all_non_terminals = symbols.values.select { |s| s.is_a?(NonTerminal) }
80
+ all_non_terminals.each do |n_term|
81
+ next if productions.any? { |prod| n_term == prod.lhs }
82
+ fail StandardError, "Nonterminal #{n_term.name} not rewritten"
83
+ end
84
+
85
+ @grammar = Grammar.new(productions.dup)
75
86
  end
76
87
 
77
- # Check that each non-terminal appears at least once in lhs.
78
- all_non_terminals = symbols.values.select { |s| s.is_a?(NonTerminal) }
79
- all_non_terminals.each do |n_term|
80
- next if productions.any? { |prod| n_term == prod.lhs }
81
- fail StandardError, "Nonterminal #{n_term.name} not rewritten"
82
- end
83
-
84
- return Grammar.new(productions.dup)
88
+ return @grammar
85
89
  end
86
90
 
87
91
  private
@@ -12,6 +12,12 @@ module Rley # This module is used as a namespace
12
12
  @name = aName.dup
13
13
  end
14
14
 
15
+ # Return true iff the symbol is a terminal
16
+ def terminal?()
17
+ # Default implementation to override if necessary
18
+ return false
19
+ end
20
+
15
21
  # The String representation of the grammar symbol
16
22
  # @return [String]
17
23
  def to_s()
@@ -12,6 +12,11 @@ module Rley # This module is used as a namespace
12
12
  super(aName)
13
13
  end
14
14
 
15
+ # Return true iff the symbol is a terminal
16
+ def terminal?()
17
+ return true
18
+ end
19
+
15
20
  # @return [false] Return true if the symbol derives
16
21
  # the empty string. As terminal symbol corresponds to a input token
17
22
  # it is by definition non-nullable.
@@ -0,0 +1,51 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ require_relative '../../../lib/rley/syntax/terminal'
4
+ require_relative '../../../lib/rley/syntax/non_terminal'
5
+ require_relative '../../../lib/rley/syntax/production'
6
+ require_relative '../../../lib/rley/parser/dotted_item'
7
+ require_relative '../../../lib/rley/gfg/start_vertex'
8
+ require_relative '../../../lib/rley/gfg/item_vertex'
9
+
10
+ # Load the class under test
11
+ require_relative '../../../lib/rley/gfg/call_edge'
12
+
13
+ module Rley # Open this namespace to avoid module qualifier prefixes
14
+ module GFG # Open this namespace to avoid module qualifier prefixes
15
+ describe CallEdge do
16
+ # Factory method. Builds a production with given left-hand side (LHS)
17
+ # and given RHS (right-hand side)
18
+ def build_prod(theLHS, *theRHSSymbols)
19
+ return Syntax::Production.new(theLHS, theRHSSymbols)
20
+ end
21
+
22
+ let(:t_a) { Rley::Syntax::Terminal.new('a') }
23
+ let(:t_b) { Rley::Syntax::Terminal.new('b') }
24
+ let(:t_c) { Rley::Syntax::Terminal.new('c') }
25
+ let(:nt_sentence) { Rley::Syntax::NonTerminal.new('sentence') }
26
+ let(:nt_b_sequence) { Rley::Syntax::NonTerminal.new('b_sequence') }
27
+ let(:sample_prod) { build_prod(nt_sentence, t_a, nt_b_sequence, t_c) }
28
+ let(:sample_item) { Parser::DottedItem.new(sample_prod, 1) }
29
+
30
+ let(:vertex1) { ItemVertex.new(sample_item) }
31
+ let(:vertex2) { StartVertex.new('to') }
32
+ subject { CallEdge.new(vertex1, vertex2) }
33
+
34
+ context 'Initialization:' do
35
+ it 'should be created with two vertice arguments' do
36
+ expect { CallEdge.new(vertex1, vertex2) }.not_to raise_error
37
+ end
38
+ end # context
39
+
40
+
41
+ context 'Provided services:' do
42
+ it 'should know its key' do
43
+ expectation = "CALL_#{sample_prod.object_id}_#{sample_item.position}"
44
+ expect(subject.key).to eq(expectation)
45
+ end
46
+ end # context
47
+ end # describe
48
+ end # module
49
+ end # module
50
+
51
+ # End of file
@@ -18,6 +18,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
18
18
  allow(sample_nt).to receive(:to_s).and_return('NT')
19
19
  expect(subject.label).to eq('NT.')
20
20
  end
21
+
21
22
  end # context
22
23
  end # describe
23
24
  end # module
@@ -1,5 +1,4 @@
1
1
  require_relative '../../spec_helper'
2
- require 'pp'
3
2
 
4
3
  require_relative '../support/grammar_abc_helper'
5
4
  require_relative '../../../lib/rley/parser/grm_items_builder'
@@ -53,6 +52,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
53
52
  expect { GrmFlowGraph.new(items_from_grammar) }.not_to raise_error
54
53
  end
55
54
 
55
+ it 'should know its main start vertex' do
56
+ expect(subject.start_vertex).to eq(subject.vertices.first)
57
+ end
58
+
56
59
  it 'should have the correct number of vertices' do
57
60
  # Number of vertices = count of dotted items +...
58
61
  # ... 2 * count of non-terminals
@@ -128,9 +131,28 @@ module Rley # Open this namespace to avoid module qualifier prefixes
128
131
  'A => a . --> A.',
129
132
  'A => . --> A.'
130
133
  ]
131
-
134
+
132
135
  compare_graph_expectations(graph, expected)
133
136
  end
137
+
138
+ it 'should have shortcut edges' do
139
+ subject.vertices.each do |a_vertex|
140
+ next unless a_vertex.kind_of?(ItemVertex)
141
+ if a_vertex.next_symbol.kind_of?(Syntax::NonTerminal)
142
+ expect(a_vertex.shortcut).not_to be_nil
143
+ my_d_item = a_vertex.dotted_item
144
+
145
+ # Retrieve dotted item of shortcut successor
146
+ other_d_item = a_vertex.shortcut.successor.dotted_item
147
+
148
+ # Now the checks...
149
+ expect(my_d_item.production).to eq(other_d_item.production)
150
+ expect(my_d_item.position).to eq(other_d_item.prev_position)
151
+ else
152
+ expect(a_vertex.shortcut).to be_nil
153
+ end
154
+ end
155
+ end
134
156
  end # context
135
157
  end # describe
136
158
  end # module
@@ -3,6 +3,7 @@ require_relative '../../../lib/rley/syntax/terminal'
3
3
  require_relative '../../../lib/rley/syntax/non_terminal'
4
4
  require_relative '../../../lib/rley/syntax/production'
5
5
  require_relative '../../../lib/rley/parser/dotted_item'
6
+ require_relative '../../../lib/rley/gfg/shortcut_edge'
6
7
 
7
8
  # Load the class under test
8
9
  require_relative '../../../lib/rley/gfg/item_vertex'
@@ -10,20 +11,25 @@ require_relative '../../../lib/rley/gfg/item_vertex'
10
11
  module Rley # Open this namespace to avoid module qualifier prefixes
11
12
  module GFG # Open this namespace to avoid module qualifier prefixes
12
13
  describe ItemVertex do
14
+
13
15
  # Factory method. Builds a production with given left-hand side (LHS)
14
16
  # and given RHS (right-hand side)
15
17
  def build_prod(theLHS, *theRHSSymbols)
16
18
  return Syntax::Production.new(theLHS, theRHSSymbols)
17
19
  end
18
20
 
19
- let(:t_a) { Rley::Syntax::Terminal.new('A') }
20
- let(:t_b) { Rley::Syntax::Terminal.new('B') }
21
- let(:t_c) { Rley::Syntax::Terminal.new('C') }
21
+ let(:t_a) { Rley::Syntax::Terminal.new('a') }
22
+ let(:t_b) { Rley::Syntax::Terminal.new('b') }
23
+ let(:t_c) { Rley::Syntax::Terminal.new('c') }
22
24
  let(:nt_sentence) { Rley::Syntax::NonTerminal.new('sentence') }
23
- let(:sample_prod) { build_prod(nt_sentence, t_a, t_b, t_c) }
25
+ let(:nt_b_sequence) { Rley::Syntax::NonTerminal.new('b_sequence') }
26
+ let(:sample_prod) { build_prod(nt_sentence, t_a, nt_b_sequence, t_c) }
24
27
  let(:other_prod) { build_prod(nt_sentence, t_a) }
28
+ let(:recursive_prod) {build_prod(nt_b_sequence, nt_b_sequence, t_b )}
29
+ let(:b_prod) {build_prod(nt_b_sequence, t_b )}
25
30
  let(:empty_prod) { build_prod(nt_sentence) }
26
31
  let(:sample_item) { Parser::DottedItem.new(sample_prod, 1) }
32
+ let(:next_item) { Parser::DottedItem.new(sample_prod, 2) }
27
33
  subject { ItemVertex.new(sample_item) }
28
34
 
29
35
  context 'Initialization:' do
@@ -34,15 +40,78 @@ module Rley # Open this namespace to avoid module qualifier prefixes
34
40
  it 'should know its dotted item' do
35
41
  expect(subject.dotted_item).to eq(sample_item)
36
42
  end
43
+
44
+ it 'should not have any shortcut edge at start' do
45
+ expect(subject.shortcut).to be_nil
46
+ end
37
47
  end # context
38
-
48
+
39
49
  context 'Provided services:' do
40
50
  it 'should know its label' do
41
51
  expect(subject.label).to eq(sample_item.to_s)
42
52
  end
53
+
54
+ it 'should know the lhs of the production' do
55
+ expect(subject.lhs).to eq(nt_sentence)
56
+ end
57
+
58
+ it 'should know whether it has a dot at the end of the rhs' do
59
+ # Case: dot not at the end
60
+ expect(subject).not_to be_complete
61
+
62
+ # Case: dot at the end
63
+ instance1 = ItemVertex.new(Parser::DottedItem.new(sample_prod, 3))
64
+ expect(instance1).to be_complete
65
+
66
+ # Case: empty production
67
+ instance2 = ItemVertex.new(Parser::DottedItem.new(empty_prod, 0))
68
+ expect(instance2).to be_complete
69
+ end
70
+
71
+ it 'should know the previous symbol (if any) in the rhs' do
72
+ # Case: dot is after first symbol
73
+ instance1 = ItemVertex.new(sample_item)
74
+ expect(instance1.prev_symbol).to eq(t_a)
75
+
76
+ # Case: dot is after second or later symbol
77
+ instance2 = ItemVertex.new(next_item)
78
+ expect(instance2.prev_symbol).to eq(nt_b_sequence)
79
+
80
+ # Case: dot is at begin
81
+ instance3 = ItemVertex.new(Parser::DottedItem.new(sample_prod, 0))
82
+ expect(instance3.prev_symbol).to be_nil
83
+
84
+ # Case: empty production
85
+ instance4 = ItemVertex.new(Parser::DottedItem.new(empty_prod, 0))
86
+ expect(instance4.prev_symbol).to be_nil
87
+ end
43
88
 
44
89
 
45
- end # context
90
+ it 'should know the next symbol (if any) in the rhs' do
91
+ #Case: dot is not penultimate
92
+ expect(subject.next_symbol).to eq(nt_b_sequence)
93
+
94
+ # Case: dot is penultimate
95
+ instance1 = ItemVertex.new(next_item)
96
+ expect(instance1.next_symbol).to eq(t_c)
97
+
98
+ # Case: dot is at end
99
+ instance2 = ItemVertex.new(Parser::DottedItem.new(sample_prod, 3))
100
+ expect(instance2.next_symbol).to be_nil
101
+
102
+ # Case: empty production
103
+ instance3 = ItemVertex.new(Parser::DottedItem.new(empty_prod, 0))
104
+ expect(instance3.next_symbol).to be_nil
105
+ end
106
+
107
+ it 'should accept a shortcut edge' do
108
+ next_vertex = ItemVertex.new(next_item)
109
+
110
+ # The ShortcutEdge constructor invokes the shortcut setter
111
+ shortcut = ShortcutEdge.new(subject, next_vertex)
112
+ expect(subject.shortcut).to eq(shortcut)
113
+ end
114
+ end # context
46
115
  end # describe
47
116
  end # module
48
117
  end # module
@@ -17,6 +17,20 @@ module Rley # Open this namespace to avoid module qualifier prefixes
17
17
  it 'should know its non-terminal' do
18
18
  expect(subject.non_terminal).to eq(sample_nt)
19
19
  end
20
+
21
+
22
+ it 'should accept at more than one outgoing edge' do
23
+ edge1 = double('fake-edge1')
24
+ edge2 = double('fake-edge2')
25
+
26
+ expect { subject.add_edge(edge1) }.not_to raise_error
27
+ expect(subject.edges.size).to eq(1)
28
+ expect(subject.edges.last).to eq(edge1)
29
+
30
+ expect { subject.add_edge(edge2) }.not_to raise_error
31
+ expect(subject.edges.size).to eq(2)
32
+ expect(subject.edges.last).to eq(edge2)
33
+ end
20
34
  end # context
21
35
  end # describe
22
36
  end # module
@@ -0,0 +1,51 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ require_relative '../../../lib/rley/syntax/terminal'
4
+ require_relative '../../../lib/rley/syntax/non_terminal'
5
+ require_relative '../../../lib/rley/syntax/production'
6
+ require_relative '../../../lib/rley/parser/dotted_item'
7
+ require_relative '../../../lib/rley/gfg/end_vertex'
8
+ require_relative '../../../lib/rley/gfg/item_vertex'
9
+
10
+ # Load the class under test
11
+ require_relative '../../../lib/rley/gfg/return_edge'
12
+
13
+ module Rley # Open this namespace to avoid module qualifier prefixes
14
+ module GFG # Open this namespace to avoid module qualifier prefixes
15
+ describe ReturnEdge do
16
+ # Factory method. Builds a production with given left-hand side (LHS)
17
+ # and given RHS (right-hand side)
18
+ def build_prod(theLHS, *theRHSSymbols)
19
+ return Syntax::Production.new(theLHS, theRHSSymbols)
20
+ end
21
+
22
+ let(:t_a) { Rley::Syntax::Terminal.new('a') }
23
+ let(:t_b) { Rley::Syntax::Terminal.new('b') }
24
+ let(:t_c) { Rley::Syntax::Terminal.new('c') }
25
+ let(:nt_sentence) { Rley::Syntax::NonTerminal.new('sentence') }
26
+ let(:nt_b_sequence) { Rley::Syntax::NonTerminal.new('b_sequence') }
27
+ let(:sample_prod) { build_prod(nt_sentence, t_a, nt_b_sequence, t_c) }
28
+ let(:sample_item) { Parser::DottedItem.new(sample_prod, 1) }
29
+
30
+ let(:vertex1) { EndVertex.new('from') }
31
+ let(:vertex2) { ItemVertex.new(sample_item) }
32
+ subject { ReturnEdge.new(vertex1, vertex2) }
33
+
34
+ context 'Initialization:' do
35
+ it 'should be created with two vertice arguments' do
36
+ expect { ReturnEdge.new(vertex1, vertex2) }.not_to raise_error
37
+ end
38
+ end # context
39
+
40
+
41
+ context 'Provided services:' do
42
+ it 'should know its key' do
43
+ expectation = "RET_#{sample_prod.object_id}_#{sample_item.position - 1}"
44
+ expect(subject.key).to eq(expectation)
45
+ end
46
+ end # context
47
+ end # describe
48
+ end # module
49
+ end # module
50
+
51
+ # End of file