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,9 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module TransactionSets
4
+ module Validation
5
+ autoload :Ambiguity, "stupidedi/transaction_sets/validation/ambiguity"
6
+ autoload :Implementation, "stupidedi/transaction_sets/validation/implementation"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Stupidedi
2
+ module TransactionSets
3
+ autoload :Builder, "stupidedi/transaction_sets/builder"
4
+ autoload :Validation, "stupidedi/transaction_sets/validation"
5
+ autoload :Common, "stupidedi/transaction_sets/common"
6
+
7
+ # Per-era transaction-set namespaces that lived under
8
+ # +Stupidedi::TransactionSets+ in the upstream stupidedi gem. tediparse
9
+ # does not ship them; reach for one by name and we surface a helpful
10
+ # error rather than +NameError+. Deeper guide names (X222A1, etc.) are
11
+ # nested under these eras, so catching at the era level is sufficient.
12
+ REMOVED_ERAS = %i[
13
+ TwoThousandOne ThirtyTen ThirtyForty ThirtyFifty FortyTen FiftyTen
14
+ ].freeze
15
+ private_constant :REMOVED_ERAS
16
+
17
+ def self.const_missing(name)
18
+ if REMOVED_ERAS.include?(name.to_sym)
19
+ raise Stupidedi::Exceptions::MissingGrammarError.new("#{self}::#{name}")
20
+ end
21
+
22
+ super
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ class AbstractElementVal < AbstractVal
7
+ # (see AbstractVal#element?)
8
+ # @return true
9
+ def element?
10
+ true
11
+ end
12
+
13
+ # (see AbstractVal#size)
14
+ def size
15
+ 0
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ class AbstractVal
7
+ include Inspect
8
+ include Color
9
+
10
+ # @return [SimpleElementDef, CompositeElementDef, LoopDef, SegmentDef, TableDef]
11
+ abstract :definition
12
+
13
+ # @return [String]
14
+ abstract :descriptor
15
+
16
+ # @see X222.pdf B.1.3.10 Absence of Data
17
+ def empty?
18
+ @children.all?(&:empty?)
19
+ end
20
+
21
+ abstract :leaf?
22
+
23
+ # Number of segments in this subtree
24
+ #
25
+ # @return [Integer]
26
+ def size
27
+ @children.sum(&:size)
28
+ end
29
+
30
+ # True except for {InvalidSegmentVal} and {AbstractElementVal} values
31
+ # that could not be parsed -- "abc" in a numeric field, for example.
32
+ def valid?
33
+ true
34
+ end
35
+
36
+ def invalid?
37
+ not valid?
38
+ end
39
+
40
+ # Is the element not blank?
41
+ def present?
42
+ not empty?
43
+ end
44
+
45
+ # Is the element not present?
46
+ def blank?
47
+ empty?
48
+ end
49
+
50
+ # Is this a {TransmissionVal}?
51
+ def transmission?
52
+ false
53
+ end
54
+
55
+ # Is this an {InterchangeVal}?
56
+ def interchange?
57
+ false
58
+ end
59
+
60
+ # Is this an {FunctionalGroupVal}?
61
+ def functional_group?
62
+ false
63
+ end
64
+
65
+ # Is this an {TransactionSetVal}?
66
+ def transaction_set?
67
+ false
68
+ end
69
+
70
+ # Is this a {TableVal}?
71
+ def table?
72
+ false
73
+ end
74
+
75
+ # Is this a {LoopVal}?
76
+ def loop?
77
+ false
78
+ end
79
+
80
+ # Is this a {SegmentVal} or {InvalidSegmentVal}?
81
+ def segment?
82
+ false
83
+ end
84
+
85
+ # Is this a {AbstractElementVal}?
86
+ def element?
87
+ false
88
+ end
89
+
90
+ # Is this a {CompositeElementVal}?
91
+ def composite?
92
+ false
93
+ end
94
+
95
+ # Is this a component {SimpleElementVal}?
96
+ def component?
97
+ false
98
+ end
99
+
100
+ # Is this a repeated {AbstractElementVal}?
101
+ def repeated?
102
+ false
103
+ end
104
+
105
+ # Is this a non-component {SimpleElementVal}?
106
+ def simple?
107
+ false
108
+ end
109
+
110
+ # Is this a simple element that represents a separator (delimiter)? For
111
+ # instance, ISA16 represents the repetition separator in version 00501.
112
+ def separator?
113
+ false
114
+ end
115
+
116
+ # Returns the set of characters that are used as data in this subtree, not
117
+ # including the separator (delimiter) elements found in the ISA segment.
118
+ #
119
+ # @return [AbstractSet<String>]
120
+ def characters(result = Sets.absolute([], Reader::C_BYTES.split(//)))
121
+ if leaf?
122
+ if present? and not separator?
123
+ result | to_x12.split(//)
124
+ else
125
+ result
126
+ end
127
+ else
128
+ children.inject(result){|r,c| c.characters(r) }
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ #
7
+ # @see X222.pdf B.1.1.3.3 Composite Data Structure
8
+ #
9
+ class CompositeElementVal < AbstractElementVal
10
+ # @return [Array<SimpleElementVal>]
11
+ attr_reader :children
12
+
13
+ alias component_vals children
14
+
15
+ # @return [CompositeElementUse]
16
+ attr_reader :usage
17
+
18
+ def_delegators :@usage, :definition, :descriptor
19
+
20
+ def initialize(children, usage)
21
+ @children, @usage =
22
+ children, usage
23
+ end
24
+
25
+ # @return [CompositeElementVal]
26
+ def copy(changes = {})
27
+ CompositeElementVal.new \
28
+ changes.fetch(:children, @children),
29
+ changes.fetch(:usage, @usage)
30
+ end
31
+
32
+ def position
33
+ if @children.present?
34
+ @children.head.position
35
+ else
36
+ # GH-194
37
+ "<position unknown>"
38
+ end
39
+ end
40
+
41
+ # @return false
42
+ def leaf?
43
+ false
44
+ end
45
+
46
+ # (see AbstractVal#composite?)
47
+ # @return true
48
+ def composite?
49
+ true
50
+ end
51
+
52
+ # @return [SimpleElementVal]
53
+ def element(n)
54
+ unless n > 0
55
+ raise ArgumentError,
56
+ "n must be positive"
57
+ end
58
+
59
+ @children.at(n - 1)
60
+ end
61
+
62
+ # @return [void]
63
+ def pretty_print(q)
64
+ id = definition.bind do |d|
65
+ "[#{d.id}: #{d.name}]".bind do |s|
66
+ if usage.forbidden?
67
+ ansi.forbidden(s)
68
+ elsif usage.required?
69
+ ansi.required(s)
70
+ else
71
+ ansi.optional(s)
72
+ end
73
+ end
74
+ end
75
+
76
+ q.text(ansi.composite("CompositeElementVal#{id}"))
77
+
78
+ if empty?
79
+ q.text(ansi.composite(".empty"))
80
+ else
81
+ q.group(2, "(", ")") do
82
+ q.breakable ""
83
+ @children.each do |e|
84
+ unless q.current_group.first?
85
+ q.text ", "
86
+ q.breakable
87
+ end
88
+ q.pp e
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ # @return [Boolean]
95
+ def ==(other)
96
+ eql?(other) or
97
+ (other.definition == definition and
98
+ other.children == @children)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ #
7
+ # @see X222.pdf B.1.1.3.13 Functional Group
8
+ # @see X222.pdf B.1.1.4.2 Functional Groups
9
+ #
10
+ class FunctionalGroupVal < AbstractVal
11
+ include SegmentValGroup
12
+
13
+ # @return [FunctionalGroupDef]
14
+ attr_reader :definition
15
+
16
+ def_delegators :definition, :descriptor
17
+
18
+ # @return [Array<SegmentVal, TransactionSetVal>]
19
+ attr_reader :children
20
+
21
+ def_delegators "@children.head", :position
22
+
23
+ def initialize(definition, children)
24
+ @definition, @children =
25
+ definition, children
26
+ end
27
+
28
+ # @return [FunctionalGroupVal]
29
+ def copy(changes = {})
30
+ FunctionalGroupVal.new \
31
+ changes.fetch(:definition, @definition),
32
+ changes.fetch(:children, @children)
33
+ end
34
+
35
+ # (see AbstractVal#functional_group?)
36
+ # @return true
37
+ def functional_group?
38
+ true
39
+ end
40
+
41
+ # @return [String, nil]
42
+ def version
43
+ if at(6) == "X"
44
+ at(7).to_s.slice(0, 3)
45
+ end
46
+ end
47
+
48
+ # @return [String, nil]
49
+ def release
50
+ if at(6) == "X"
51
+ at(7).to_s.slice(0, 4)
52
+ end
53
+ end
54
+
55
+ # @return [String, nil]
56
+ def subrelease
57
+ if at(6) == "X"
58
+ at(7).to_s.slice(0, 5)
59
+ end
60
+ end
61
+
62
+ # @return [String, nil]
63
+ def implementation
64
+ if at(6) == "X"
65
+ at(7).to_s.slice(6, 4)
66
+ end
67
+ end
68
+
69
+ # @return [Module]
70
+ def segment_dict
71
+ @definition.segment_dict
72
+ end
73
+
74
+ # @return [void]
75
+ def pretty_print(q)
76
+ id = @definition.try do |d|
77
+ ansi.bold("[#{d.id.to_s}]")
78
+ end
79
+
80
+ q.text(ansi.envelope("FunctionalGroupVal#{id}"))
81
+ q.group(2, "(", ")") do
82
+ q.breakable ""
83
+ @children.each do |e|
84
+ unless q.current_group.first?
85
+ q.text ", "
86
+ q.breakable
87
+ end
88
+ q.pp e
89
+ end
90
+ end
91
+ end
92
+
93
+ # @return [String]
94
+ def inspect
95
+ ansi.envelope("Group") + "(#{@children.map(&:inspect).join(", ")})"
96
+ end
97
+
98
+ def ==(other)
99
+ eql?(other) or
100
+ (other.definition == @definition or
101
+ other.children == @children)
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ #
7
+ # @see X12-5.pdf 3.2.1 Basic Interchange Service Request
8
+ # @see X222.pdf B.1.1.4.1 Interchange Control Structures
9
+ #
10
+ class InterchangeVal < AbstractVal
11
+ include SegmentValGroup
12
+
13
+ # @return [InterchangeDef]
14
+ attr_reader :definition
15
+
16
+ def_delegators :definition, :descriptor
17
+
18
+ # @return [Array<SegmentVal, FunctionalGroupVal>]
19
+ attr_reader :children
20
+
21
+ def_delegators "@children.head", :position
22
+
23
+ def initialize(definition, children, separators)
24
+ @definition, @children, @separators =
25
+ definition, children, separators
26
+ end
27
+
28
+ # @return [InterchangeVal]
29
+ def copy(changes = {})
30
+ InterchangeVal.new \
31
+ changes.fetch(:definition, @definition),
32
+ changes.fetch(:children, @children),
33
+ changes.fetch(:separators, @separators)
34
+ end
35
+
36
+ # (see AbstractVal#interchange?)
37
+ # @return true
38
+ def interchange?
39
+ true
40
+ end
41
+
42
+ # @return [Module]
43
+ def segment_dict
44
+ @definition.segment_dict
45
+ end
46
+
47
+ # Note these will not contain the element and segment terminator, because
48
+ # those are not values stored as part of the interchange. Those values are
49
+ # stored in the state machine and can be retrieved by calling #separators
50
+ # on StateMachine
51
+ #
52
+ # @return [Reader::Separators]
53
+ def separators
54
+ @separators.merge(definition.separators(@children.find(&:segment?)))
55
+ end
56
+
57
+ # @return [InterchangeVal]
58
+ def replace_separators(replacement)
59
+ whole = separators.merge(replacement)
60
+ head, (isa, *tail) = @children.split_when(&:segment?)
61
+
62
+ # replace ISA11 and ISA16 with given separators
63
+ isa = definition.replace_separators(isa, whole)
64
+
65
+ copy \
66
+ :children => isa.snoc(head) + tail,
67
+ :separators => whole
68
+ end
69
+
70
+ # @return [void]
71
+ def pretty_print(q)
72
+ id = @definition.try do |d|
73
+ ansi.bold("[#{d.id.to_s}]")
74
+ end
75
+
76
+ q.text(ansi.envelope("InterchangeVal#{id}"))
77
+ q.group(2, "(", ")") do
78
+ q.breakable ""
79
+ @children.each do |e|
80
+ unless q.current_group.first?
81
+ q.text ", "
82
+ q.breakable
83
+ end
84
+ q.pp e
85
+ end
86
+ end
87
+ end
88
+
89
+ # @return [String]
90
+ def inspect
91
+ ansi.envelope("Interchange") + "(#{@children.map(&:inspect).join(", ")})"
92
+ end
93
+
94
+ # @return [Boolean]
95
+ def ==(other)
96
+ eql?(other) or
97
+ (other.definition == @definition and
98
+ other.children == @children)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ class InvalidEnvelopeVal < AbstractVal
7
+ # @return [Array<SegmentVal>]
8
+ attr_reader :children
9
+
10
+ def_delegators "@children.head", :descriptor, :position, :reason
11
+
12
+ def initialize(children)
13
+ @children = children
14
+ end
15
+
16
+ # @return [SegmentVal]
17
+ def copy(changes = {})
18
+ InvalidEnvelopeVal.new(changes.fetch(:children, @children))
19
+ end
20
+
21
+ # (see AbstractVal#size)
22
+ def size
23
+ 0
24
+ end
25
+
26
+ # @return false
27
+ def leaf?
28
+ false
29
+ end
30
+
31
+ def valid?
32
+ false
33
+ end
34
+
35
+ # @return [void]
36
+ def pretty_print(q)
37
+ q.text(ansi.segment("InvalidEnvelopeVal"))
38
+ q.group(2, "(", ")") do
39
+ q.breakable ""
40
+ q.text @children.first.reason
41
+ q.text ","
42
+ q.breakable
43
+
44
+ @children.each do |e|
45
+ unless q.current_group.first?
46
+ q.text ","
47
+ q.breakable
48
+ end
49
+ q.pp e
50
+ end
51
+ end
52
+ end
53
+
54
+ # @return [String]
55
+ def inspect
56
+ ansi.invalid("InvalidEnvelopeVal") <<
57
+ "(#{@children.map(&:inspect).join(", ")})"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Values
6
+ class InvalidSegmentVal < AbstractVal
7
+ # @return [String]
8
+ attr_reader :reason
9
+
10
+ # @return [Reader::SegmentTok]
11
+ attr_reader :segment_tok
12
+
13
+ def_delegators :@segment_tok, :position
14
+
15
+ def initialize(reason, segment_tok, separators)
16
+ @reason, @segment_tok, @separators =
17
+ reason, segment_tok, separators
18
+ end
19
+
20
+ # @return [SegmentVal]
21
+ def copy(changes = {})
22
+ InvalidSegmentVal.new \
23
+ changes.fetch(:reason, @reason),
24
+ changes.fetch(:segment_tok, @segment_tok),
25
+ changes.fetch(:separators, @separators)
26
+ end
27
+
28
+ # @return [String]
29
+ def descriptor
30
+ "segment #{@segment_tok.to_x12(@separators)} #{@reason}"
31
+ end
32
+
33
+ # (see AbstractVal#size)
34
+ def size
35
+ 0
36
+ end
37
+
38
+ # @return [Symbol]
39
+ def id
40
+ @segment_tok.id
41
+ end
42
+
43
+ # @return true
44
+ def leaf?
45
+ true
46
+ end
47
+
48
+ def valid?
49
+ false
50
+ end
51
+
52
+ # (see AbstractVal#segment?)
53
+ # @return true
54
+ def segment?
55
+ true
56
+ end
57
+
58
+ def empty?
59
+ true
60
+ end
61
+
62
+ # @return nil
63
+ def usage
64
+ nil
65
+ end
66
+
67
+ # @return nul
68
+ def definition
69
+ nil
70
+ end
71
+
72
+ # @return [void]
73
+ def pretty_print(q)
74
+ id = ansi.invalid("[#{@segment_tok.to_x12(@separators)}]")
75
+ q.text(ansi.segment("InvalidSegmentVal#{id}"))
76
+ end
77
+
78
+ # @return [String]
79
+ def inspect
80
+ ansi.invalid(@segment_tok.id.to_s)
81
+ end
82
+
83
+ # @return [Boolean]
84
+ def ==(other)
85
+ eql?(other)
86
+ end
87
+ end
88
+ end
89
+ end