tediparse 2.0.0

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 (176) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +319 -0
  3. data/LICENSE +26 -0
  4. data/README.md +308 -0
  5. data/Rakefile +33 -0
  6. data/bin/tediparse +102 -0
  7. data/doc/Defining.md +97 -0
  8. data/doc/Generating-Grammars.md +241 -0
  9. data/doc/Generating.md +332 -0
  10. data/doc/Navigating.md +670 -0
  11. data/doc/Parsing.md +133 -0
  12. data/doc/README.md +51 -0
  13. data/doc/Serializing.md +100 -0
  14. data/doc/Tokenizing.md +136 -0
  15. data/doc/Validating.md +140 -0
  16. data/lib/ruby/array.rb +226 -0
  17. data/lib/ruby/blank.rb +52 -0
  18. data/lib/ruby/exception.rb +14 -0
  19. data/lib/ruby/hash.rb +14 -0
  20. data/lib/ruby/module.rb +60 -0
  21. data/lib/ruby/object.rb +56 -0
  22. data/lib/ruby/string.rb +89 -0
  23. data/lib/ruby/to_d.rb +82 -0
  24. data/lib/ruby/to_date.rb +26 -0
  25. data/lib/ruby/to_time.rb +21 -0
  26. data/lib/ruby/try.rb +46 -0
  27. data/lib/stupidedi/builder.rb +6 -0
  28. data/lib/stupidedi/color.rb +94 -0
  29. data/lib/stupidedi/config/code_list_config.rb +45 -0
  30. data/lib/stupidedi/config/functional_group_config.rb +72 -0
  31. data/lib/stupidedi/config/interchange_config.rb +86 -0
  32. data/lib/stupidedi/config/transaction_set_config.rb +73 -0
  33. data/lib/stupidedi/config.rb +100 -0
  34. data/lib/stupidedi/either.rb +286 -0
  35. data/lib/stupidedi/exceptions/invalid_element_error.rb +7 -0
  36. data/lib/stupidedi/exceptions/invalid_schema_error.rb +7 -0
  37. data/lib/stupidedi/exceptions/missing_grammar_error.rb +50 -0
  38. data/lib/stupidedi/exceptions/output_error.rb +7 -0
  39. data/lib/stupidedi/exceptions/parse_error.rb +7 -0
  40. data/lib/stupidedi/exceptions/stupidedi_error.rb +7 -0
  41. data/lib/stupidedi/exceptions/tokenize_error.rb +7 -0
  42. data/lib/stupidedi/exceptions/zipper_error.rb +7 -0
  43. data/lib/stupidedi/exceptions.rb +13 -0
  44. data/lib/stupidedi/inspect.rb +26 -0
  45. data/lib/stupidedi/interchanges/element_types/separator_val.rb +79 -0
  46. data/lib/stupidedi/interchanges/element_types/special_val.rb +48 -0
  47. data/lib/stupidedi/interchanges/element_types.rb +11 -0
  48. data/lib/stupidedi/interchanges.rb +21 -0
  49. data/lib/stupidedi/parser/builder_dsl.rb +292 -0
  50. data/lib/stupidedi/parser/constraint_table.rb +566 -0
  51. data/lib/stupidedi/parser/generation.rb +147 -0
  52. data/lib/stupidedi/parser/identifier_stack.rb +248 -0
  53. data/lib/stupidedi/parser/instruction.rb +112 -0
  54. data/lib/stupidedi/parser/instruction_table.rb +222 -0
  55. data/lib/stupidedi/parser/navigation.rb +786 -0
  56. data/lib/stupidedi/parser/state_machine.rb +62 -0
  57. data/lib/stupidedi/parser/states/abstract_state.rb +385 -0
  58. data/lib/stupidedi/parser/states/failure_state.rb +69 -0
  59. data/lib/stupidedi/parser/states/functional_group_state.rb +101 -0
  60. data/lib/stupidedi/parser/states/initial_state.rb +62 -0
  61. data/lib/stupidedi/parser/states/interchange_state.rb +96 -0
  62. data/lib/stupidedi/parser/states/loop_state.rb +74 -0
  63. data/lib/stupidedi/parser/states/table_state.rb +90 -0
  64. data/lib/stupidedi/parser/states/transaction_set_state.rb +120 -0
  65. data/lib/stupidedi/parser/states/transmission_state.rb +59 -0
  66. data/lib/stupidedi/parser/tokenization.rb +195 -0
  67. data/lib/stupidedi/parser.rb +32 -0
  68. data/lib/stupidedi/reader/input/abstract_input.rb +137 -0
  69. data/lib/stupidedi/reader/input/delegated_input.rb +112 -0
  70. data/lib/stupidedi/reader/input/file_input.rb +157 -0
  71. data/lib/stupidedi/reader/input.rb +31 -0
  72. data/lib/stupidedi/reader/position.rb +78 -0
  73. data/lib/stupidedi/reader/result.rb +172 -0
  74. data/lib/stupidedi/reader/segment_dict.rb +176 -0
  75. data/lib/stupidedi/reader/separators.rb +90 -0
  76. data/lib/stupidedi/reader/stream_reader.rb +173 -0
  77. data/lib/stupidedi/reader/token_reader.rb +465 -0
  78. data/lib/stupidedi/reader/tokens/component_element_tok.rb +71 -0
  79. data/lib/stupidedi/reader/tokens/composite_element_tok.rb +85 -0
  80. data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +74 -0
  81. data/lib/stupidedi/reader/tokens/segment_tok.rb +74 -0
  82. data/lib/stupidedi/reader/tokens/simple_element_tok.rb +76 -0
  83. data/lib/stupidedi/reader.rb +121 -0
  84. data/lib/stupidedi/schema/abstract_def.rb +76 -0
  85. data/lib/stupidedi/schema/abstract_element_def.rb +35 -0
  86. data/lib/stupidedi/schema/abstract_element_use.rb +47 -0
  87. data/lib/stupidedi/schema/abstract_use.rb +79 -0
  88. data/lib/stupidedi/schema/code_list.rb +99 -0
  89. data/lib/stupidedi/schema/component_element_use.rb +76 -0
  90. data/lib/stupidedi/schema/composite_element_def.rb +103 -0
  91. data/lib/stupidedi/schema/composite_element_use.rb +78 -0
  92. data/lib/stupidedi/schema/element_req.rb +57 -0
  93. data/lib/stupidedi/schema/functional_group_def.rb +124 -0
  94. data/lib/stupidedi/schema/generation/definition_generator.rb +139 -0
  95. data/lib/stupidedi/schema/generation/element_generator.rb +221 -0
  96. data/lib/stupidedi/schema/generation/flat_file_reader.rb +551 -0
  97. data/lib/stupidedi/schema/generation/functional_group_generator.rb +64 -0
  98. data/lib/stupidedi/schema/generation/interchange_generator.rb +145 -0
  99. data/lib/stupidedi/schema/generation/master_loader_generator.rb +121 -0
  100. data/lib/stupidedi/schema/generation/models.rb +85 -0
  101. data/lib/stupidedi/schema/generation/module_loader_generator.rb +64 -0
  102. data/lib/stupidedi/schema/generation/registration_generator.rb +230 -0
  103. data/lib/stupidedi/schema/generation/runner.rb +161 -0
  104. data/lib/stupidedi/schema/generation/segment_generator.rb +130 -0
  105. data/lib/stupidedi/schema/generation/support.rb +78 -0
  106. data/lib/stupidedi/schema/generation/support_modules_generator.rb +126 -0
  107. data/lib/stupidedi/schema/generation/version_modules.rb +35 -0
  108. data/lib/stupidedi/schema/generation.rb +94 -0
  109. data/lib/stupidedi/schema/interchange_def.rb +103 -0
  110. data/lib/stupidedi/schema/loop_def.rb +156 -0
  111. data/lib/stupidedi/schema/repeat_count.rb +86 -0
  112. data/lib/stupidedi/schema/segment_def.rb +122 -0
  113. data/lib/stupidedi/schema/segment_req.rb +46 -0
  114. data/lib/stupidedi/schema/segment_use.rb +99 -0
  115. data/lib/stupidedi/schema/simple_element_def.rb +51 -0
  116. data/lib/stupidedi/schema/simple_element_use.rb +83 -0
  117. data/lib/stupidedi/schema/syntax_note.rb +52 -0
  118. data/lib/stupidedi/schema/table_def.rb +178 -0
  119. data/lib/stupidedi/schema/transaction_set_def.rb +125 -0
  120. data/lib/stupidedi/schema.rb +30 -0
  121. data/lib/stupidedi/sets.rb +42 -0
  122. data/lib/stupidedi/transaction_sets/builder/dsl.rb +192 -0
  123. data/lib/stupidedi/transaction_sets/builder.rb +188 -0
  124. data/lib/stupidedi/transaction_sets/common/implementations/element_reqs.rb +37 -0
  125. data/lib/stupidedi/transaction_sets/common/implementations/segment_reqs.rb +31 -0
  126. data/lib/stupidedi/transaction_sets/common/implementations.rb +11 -0
  127. data/lib/stupidedi/transaction_sets/common.rb +8 -0
  128. data/lib/stupidedi/transaction_sets/validation/ambiguity.rb +395 -0
  129. data/lib/stupidedi/transaction_sets/validation/implementation.rb +12 -0
  130. data/lib/stupidedi/transaction_sets/validation.rb +9 -0
  131. data/lib/stupidedi/transaction_sets.rb +25 -0
  132. data/lib/stupidedi/values/abstract_element_val.rb +19 -0
  133. data/lib/stupidedi/values/abstract_val.rb +133 -0
  134. data/lib/stupidedi/values/composite_element_val.rb +102 -0
  135. data/lib/stupidedi/values/functional_group_val.rb +105 -0
  136. data/lib/stupidedi/values/interchange_val.rb +102 -0
  137. data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
  138. data/lib/stupidedi/values/invalid_segment_val.rb +89 -0
  139. data/lib/stupidedi/values/loop_val.rb +73 -0
  140. data/lib/stupidedi/values/repeated_element_val.rb +113 -0
  141. data/lib/stupidedi/values/segment_val.rb +105 -0
  142. data/lib/stupidedi/values/segment_val_group.rb +20 -0
  143. data/lib/stupidedi/values/simple_element_val.rb +80 -0
  144. data/lib/stupidedi/values/table_val.rb +69 -0
  145. data/lib/stupidedi/values/transaction_set_val.rb +69 -0
  146. data/lib/stupidedi/values/transmission_val.rb +56 -0
  147. data/lib/stupidedi/values.rb +22 -0
  148. data/lib/stupidedi/version.rb +4 -0
  149. data/lib/stupidedi/versions/common/element_reqs.rb +13 -0
  150. data/lib/stupidedi/versions/common/element_types/an.rb +386 -0
  151. data/lib/stupidedi/versions/common/element_types/dt.rb +572 -0
  152. data/lib/stupidedi/versions/common/element_types/id.rb +304 -0
  153. data/lib/stupidedi/versions/common/element_types/nn.rb +312 -0
  154. data/lib/stupidedi/versions/common/element_types/operators.rb +128 -0
  155. data/lib/stupidedi/versions/common/element_types/r.rb +342 -0
  156. data/lib/stupidedi/versions/common/element_types/simple_element.rb +73 -0
  157. data/lib/stupidedi/versions/common/element_types/tm.rb +347 -0
  158. data/lib/stupidedi/versions/common/element_types.rb +29 -0
  159. data/lib/stupidedi/versions/common/segment_reqs.rb +15 -0
  160. data/lib/stupidedi/versions/common/syntax_notes.rb +172 -0
  161. data/lib/stupidedi/versions/common.rb +11 -0
  162. data/lib/stupidedi/versions.rb +25 -0
  163. data/lib/stupidedi/writer/claredi.rb +178 -0
  164. data/lib/stupidedi/writer/default.rb +119 -0
  165. data/lib/stupidedi/writer.rb +7 -0
  166. data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
  167. data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
  168. data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
  169. data/lib/stupidedi/zipper/memoized_cursor.rb +133 -0
  170. data/lib/stupidedi/zipper/path.rb +132 -0
  171. data/lib/stupidedi/zipper/root_cursor.rb +120 -0
  172. data/lib/stupidedi/zipper/stack_cursor.rb +107 -0
  173. data/lib/stupidedi/zipper.rb +45 -0
  174. data/lib/stupidedi.rb +69 -0
  175. data/lib/tediparse.rb +1 -0
  176. metadata +249 -0
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Zipper
6
+ class DanglingCursor < AbstractCursor
7
+ # @return [AbstractCursor]
8
+ attr_reader :parent
9
+
10
+ def initialize(parent)
11
+ @parent = parent
12
+ end
13
+
14
+ # (see AbstractCursor#node)
15
+ def node
16
+ raise Exceptions::ZipperError,
17
+ "DanglingCursor#node should not be called"
18
+ end
19
+
20
+ # (see AbstractCursor#path)
21
+ def path
22
+ Hole.new([], @parent.path.parent, [])
23
+ end
24
+
25
+ # @group Querying the Tree Location
26
+ #########################################################################
27
+
28
+ # (see AbstractCursor#leaf?)
29
+ def leaf?
30
+ true
31
+ end
32
+
33
+ # (see AbstractCursor#root?)
34
+ def root?
35
+ false
36
+ end
37
+
38
+ # (see AbstractCursor#depth)
39
+ def depth
40
+ @parent.depth + 1
41
+ end
42
+
43
+ # (see AbstractCursor#first?)
44
+ def first?
45
+ true
46
+ end
47
+
48
+ # (see AbstractCursor#last?)
49
+ def last?
50
+ true
51
+ end
52
+
53
+ # @group Traversing the Tree
54
+ #########################################################################
55
+
56
+ # @return [AbstractCursor]
57
+ def up
58
+ @parent
59
+ end
60
+
61
+ # (see AbstractCursor#next)
62
+ def next
63
+ raise Exceptions::ZipperError,
64
+ "cannot move to next after last node"
65
+ end
66
+
67
+ # (see AbstractCursor#prev)
68
+ def prev
69
+ raise Exceptions::ZipperError,
70
+ "cannot move to prev before first node"
71
+ end
72
+
73
+ # (see AbstractCursor#first)
74
+ def first
75
+ self
76
+ end
77
+
78
+ # (see AbstractCursor#last)
79
+ def last
80
+ self
81
+ end
82
+
83
+ # @group Editing the Tree
84
+ #########################################################################
85
+
86
+ # (see AbstractCursor#replace)
87
+ def replace(node)
88
+ @parent.append_child(node)
89
+ end
90
+
91
+ alias prepend replace
92
+ alias append replace
93
+
94
+ # (see AbstractCursor#delete)
95
+ def delete
96
+ self
97
+ end
98
+
99
+ # @endgroup
100
+ #########################################################################
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Zipper
6
+ class EditedCursor < AbstractCursor
7
+ # (see AbstractCursor#node)
8
+ attr_reader :node
9
+
10
+ # @return [Hole]
11
+ attr_reader :path
12
+
13
+ # @return [AbstractCursor]
14
+ attr_reader :parent
15
+
16
+ def initialize(node, path, parent)
17
+ @node, @path, @parent =
18
+ node, path, parent
19
+ end
20
+
21
+ # @group Querying the Tree Location
22
+ #########################################################################
23
+
24
+ # (see AbstractCursor#leaf?)
25
+ def leaf?
26
+ @node.leaf? or @node.children.empty?
27
+ end
28
+
29
+ # (see AbstractCursor#root?)
30
+ def root?
31
+ false
32
+ end
33
+
34
+ # @group Traversing the Tree
35
+ #########################################################################
36
+
37
+ # (see AbstractCursor#up)
38
+ # @return [AbstractCursor]
39
+ def up
40
+ node =
41
+ @parent.node.copy(:children =>
42
+ @path.left.reverse.concat(@node.cons(@path.right)))
43
+
44
+ if parent.root?
45
+ RootCursor.new(node)
46
+ else
47
+ EditedCursor.new(node, @path.parent, @parent.parent)
48
+ end
49
+ end
50
+
51
+ # (see AbstractCursor#next)
52
+ # @return [EditedCursor]
53
+ def next
54
+ if last?
55
+ raise Exceptions::ZipperError,
56
+ "cannot move to next after last node"
57
+ end
58
+
59
+ head, *tail = @path.right
60
+
61
+ EditedCursor.new(head,
62
+ Hole.new(@node.cons(@path.left), @path.parent, tail), @parent)
63
+ end
64
+
65
+ # (see AbstractCursor#prev)
66
+ # @return [EditedCursor]
67
+ def prev
68
+ if first?
69
+ raise Exceptions::ZipperError,
70
+ "cannot move to prev before first node"
71
+ end
72
+
73
+ head, *tail = @path.left
74
+
75
+ EditedCursor.new(head,
76
+ Hole.new(tail, @path.parent, @node.cons(@path.right)), @parent)
77
+ end
78
+
79
+ # (see AbstractCursor#first)
80
+ # @return [EditedCursor]
81
+ def first
82
+ if first?
83
+ return self
84
+ end
85
+
86
+ right = @path.left.init.reverse.concat(@node.cons(@path.right))
87
+
88
+ EditedCursor.new(@path.left.last,
89
+ Hole.new([], @path.parent, right), @parent)
90
+ end
91
+
92
+ # (see AbstractCursor#last)
93
+ # @return [EditedCursor]
94
+ def last
95
+ if last?
96
+ return self
97
+ end
98
+
99
+ left = @node.cons(@path.right.init.reverse).concat(@path.left)
100
+
101
+ EditedCursor.new(@path.right.last,
102
+ Hole.new(left, @path.parent, []), @parent)
103
+ end
104
+
105
+ # @group Editing the Tree
106
+ #########################################################################
107
+
108
+ # (see AbstractCursor#last)
109
+ # @return [EditedCursor]
110
+ def append(node)
111
+ EditedCursor.new(node,
112
+ Hole.new(@node.cons(@path.left), @path.parent, @path.right), @parent)
113
+ end
114
+
115
+ # (see AbstractCursor#last)
116
+ # @return [EditedCursor]
117
+ def prepend(node)
118
+ EditedCursor.new(node,
119
+ Hole.new(@path.left, @path.parent, @node.cons(@path.right)), @parent)
120
+ end
121
+
122
+ # (see AbstractCursor#last)
123
+ # @return [EditedCursor]
124
+ def replace(node)
125
+ EditedCursor.new(node, @path, @parent)
126
+ end
127
+
128
+ # (see AbstractCursor#last)
129
+ # @return [EditedCursor]
130
+ def delete
131
+ if not last?
132
+ # Move to `next`
133
+ head, *tail = @path.right
134
+
135
+ EditedCursor.new(head,
136
+ Hole.new(@path.left, @path.parent, tail), @parent)
137
+ elsif not first?
138
+ # Move to `prev`
139
+ head, *tail = @path.left
140
+
141
+ EditedCursor.new(head,
142
+ Hole.new(tail, @path.parent, @path.right), @parent)
143
+ else
144
+ # Deleting the only child
145
+ parent =
146
+ @parent.node.copy(:children =>
147
+ @path.left.reverse.concat(@path.right))
148
+
149
+ EditedCursor.new(parent, @path.parent, @parent.parent).dangle
150
+ end
151
+ end
152
+
153
+ # @endgroup
154
+ #########################################################################
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Zipper
6
+ class MemoizedCursor < AbstractCursor
7
+ # @return [#leaf?, #children, #copy]
8
+ attr_reader :node
9
+
10
+ # @return [Hole]
11
+ attr_reader :path
12
+
13
+ # @private
14
+ # @return [AbstractCursor]
15
+ attr_reader :parent
16
+
17
+ def initialize(node, path, parent)
18
+ @node, @path, @parent =
19
+ node, path, parent
20
+ end
21
+
22
+ # @group Querying the Tree Location
23
+ #########################################################################
24
+
25
+ # (see AbstractCursor#leaf?)
26
+ def leaf?
27
+ @node.leaf? or @node.children.empty?
28
+ end
29
+
30
+ # (see AbstractCursor#root?)
31
+ def root?
32
+ false
33
+ end
34
+
35
+ # @group Traversing the Tree
36
+ #########################################################################
37
+
38
+ # @return [AbstractCursor]
39
+ def up
40
+ @parent
41
+ end
42
+
43
+ # @return [MemoizedCursor]
44
+ def next
45
+ @__next ||= begin
46
+ if last?
47
+ raise Exceptions::ZipperError,
48
+ "cannot move to next after last node"
49
+ end
50
+
51
+ head, *tail = @path.right
52
+
53
+ MemoizedCursor.new(head,
54
+ Hole.new(@node.cons(@path.left), @path.parent, tail), @parent)
55
+ end
56
+ end
57
+
58
+ # @return [MemoizedCursor]
59
+ def prev
60
+ @__prev ||= begin
61
+ if first?
62
+ raise Exceptions::ZipperError,
63
+ "cannot move to prev before first node"
64
+ end
65
+
66
+ head, *tail = @path.left
67
+
68
+ MemoizedCursor.new(head,
69
+ Hole.new(tail, @path.parent, @node.cons(@path.right)), @parent)
70
+ end
71
+ end
72
+
73
+ # @return [MemoizedCursor]
74
+ def first
75
+ @parent.down
76
+ end
77
+
78
+ # @return [MemoizedCursor]
79
+ def last
80
+ current = self
81
+ current = current.next until current.last?
82
+ current
83
+ end
84
+
85
+ # @group Editing the Tree
86
+ #########################################################################
87
+
88
+ # @return [EditedCursor]
89
+ def append(node)
90
+ EditedCursor.new(node,
91
+ Hole.new(@node.cons(@path.left), @path.parent, @path.right), @parent)
92
+ end
93
+
94
+ # @return [EditedCursor]
95
+ def prepend
96
+ EditedCursor.new(node,
97
+ Hole.new(@path.left, @path.parent, @node.cons(@path.right)), @parent)
98
+ end
99
+
100
+ # @return [EditedCursor]
101
+ def replace(node)
102
+ EditedCursor.new(node, @path, @parent)
103
+ end
104
+
105
+ # @return [EditedCursor]
106
+ def delete
107
+ if not last?
108
+ # Move to `next`
109
+ head, *tail = @path.right
110
+
111
+ EditedCursor.new(head,
112
+ Hole.new(@path.left, @path.parent, tail), @parent)
113
+ elsif not first?
114
+ # Move to `prev`
115
+ head, *tail = @path.left
116
+
117
+ EditedCursor.new(head,
118
+ Hole.new(tail, @path.parent, @path.right), @parent)
119
+ else
120
+ # Deleting the only child
121
+ parent =
122
+ @parent.node.copy(:children =>
123
+ @path.left.reverse.concat(@path.right))
124
+
125
+ EditedCursor.new(parent, @path.parent, @parent.parent).dangle
126
+ end
127
+ end
128
+
129
+ # @endgroup
130
+ #########################################################################
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Zipper
6
+ class AbstractPath
7
+ abstract :root?
8
+
9
+ # @return [AbstractPath]
10
+ abstract :parent
11
+
12
+ # Contains the node's leftward siblings, sorted nearest to furthest
13
+ #
14
+ # @return [Array<#leaf?, #children, #copy>]
15
+ abstract :left
16
+
17
+ # Contains the node's rightward siblings, sorted nearest to furthest
18
+ #
19
+ # @return [Array<#leaf?, #children, #copy>]
20
+ abstract :right
21
+
22
+ # True when the node has no rightward siblings
23
+ abstract :last?
24
+
25
+ # True when the node has no leftward siblings
26
+ abstract :first?
27
+
28
+ # Distance from the root node
29
+ #
30
+ # @return [Integer]
31
+ abstract :depth
32
+ end
33
+
34
+ # @private
35
+ Root = Class.new(AbstractPath) do
36
+ def root?
37
+ true
38
+ end
39
+
40
+ # @return self
41
+ def parent
42
+ self
43
+ end
44
+
45
+ # (see AbstractPath#left)
46
+ def left
47
+ []
48
+ end
49
+
50
+ # (see AbstractPath#right)
51
+ def right
52
+ []
53
+ end
54
+
55
+ # (see AbstractPath#last?)
56
+ # @return true
57
+ def last?
58
+ true
59
+ end
60
+
61
+ # (see AbstractPath#first?)
62
+ # @return true
63
+ def first?
64
+ true
65
+ end
66
+
67
+ # (see AbstractPath#depth)
68
+ def depth
69
+ 0
70
+ end
71
+
72
+ def position
73
+ nil
74
+ end
75
+
76
+ # @return [String]
77
+ def inspect
78
+ "root"
79
+ end
80
+ end.new
81
+
82
+ class Hole < AbstractPath
83
+ # (see AbstractPath#right)
84
+ attr_reader :left
85
+
86
+ # @return [AbstractPath]
87
+ attr_reader :parent
88
+
89
+ # (see AbstractPath#left)
90
+ attr_reader :right
91
+
92
+ def initialize(left, parent, right)
93
+ @left, @parent, @right =
94
+ left, parent, right
95
+ end
96
+
97
+ def root?
98
+ false
99
+ end
100
+
101
+ # (see AbstractPath#last?)
102
+ def last?
103
+ @right.empty?
104
+ end
105
+
106
+ # (see AbstractPath#first?)
107
+ def first?
108
+ @left.empty?
109
+ end
110
+
111
+ # (see AbstractPath#depth)
112
+ def depth
113
+ 1 + @parent.depth
114
+ end
115
+
116
+ def position
117
+ @left.length
118
+ end
119
+
120
+ # @return [String]
121
+ def inspect
122
+ "#{@parent.inspect}/#{@left.length}"
123
+ end
124
+
125
+ # @return [Boolean]
126
+ def ==(other)
127
+ depth == other.depth and
128
+ position == other.position
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Zipper
6
+ class RootCursor < AbstractCursor
7
+ # @return [AbstractNode]
8
+ attr_reader :node
9
+
10
+ # @return [AbstractPath]
11
+ attr_reader :path
12
+
13
+ def initialize(node)
14
+ @node, @path =
15
+ node, Root
16
+ end
17
+
18
+ # @group Querying the Tree Location
19
+ #########################################################################
20
+
21
+ # (see AbstractCursor#depth)
22
+ def depth
23
+ 0
24
+ end
25
+
26
+ # (see AbstractCursor#first?)
27
+ def first?
28
+ true
29
+ end
30
+
31
+ # (see AbstractCursor#last?)
32
+ def last?
33
+ true
34
+ end
35
+
36
+ # (see AbstractCursor#leaf?)
37
+ def leaf?
38
+ @node.leaf? or @node.children.empty?
39
+ end
40
+
41
+ # (see AbstractCursor#root?)
42
+ def root?
43
+ true
44
+ end
45
+
46
+ # @group Traversing the Tree
47
+ #########################################################################
48
+
49
+ # (see AbstractCursor#first)
50
+ def first
51
+ self
52
+ end
53
+
54
+ # (see AbstractCursor#last)
55
+ def last
56
+ self
57
+ end
58
+
59
+ # (see AbstractCursor#next)
60
+ # @return [void]
61
+ def next
62
+ raise Exceptions::ZipperError,
63
+ "root node has no siblings"
64
+ end
65
+
66
+ # (see AbstractCursor#prev)
67
+ # @return [void]
68
+ def prev
69
+ raise Exceptions::ZipperError,
70
+ "root node has no siblings"
71
+ end
72
+
73
+ # (see AbstractCursor#root)
74
+ # @return [RootCursor]
75
+ def root
76
+ self
77
+ end
78
+
79
+ # (see AbstractCursor#up)
80
+ # @return [void]
81
+ def up
82
+ raise Exceptions::ZipperError,
83
+ "root node has no parent"
84
+ end
85
+
86
+ # @group Editing the Tree
87
+ #########################################################################
88
+
89
+ # (see AbstractCursor#append)
90
+ # @return [void]
91
+ def append(node)
92
+ raise Exceptions::ZipperError,
93
+ "root node has no siblings"
94
+ end
95
+
96
+ # (see AbstractCursor#prepend)
97
+ # @return [void]
98
+ def prepend(node)
99
+ raise Exceptions::ZipperError,
100
+ "root node has no siblings"
101
+ end
102
+
103
+ # (see AbstractCursor#replace)
104
+ # @return [RootCursor]
105
+ def replace(node)
106
+ RootCursor.new(node)
107
+ end
108
+
109
+ # (see AbstractCursor#delete)
110
+ # @return [void]
111
+ def delete
112
+ raise Exceptions::ZipperError,
113
+ "cannot delete root node"
114
+ end
115
+
116
+ # @endgroup
117
+ #########################################################################
118
+ end
119
+ end
120
+ end