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,347 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Versions
6
+ module Common
7
+ module ElementTypes
8
+ class TM < SimpleElementDef
9
+ def initialize(id, name, min_length, max_length, description = nil, parent = nil)
10
+ super(id, name, min_length, max_length, description)
11
+
12
+ unless min_length == 2 or min_length == 4 or min_length >= 6
13
+ raise Exceptions::InvalidSchemaError,
14
+ "min_length must be either 2, 4, 6, or greater"
15
+ end
16
+
17
+ unless max_length == 2 or max_length == 4 or max_length >= 6
18
+ raise Exceptions::InvalidSchemaError,
19
+ "max_length must be either 2, 4, 6, or greater"
20
+ end
21
+ end
22
+
23
+ def companion
24
+ TimeVal
25
+ end
26
+ end
27
+
28
+ #
29
+ # @see X222.pdf B.1.1.3.1.6 Time
30
+ #
31
+ class TimeVal < Values::SimpleElementVal
32
+ def time?
33
+ true
34
+ end
35
+
36
+ def too_short?
37
+ false
38
+ end
39
+
40
+ def too_long?
41
+ false
42
+ end
43
+
44
+ class Invalid < TimeVal
45
+ # @return [Object]
46
+ attr_reader :value
47
+
48
+ def initialize(value, usage, position)
49
+ @value = value
50
+ super(usage, position)
51
+ end
52
+
53
+ def valid?
54
+ false
55
+ end
56
+
57
+ def empty?
58
+ false
59
+ end
60
+
61
+ # @return [TimeVal]
62
+ def map
63
+ self
64
+ end
65
+
66
+ # @return [String]
67
+ # :nocov:
68
+ def inspect
69
+ id = definition.bind do |d|
70
+ "[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
71
+ if usage.forbidden?
72
+ ansi.forbidden(s)
73
+ elsif usage.required?
74
+ ansi.required(s)
75
+ else
76
+ ansi.optional(s)
77
+ end
78
+ end
79
+ end
80
+
81
+ ansi.element("TM.invalid#{id}") + "(#{ansi.invalid(@value.inspect)})"
82
+ end
83
+ # :nocov:
84
+
85
+ # @return [String]
86
+ def to_s
87
+ ""
88
+ end
89
+
90
+ # @return [String]
91
+ def to_x12(truncate = true)
92
+ ""
93
+ end
94
+
95
+ # @return [Boolean]
96
+ def ==(other)
97
+ eql?(other)
98
+ end
99
+
100
+ def copy(changes = {})
101
+ self
102
+ end
103
+ end
104
+
105
+ class Valid < TimeVal
106
+ def valid?
107
+ true
108
+ end
109
+
110
+ # @return [TimeVal]
111
+ def map
112
+ TimeVal.value(yield(value), usage, position)
113
+ end
114
+
115
+ def copy(changes = {})
116
+ TimeVal.value \
117
+ changes.fetch(:value, value),
118
+ changes.fetch(:usage, usage),
119
+ changes.fetch(:position, position)
120
+ end
121
+
122
+ def coerce(other)
123
+ return TimeVal.value(other, usage, position), self
124
+ end
125
+
126
+ # @return [Boolean]
127
+ def ==(other)
128
+ other = TimeVal.value(other, usage, position)
129
+ other.valid? and other.value == value
130
+ end
131
+ end
132
+
133
+ class Empty < Valid
134
+ def value
135
+ nil
136
+ end
137
+
138
+ def empty?
139
+ true
140
+ end
141
+
142
+ # @return [String]
143
+ # :nocov:
144
+ def inspect
145
+ id = definition.bind do |d|
146
+ "[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
147
+ if usage.forbidden?
148
+ ansi.forbidden(s)
149
+ elsif usage.required?
150
+ ansi.required(s)
151
+ else
152
+ ansi.optional(s)
153
+ end
154
+ end
155
+ end
156
+
157
+ ansi.element("TM.empty#{id}")
158
+ end
159
+ # :nocov:
160
+
161
+ # @return [String]
162
+ def to_s
163
+ ""
164
+ end
165
+
166
+ # @return [String]
167
+ def to_x12(truncate = true)
168
+ ""
169
+ end
170
+ end
171
+
172
+ class NonEmpty < Valid
173
+ # @return [Integer]
174
+ attr_reader :hour
175
+
176
+ # @return [Integer]
177
+ attr_reader :minute
178
+
179
+ # @return [Integer, BigDecimal]
180
+ attr_reader :second
181
+
182
+ def initialize(hour, minute, second, usage, position)
183
+ @hour, @minute, @second = hour, minute, second
184
+
185
+ valid = ( hour.nil? or hour.between?(0, 24))
186
+ valid &&= (minute.nil? or not hour.nil?)
187
+ valid &&= (minute.nil? or minute.between?(0, 60))
188
+ valid &&= (second.nil? or not minute.nil?)
189
+ valid &&= (second.nil? or second.between?(0, 60))
190
+
191
+ super(usage, position)
192
+
193
+ unless valid
194
+ raise Exceptions::InvalidElementError,
195
+ "invalid time #{inspect}"
196
+ end
197
+ end
198
+
199
+ def copy(changes = {})
200
+ if [:hour, :minute, :second].any?{|x| changes.include?(x) }
201
+ changes[:value] = [changes.fetch(:hour, @hour),
202
+ changes.fetch(:minute, @minute),
203
+ changes.fetch(:second, @second)]
204
+ end
205
+
206
+ super(changes)
207
+ end
208
+
209
+ def value
210
+ [@hour, @minute, @second]
211
+ end
212
+
213
+ def empty?
214
+ false
215
+ end
216
+
217
+ def too_short?
218
+ to_x12(false).length < definition.min_length
219
+ end
220
+
221
+ # @return [Time]
222
+ def to_time(date, minute = nil, second = nil)
223
+ minute = @minute || minute
224
+ second = @second || second
225
+
226
+ if not second.nil?
227
+ Time.utc(date.year, date.month, date.day, @hour, minute, second.to_f)
228
+ elsif not minute.nil?
229
+ Time.utc(date.year, date.month, date.day, @hour, minute)
230
+ else
231
+ Time.utc(date.year, date.month, date.day, @hour)
232
+ end
233
+ end
234
+
235
+ # @return [String]
236
+ # :nocov:
237
+ def inspect
238
+ id = definition.bind do |d|
239
+ "[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
240
+ if usage.forbidden?
241
+ ansi.forbidden(s)
242
+ elsif usage.required?
243
+ ansi.required(s)
244
+ else
245
+ ansi.optional(s)
246
+ end
247
+ end
248
+ end
249
+
250
+ hh = @hour.try{|h| "%02d" % h } || "hh"
251
+ mm = @minute.try{|m| "%02d" % m } || "mm"
252
+ ss = @second.try{|s| s.to_s("F") } || "ss"
253
+ ss = ss.gsub(/^0*\.|\.0*$/, "")
254
+
255
+ ansi.element("TM.value#{id}") + "(#{hh}:#{mm}:#{ss})"
256
+ end
257
+ # :nocov:
258
+
259
+ # @return [String]
260
+ def to_s(hh = "hh", mm = "mm", ss = "ss")
261
+ hh = @hour.try{|h| "%02d" % h } || hh
262
+ mm = @minute.try{|m| "%02d" % m } || mm
263
+ ss = @second.try{|s| "%02f" % s } || ss
264
+ "#{hh}:#{mm}:#{ss}".gsub(/\.?0*$|:$/, "")
265
+ end
266
+
267
+ # @return [String]
268
+ def to_x12(truncate = true)
269
+ hh = @hour.try{|h| "%02d" % h }
270
+ mm = @minute.try{|m| "%02d" % m }
271
+ ss = @second.try{|s| "%02d" % s }
272
+ ff = @second.try{|s| s.frac.to_s("F").gsub(/^0*\.|0+$/, "") }
273
+
274
+ x12 = "#{hh}#{mm}#{ss}#{ff}"
275
+
276
+ truncate ? x12.take(definition.max_length) : x12
277
+ end
278
+ end
279
+ end
280
+
281
+ class << TimeVal
282
+ # @group Constructors
283
+ ###################################################################
284
+
285
+ # @return [TimeVal]
286
+ def empty(usage, position)
287
+ self::Empty.new(usage, position)
288
+ end
289
+
290
+ # @return [TimeVal]
291
+ def value(object, usage, position)
292
+ if object.is_a?(TimeVal)
293
+ object#.copy(:usage => usage, :position => position)
294
+ elsif object.blank?
295
+ self::Empty.new(usage, position)
296
+ elsif object.is_a?(String) or object.is_a?(StringVal)
297
+ return self::Invalid.new(object, usage, position) \
298
+ unless object =~ /^\d{4,}$/
299
+
300
+ hour = object.to_s.slice(0, 2).to_i
301
+ minute = object.to_s.slice(2, 2).try{|mm| mm.to_i unless mm.blank? }
302
+ second = object.to_s.slice(4, 2).try{|ss| ss.to_d unless ss.blank? }
303
+
304
+ if decimal = object.to_s.slice(6..-1)
305
+ decimal = 0 if decimal.empty?
306
+ second += "0.#{decimal}".to_d
307
+ end
308
+
309
+ self::NonEmpty.new(hour, minute, second, usage, position)
310
+ elsif object.respond_to?(:hour) and
311
+ object.respond_to?(:min) and
312
+ object.respond_to?(:sec)
313
+ sec = object.sec.to_d
314
+
315
+ if object.respond_to?(:usec)
316
+ sec += object.usec.to_d / 1000000
317
+ elsif object.respond_to?(:sec_fraction)
318
+ sec += object.sec_fraction.to_d
319
+ end
320
+
321
+ self::NonEmpty.new(object.hour, object.min, sec, usage, position)
322
+ elsif object.respond_to?(:hour) and
323
+ object.respond_to?(:minute) and
324
+ object.respond_to?(:second)
325
+ self::NonEmpty.new(object.hour, object.minute, object.second.to_d, usage, position)
326
+ elsif object.is_a?(Array) and object.length == 3
327
+ self::NonEmpty.new(*object, usage, position)
328
+ else
329
+ self::Invalid.new(object, usage, position)
330
+ end
331
+ rescue Exceptions::InvalidElementError
332
+ self::Invalid.new(object, usage, position)
333
+ end
334
+
335
+ # @endgroup
336
+ ###################################################################
337
+ end
338
+
339
+ # Prevent direct instantiation of abstract class TimeVal
340
+ TimeVal.eigenclass.send(:protected, :new)
341
+ TimeVal::Empty.eigenclass.send(:public, :new)
342
+ TimeVal::Invalid.eigenclass.send(:public, :new)
343
+ TimeVal::NonEmpty.eigenclass.send(:public, :new)
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Versions
4
+ module Common
5
+ module ElementTypes
6
+ autoload :DT, "stupidedi/versions/common/element_types/dt"
7
+ autoload :DateVal, "stupidedi/versions/common/element_types/dt"
8
+
9
+ autoload :R, "stupidedi/versions/common/element_types/r"
10
+ autoload :FloatVal, "stupidedi/versions/common/element_types/r"
11
+
12
+ autoload :ID, "stupidedi/versions/common/element_types/id"
13
+ autoload :IdentifierVal, "stupidedi/versions/common/element_types/id"
14
+
15
+ autoload :Nn, "stupidedi/versions/common/element_types/nn"
16
+ autoload :FixnumVal, "stupidedi/versions/common/element_types/nn"
17
+
18
+ autoload :AN, "stupidedi/versions/common/element_types/an"
19
+ autoload :StringVal, "stupidedi/versions/common/element_types/an"
20
+
21
+ autoload :TM, "stupidedi/versions/common/element_types/tm"
22
+ autoload :TimeVal, "stupidedi/versions/common/element_types/tm"
23
+
24
+ autoload :Operators, "stupidedi/versions/common/element_types/operators"
25
+ autoload :SimpleElementDef, "stupidedi/versions/common/element_types/simple_element"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Versions
4
+ module Common
5
+ #
6
+ # @see X222.pdf A.1.3.9 Condition Designator
7
+ # @see X222.pdf A.1.3.12.6 Data Segment Requirement Designator
8
+ #
9
+ module SegmentReqs
10
+ Mandatory = Schema::SegmentReq.new(true, false, "M")
11
+ Optional = Schema::SegmentReq.new(false, false, "O")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Versions
6
+ module Common
7
+ #
8
+ # @see X222.pdf A.1.3.4 Syntax Notes
9
+ # @see X222.pdf A.1.3.8 Condition Designator
10
+ #
11
+ module SyntaxNotes
12
+ #
13
+ # Paired or Multiple: if any element specified in the relational
14
+ # condition is present, then all of the elements specified must
15
+ # be present.
16
+ #
17
+ class P < Schema::SyntaxNote
18
+ def required(zipper)
19
+ # if zipper.node.present?
20
+ xs = children(zipper)
21
+ xs.any?{|x| x.node.present? } ? xs : []
22
+ # else
23
+ # []
24
+ # end
25
+ end
26
+
27
+ def forbidden(zipper)
28
+ []
29
+ end
30
+
31
+ def reason(zipper)
32
+ present = indexes.select{|n| zipper.child(n - 1).node.present? }
33
+ missing = indexes - present
34
+ "elements #{missing.join(", ")} must be present when elements #{present.join(", ")} are present"
35
+ end
36
+ end
37
+
38
+ #
39
+ # Required: at least one of the elements specified in the condition
40
+ # must be present
41
+ #
42
+ class R < Schema::SyntaxNote
43
+ def required(zipper)
44
+ # if zipper.node.present?
45
+ xs = children(zipper)
46
+ xs.any?{|x| x.node.present? } ? [] : xs
47
+ # else
48
+ # []
49
+ # end
50
+ end
51
+
52
+ def forbidden(zipper)
53
+ []
54
+ end
55
+
56
+ def reason(zipper)
57
+ present = indexes.select{|n| zipper.child(n - 1).node.present? }
58
+ missing = indexes - present
59
+ "at least one of elements #{missing.join(", ")} must be present"
60
+ end
61
+ end
62
+
63
+ #
64
+ # Exclusion: not more than one of the elements in the condition may
65
+ # be present
66
+ #
67
+ class E < Schema::SyntaxNote
68
+ def required(zipper)
69
+ []
70
+ end
71
+
72
+ def forbidden(zipper)
73
+ # if zipper.node.present?
74
+ xs = children(zipper)
75
+ xs.count{|x| x.node.present? } <= 1 ? [] : xs
76
+ # else
77
+ # []
78
+ # end
79
+ end
80
+
81
+ def reason(zipper)
82
+ present = indexes.select{|n| zipper.child(n - 1).node.present? }
83
+ "only one of elements #{present.join(", ")} may be present"
84
+ end
85
+ end
86
+
87
+ #
88
+ # Conditional: if the first element specified in the condition is
89
+ # present, then all other elements must be specified.
90
+ #
91
+ class C < Schema::SyntaxNote
92
+ def required(zipper)
93
+ # if zipper.node.present?
94
+ if zipper.child(indexes.head - 1).node.present?
95
+ children(zipper).tail
96
+ else
97
+ []
98
+ end
99
+ # else
100
+ # []
101
+ # end
102
+ end
103
+
104
+ def forbidden(zipper)
105
+ []
106
+ end
107
+
108
+ def reason(zipper)
109
+ "elements #{indexes.tail.join(", ")} must be present when element #{indexes.head} is present"
110
+ end
111
+ end
112
+
113
+ #
114
+ # List Conditional: if the first element specified in the condition is
115
+ # present, then at least one of the remaining elements must be present
116
+ #
117
+ class L < Schema::SyntaxNote
118
+ def required(zipper)
119
+ # if zipper.node.present?
120
+ if zipper.child(indexes.head - 1).node.present?
121
+ xs = children(zipper).tail
122
+ xs.any?{|x| x.node.present? } ? [] : xs
123
+ else
124
+ []
125
+ end
126
+ # else
127
+ # []
128
+ # end
129
+ end
130
+
131
+ def forbidden(zipper)
132
+ []
133
+ end
134
+
135
+ def reason(zipper)
136
+ "at least one of elements #{indexes.tail.join(", ")} must be present when element #{indexes.head} is present"
137
+ end
138
+ end
139
+
140
+ class << P
141
+ def build(*args)
142
+ new(args)
143
+ end
144
+ end
145
+
146
+ class << R
147
+ def build(*args)
148
+ new(args)
149
+ end
150
+ end
151
+
152
+ class << E
153
+ def build(*args)
154
+ new(args)
155
+ end
156
+ end
157
+
158
+ class << C
159
+ def build(*args)
160
+ new(args)
161
+ end
162
+ end
163
+
164
+ class << L
165
+ def build(*args)
166
+ new(args)
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Versions
4
+ module Common
5
+ autoload :ElementReqs, "stupidedi/versions/common/element_reqs"
6
+ autoload :ElementTypes, "stupidedi/versions/common/element_types"
7
+ autoload :SegmentReqs, "stupidedi/versions/common/segment_reqs"
8
+ autoload :SyntaxNotes, "stupidedi/versions/common/syntax_notes"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Versions
4
+ autoload :Common, "stupidedi/versions/common"
5
+
6
+ # Per-era namespaces that lived under +Stupidedi::Versions+ in the
7
+ # upstream stupidedi gem (plus the two long-deprecated
8
+ # +FunctionalGroups+ / +Interchanges+ aliases). tediparse does not ship
9
+ # them; reach for one by name and we surface a helpful error rather
10
+ # than +NameError+.
11
+ REMOVED_ERAS = %i[
12
+ TwoThousandOne ThirtyTen ThirtyForty ThirtyFifty FortyTen FiftyTen
13
+ FunctionalGroups Interchanges
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