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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +319 -0
- data/LICENSE +26 -0
- data/README.md +308 -0
- data/Rakefile +33 -0
- data/bin/tediparse +102 -0
- data/doc/Defining.md +97 -0
- data/doc/Generating-Grammars.md +241 -0
- data/doc/Generating.md +332 -0
- data/doc/Navigating.md +670 -0
- data/doc/Parsing.md +133 -0
- data/doc/README.md +51 -0
- data/doc/Serializing.md +100 -0
- data/doc/Tokenizing.md +136 -0
- data/doc/Validating.md +140 -0
- data/lib/ruby/array.rb +226 -0
- data/lib/ruby/blank.rb +52 -0
- data/lib/ruby/exception.rb +14 -0
- data/lib/ruby/hash.rb +14 -0
- data/lib/ruby/module.rb +60 -0
- data/lib/ruby/object.rb +56 -0
- data/lib/ruby/string.rb +89 -0
- data/lib/ruby/to_d.rb +82 -0
- data/lib/ruby/to_date.rb +26 -0
- data/lib/ruby/to_time.rb +21 -0
- data/lib/ruby/try.rb +46 -0
- data/lib/stupidedi/builder.rb +6 -0
- data/lib/stupidedi/color.rb +94 -0
- data/lib/stupidedi/config/code_list_config.rb +45 -0
- data/lib/stupidedi/config/functional_group_config.rb +72 -0
- data/lib/stupidedi/config/interchange_config.rb +86 -0
- data/lib/stupidedi/config/transaction_set_config.rb +73 -0
- data/lib/stupidedi/config.rb +100 -0
- data/lib/stupidedi/either.rb +286 -0
- data/lib/stupidedi/exceptions/invalid_element_error.rb +7 -0
- data/lib/stupidedi/exceptions/invalid_schema_error.rb +7 -0
- data/lib/stupidedi/exceptions/missing_grammar_error.rb +50 -0
- data/lib/stupidedi/exceptions/output_error.rb +7 -0
- data/lib/stupidedi/exceptions/parse_error.rb +7 -0
- data/lib/stupidedi/exceptions/stupidedi_error.rb +7 -0
- data/lib/stupidedi/exceptions/tokenize_error.rb +7 -0
- data/lib/stupidedi/exceptions/zipper_error.rb +7 -0
- data/lib/stupidedi/exceptions.rb +13 -0
- data/lib/stupidedi/inspect.rb +26 -0
- data/lib/stupidedi/interchanges/element_types/separator_val.rb +79 -0
- data/lib/stupidedi/interchanges/element_types/special_val.rb +48 -0
- data/lib/stupidedi/interchanges/element_types.rb +11 -0
- data/lib/stupidedi/interchanges.rb +21 -0
- data/lib/stupidedi/parser/builder_dsl.rb +292 -0
- data/lib/stupidedi/parser/constraint_table.rb +566 -0
- data/lib/stupidedi/parser/generation.rb +147 -0
- data/lib/stupidedi/parser/identifier_stack.rb +248 -0
- data/lib/stupidedi/parser/instruction.rb +112 -0
- data/lib/stupidedi/parser/instruction_table.rb +222 -0
- data/lib/stupidedi/parser/navigation.rb +786 -0
- data/lib/stupidedi/parser/state_machine.rb +62 -0
- data/lib/stupidedi/parser/states/abstract_state.rb +385 -0
- data/lib/stupidedi/parser/states/failure_state.rb +69 -0
- data/lib/stupidedi/parser/states/functional_group_state.rb +101 -0
- data/lib/stupidedi/parser/states/initial_state.rb +62 -0
- data/lib/stupidedi/parser/states/interchange_state.rb +96 -0
- data/lib/stupidedi/parser/states/loop_state.rb +74 -0
- data/lib/stupidedi/parser/states/table_state.rb +90 -0
- data/lib/stupidedi/parser/states/transaction_set_state.rb +120 -0
- data/lib/stupidedi/parser/states/transmission_state.rb +59 -0
- data/lib/stupidedi/parser/tokenization.rb +195 -0
- data/lib/stupidedi/parser.rb +32 -0
- data/lib/stupidedi/reader/input/abstract_input.rb +137 -0
- data/lib/stupidedi/reader/input/delegated_input.rb +112 -0
- data/lib/stupidedi/reader/input/file_input.rb +157 -0
- data/lib/stupidedi/reader/input.rb +31 -0
- data/lib/stupidedi/reader/position.rb +78 -0
- data/lib/stupidedi/reader/result.rb +172 -0
- data/lib/stupidedi/reader/segment_dict.rb +176 -0
- data/lib/stupidedi/reader/separators.rb +90 -0
- data/lib/stupidedi/reader/stream_reader.rb +173 -0
- data/lib/stupidedi/reader/token_reader.rb +465 -0
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +71 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +85 -0
- data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +76 -0
- data/lib/stupidedi/reader.rb +121 -0
- data/lib/stupidedi/schema/abstract_def.rb +76 -0
- data/lib/stupidedi/schema/abstract_element_def.rb +35 -0
- data/lib/stupidedi/schema/abstract_element_use.rb +47 -0
- data/lib/stupidedi/schema/abstract_use.rb +79 -0
- data/lib/stupidedi/schema/code_list.rb +99 -0
- data/lib/stupidedi/schema/component_element_use.rb +76 -0
- data/lib/stupidedi/schema/composite_element_def.rb +103 -0
- data/lib/stupidedi/schema/composite_element_use.rb +78 -0
- data/lib/stupidedi/schema/element_req.rb +57 -0
- data/lib/stupidedi/schema/functional_group_def.rb +124 -0
- data/lib/stupidedi/schema/generation/definition_generator.rb +139 -0
- data/lib/stupidedi/schema/generation/element_generator.rb +221 -0
- data/lib/stupidedi/schema/generation/flat_file_reader.rb +551 -0
- data/lib/stupidedi/schema/generation/functional_group_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/interchange_generator.rb +145 -0
- data/lib/stupidedi/schema/generation/master_loader_generator.rb +121 -0
- data/lib/stupidedi/schema/generation/models.rb +85 -0
- data/lib/stupidedi/schema/generation/module_loader_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/registration_generator.rb +230 -0
- data/lib/stupidedi/schema/generation/runner.rb +161 -0
- data/lib/stupidedi/schema/generation/segment_generator.rb +130 -0
- data/lib/stupidedi/schema/generation/support.rb +78 -0
- data/lib/stupidedi/schema/generation/support_modules_generator.rb +126 -0
- data/lib/stupidedi/schema/generation/version_modules.rb +35 -0
- data/lib/stupidedi/schema/generation.rb +94 -0
- data/lib/stupidedi/schema/interchange_def.rb +103 -0
- data/lib/stupidedi/schema/loop_def.rb +156 -0
- data/lib/stupidedi/schema/repeat_count.rb +86 -0
- data/lib/stupidedi/schema/segment_def.rb +122 -0
- data/lib/stupidedi/schema/segment_req.rb +46 -0
- data/lib/stupidedi/schema/segment_use.rb +99 -0
- data/lib/stupidedi/schema/simple_element_def.rb +51 -0
- data/lib/stupidedi/schema/simple_element_use.rb +83 -0
- data/lib/stupidedi/schema/syntax_note.rb +52 -0
- data/lib/stupidedi/schema/table_def.rb +178 -0
- data/lib/stupidedi/schema/transaction_set_def.rb +125 -0
- data/lib/stupidedi/schema.rb +30 -0
- data/lib/stupidedi/sets.rb +42 -0
- data/lib/stupidedi/transaction_sets/builder/dsl.rb +192 -0
- data/lib/stupidedi/transaction_sets/builder.rb +188 -0
- data/lib/stupidedi/transaction_sets/common/implementations/element_reqs.rb +37 -0
- data/lib/stupidedi/transaction_sets/common/implementations/segment_reqs.rb +31 -0
- data/lib/stupidedi/transaction_sets/common/implementations.rb +11 -0
- data/lib/stupidedi/transaction_sets/common.rb +8 -0
- data/lib/stupidedi/transaction_sets/validation/ambiguity.rb +395 -0
- data/lib/stupidedi/transaction_sets/validation/implementation.rb +12 -0
- data/lib/stupidedi/transaction_sets/validation.rb +9 -0
- data/lib/stupidedi/transaction_sets.rb +25 -0
- data/lib/stupidedi/values/abstract_element_val.rb +19 -0
- data/lib/stupidedi/values/abstract_val.rb +133 -0
- data/lib/stupidedi/values/composite_element_val.rb +102 -0
- data/lib/stupidedi/values/functional_group_val.rb +105 -0
- data/lib/stupidedi/values/interchange_val.rb +102 -0
- data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
- data/lib/stupidedi/values/invalid_segment_val.rb +89 -0
- data/lib/stupidedi/values/loop_val.rb +73 -0
- data/lib/stupidedi/values/repeated_element_val.rb +113 -0
- data/lib/stupidedi/values/segment_val.rb +105 -0
- data/lib/stupidedi/values/segment_val_group.rb +20 -0
- data/lib/stupidedi/values/simple_element_val.rb +80 -0
- data/lib/stupidedi/values/table_val.rb +69 -0
- data/lib/stupidedi/values/transaction_set_val.rb +69 -0
- data/lib/stupidedi/values/transmission_val.rb +56 -0
- data/lib/stupidedi/values.rb +22 -0
- data/lib/stupidedi/version.rb +4 -0
- data/lib/stupidedi/versions/common/element_reqs.rb +13 -0
- data/lib/stupidedi/versions/common/element_types/an.rb +386 -0
- data/lib/stupidedi/versions/common/element_types/dt.rb +572 -0
- data/lib/stupidedi/versions/common/element_types/id.rb +304 -0
- data/lib/stupidedi/versions/common/element_types/nn.rb +312 -0
- data/lib/stupidedi/versions/common/element_types/operators.rb +128 -0
- data/lib/stupidedi/versions/common/element_types/r.rb +342 -0
- data/lib/stupidedi/versions/common/element_types/simple_element.rb +73 -0
- data/lib/stupidedi/versions/common/element_types/tm.rb +347 -0
- data/lib/stupidedi/versions/common/element_types.rb +29 -0
- data/lib/stupidedi/versions/common/segment_reqs.rb +15 -0
- data/lib/stupidedi/versions/common/syntax_notes.rb +172 -0
- data/lib/stupidedi/versions/common.rb +11 -0
- data/lib/stupidedi/versions.rb +25 -0
- data/lib/stupidedi/writer/claredi.rb +178 -0
- data/lib/stupidedi/writer/default.rb +119 -0
- data/lib/stupidedi/writer.rb +7 -0
- data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
- data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
- data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
- data/lib/stupidedi/zipper/memoized_cursor.rb +133 -0
- data/lib/stupidedi/zipper/path.rb +132 -0
- data/lib/stupidedi/zipper/root_cursor.rb +120 -0
- data/lib/stupidedi/zipper/stack_cursor.rb +107 -0
- data/lib/stupidedi/zipper.rb +45 -0
- data/lib/stupidedi.rb +69 -0
- data/lib/tediparse.rb +1 -0
- metadata +249 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
class Either
|
|
6
|
+
# @return [Boolean]
|
|
7
|
+
abstract :defined?
|
|
8
|
+
|
|
9
|
+
###########################################################################
|
|
10
|
+
# @group Filtering the Value
|
|
11
|
+
|
|
12
|
+
# @return [Either]
|
|
13
|
+
abstract :select, :args => %w(reason='select' &block)
|
|
14
|
+
|
|
15
|
+
# @return [Either]
|
|
16
|
+
abstract :reject, :args => %w(reason='reject' &block)
|
|
17
|
+
|
|
18
|
+
# @endgroup
|
|
19
|
+
###########################################################################
|
|
20
|
+
|
|
21
|
+
###########################################################################
|
|
22
|
+
# @group Transforming the Value
|
|
23
|
+
|
|
24
|
+
# @return [Either]
|
|
25
|
+
abstract :map, :args => %w(&block)
|
|
26
|
+
|
|
27
|
+
# @return [Either]
|
|
28
|
+
abstract :flatmap, :args => %w(&block)
|
|
29
|
+
|
|
30
|
+
# @return [Either]
|
|
31
|
+
abstract :or, :args => %w(&block)
|
|
32
|
+
|
|
33
|
+
# @return [Either]
|
|
34
|
+
abstract :explain, :args => %w(&block)
|
|
35
|
+
|
|
36
|
+
# @return [Object]
|
|
37
|
+
abstract :fetch, :args => %w(default)
|
|
38
|
+
|
|
39
|
+
# @endgroup
|
|
40
|
+
###########################################################################
|
|
41
|
+
|
|
42
|
+
class Success < Either
|
|
43
|
+
def initialize(value)
|
|
44
|
+
@value = value
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def copy(changes = {})
|
|
48
|
+
Success.new \
|
|
49
|
+
changes.fetch(:value, @value)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return true
|
|
53
|
+
def defined?
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def fetch(default = nil)
|
|
58
|
+
@value
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
#########################################################################
|
|
62
|
+
# @group Filtering the Value
|
|
63
|
+
|
|
64
|
+
# @return [Either]
|
|
65
|
+
# @yieldparam value
|
|
66
|
+
# @yieldreturn [Boolean]
|
|
67
|
+
def select(reason = "select", &block)
|
|
68
|
+
if deconstruct(block)
|
|
69
|
+
self
|
|
70
|
+
else
|
|
71
|
+
failure(reason)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @return [Either]
|
|
76
|
+
# @yieldparam value
|
|
77
|
+
# @yieldreturn [Boolean]
|
|
78
|
+
def reject(reason = "reject", &block)
|
|
79
|
+
if deconstruct(block)
|
|
80
|
+
failure(reason)
|
|
81
|
+
else
|
|
82
|
+
self
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @endgroup
|
|
87
|
+
#########################################################################
|
|
88
|
+
|
|
89
|
+
#########################################################################
|
|
90
|
+
# @group Transforming the Value
|
|
91
|
+
|
|
92
|
+
# @return [Success]
|
|
93
|
+
# @yieldparam value
|
|
94
|
+
# @yieldreturn value
|
|
95
|
+
def map(&block)
|
|
96
|
+
copy(:value => deconstruct(block))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @return [Either]
|
|
100
|
+
# @yieldparam value
|
|
101
|
+
# @yieldreturn [Either]
|
|
102
|
+
def flatmap(&block)
|
|
103
|
+
result = deconstruct(block)
|
|
104
|
+
|
|
105
|
+
if result.is_a?(Either)
|
|
106
|
+
result
|
|
107
|
+
else
|
|
108
|
+
raise TypeError, "block did not return an instance of Either"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @return [Success]
|
|
113
|
+
def or
|
|
114
|
+
self
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @return [Success]
|
|
118
|
+
def explain
|
|
119
|
+
self
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @endgroup
|
|
123
|
+
#########################################################################
|
|
124
|
+
|
|
125
|
+
def tap(&block)
|
|
126
|
+
deconstruct(block); self
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @return [Boolean]
|
|
130
|
+
def ==(other)
|
|
131
|
+
other.is_a?(self.class) and other.select{|x| x == @value }.defined?
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @return [void]
|
|
135
|
+
def pretty_print(q)
|
|
136
|
+
q.text("Either.success")
|
|
137
|
+
q.group(2, "(", ")") do
|
|
138
|
+
q.breakable ""
|
|
139
|
+
q.pp @value
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @return [String]
|
|
144
|
+
def inspect
|
|
145
|
+
"Either.success(#{@value.inspect})"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def deconstruct(block)
|
|
151
|
+
block.call(@value)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def failure(reason)
|
|
155
|
+
Either::Failure.new(reason)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
class Failure < Either
|
|
160
|
+
attr_reader :reason
|
|
161
|
+
|
|
162
|
+
def initialize(reason)
|
|
163
|
+
@reason = reason
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @return [Failure]
|
|
167
|
+
def copy(changes = {})
|
|
168
|
+
Failure.new \
|
|
169
|
+
changes.fetch(:reason, @reason)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# @return false
|
|
173
|
+
def defined?
|
|
174
|
+
false
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def fetch(default = nil)
|
|
178
|
+
default
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
#########################################################################
|
|
182
|
+
# @group Filtering the Value
|
|
183
|
+
|
|
184
|
+
# @return [Failure]
|
|
185
|
+
def select(reason = nil)
|
|
186
|
+
self
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# @return [Failure]
|
|
190
|
+
def reject(reason = nil)
|
|
191
|
+
self
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# @endgroup
|
|
195
|
+
#########################################################################
|
|
196
|
+
|
|
197
|
+
#########################################################################
|
|
198
|
+
# @group Transforming the Value
|
|
199
|
+
|
|
200
|
+
# @return [Failure]
|
|
201
|
+
def map
|
|
202
|
+
self
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# @return [Failure]
|
|
206
|
+
def flatmap
|
|
207
|
+
self
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# @return [Either]
|
|
211
|
+
# @yieldparam reason
|
|
212
|
+
# @yieldreturn [Either]
|
|
213
|
+
def or(&block)
|
|
214
|
+
result = deconstruct(block)
|
|
215
|
+
|
|
216
|
+
if result.is_a?(Either)
|
|
217
|
+
result
|
|
218
|
+
else
|
|
219
|
+
raise TypeError, "block did not return an instance of Either"
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# @return [Failure]
|
|
224
|
+
# @yieldparam reason
|
|
225
|
+
# @yieldreturn reason
|
|
226
|
+
def explain(&block)
|
|
227
|
+
copy(:reason => deconstruct(block))
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# @endgroup
|
|
231
|
+
#########################################################################
|
|
232
|
+
|
|
233
|
+
def tap
|
|
234
|
+
self
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# @return [Boolean]
|
|
238
|
+
def ==(other)
|
|
239
|
+
other.is_a?(self.class) and other.reason == @reason
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# @return [void]
|
|
243
|
+
def pretty_print(q)
|
|
244
|
+
q.text("Either.failure")
|
|
245
|
+
q.group(2, "(", ")") do
|
|
246
|
+
q.breakable ""
|
|
247
|
+
q.pp @reason
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# @return [String]
|
|
252
|
+
def inspect
|
|
253
|
+
"Either.failure(#{@reason.inspect})"
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
private
|
|
257
|
+
|
|
258
|
+
def deconstruct(block)
|
|
259
|
+
block.call(@reason)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
class << Either
|
|
265
|
+
###########################################################################
|
|
266
|
+
# @group Constructors
|
|
267
|
+
|
|
268
|
+
# @return [Success]
|
|
269
|
+
def success(value)
|
|
270
|
+
Either::Success.new(value)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# @return [Failure]
|
|
274
|
+
def failure(reason)
|
|
275
|
+
Either::Failure.new(reason)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# @endgroup
|
|
279
|
+
###########################################################################
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
Either.eigenclass.send(:protected, :new)
|
|
283
|
+
Either::Success.eigenclass.send(:public, :new)
|
|
284
|
+
Either::Failure.eigenclass.send(:public, :new)
|
|
285
|
+
|
|
286
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Exceptions
|
|
4
|
+
#
|
|
5
|
+
# Raised when application code reaches for a grammar that tediparse does
|
|
6
|
+
# not ship. tediparse is the parser/writer engine only; transaction-set
|
|
7
|
+
# grammars, code lists, and implementation guides are not bundled (they
|
|
8
|
+
# are X12 IP). Users must register their own grammar against
|
|
9
|
+
# +Stupidedi::Config+ before parsing.
|
|
10
|
+
#
|
|
11
|
+
# Three places raise this:
|
|
12
|
+
#
|
|
13
|
+
# 1. +Stupidedi::Interchanges.const_missing+,
|
|
14
|
+
# +Stupidedi::Versions.const_missing+, and
|
|
15
|
+
# +Stupidedi::TransactionSets.const_missing+ raise it when application
|
|
16
|
+
# code references a per-era constant by name
|
|
17
|
+
# (e.g. +Stupidedi::Versions::FiftyTen+).
|
|
18
|
+
#
|
|
19
|
+
# 2. The three envelope parser states (+InterchangeState+,
|
|
20
|
+
# +FunctionalGroupState+, +TransactionSetState+) surface this message
|
|
21
|
+
# as the +reason+ on +InvalidSegmentVal+ when the relevant config
|
|
22
|
+
# sub-registry is empty. The parser itself does not raise — it
|
|
23
|
+
# produces a +FailureState+ — but the message is the same so users
|
|
24
|
+
# see one consistent UX whether they hit a bare +const_missing+ or a
|
|
25
|
+
# parse failure.
|
|
26
|
+
#
|
|
27
|
+
class MissingGrammarError < StupidediError
|
|
28
|
+
DEFAULT_MESSAGE =
|
|
29
|
+
"tediparse does not ship with X12 grammars or transaction-set " \
|
|
30
|
+
"definitions. Register your own grammar against Stupidedi::Config " \
|
|
31
|
+
"before parsing — see the README for an authoring example."
|
|
32
|
+
|
|
33
|
+
# @param context [String, nil]
|
|
34
|
+
# When given, appended to the default message as " (while resolving
|
|
35
|
+
# <context>)". Used by the +const_missing+ hooks to name the
|
|
36
|
+
# per-era constant the caller reached for; left nil at parser-state
|
|
37
|
+
# callsites where no constant name is in play.
|
|
38
|
+
def initialize(context = nil)
|
|
39
|
+
message =
|
|
40
|
+
if context
|
|
41
|
+
"#{DEFAULT_MESSAGE} (while resolving #{context})"
|
|
42
|
+
else
|
|
43
|
+
DEFAULT_MESSAGE
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
super(message)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Exceptions
|
|
4
|
+
autoload :StupidediError, "stupidedi/exceptions/stupidedi_error"
|
|
5
|
+
autoload :InvalidElementError, "stupidedi/exceptions/invalid_element_error"
|
|
6
|
+
autoload :InvalidSchemaError, "stupidedi/exceptions/invalid_schema_error"
|
|
7
|
+
autoload :MissingGrammarError, "stupidedi/exceptions/missing_grammar_error"
|
|
8
|
+
autoload :OutputError, "stupidedi/exceptions/output_error"
|
|
9
|
+
autoload :ParseError, "stupidedi/exceptions/parse_error"
|
|
10
|
+
autoload :TokenizeError, "stupidedi/exceptions/tokenize_error"
|
|
11
|
+
autoload :ZipperError, "stupidedi/exceptions/zipper_error"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# When an exception is raised, in some cases `#inspect` is called on a
|
|
7
|
+
# huge object graph to generate the message `"undefined method '...' for
|
|
8
|
+
# <Stupidedi::Schema::TransactionSetDef:0x...>"`. This can take several
|
|
9
|
+
# seconds, since `Object#inspect` descends recursively into each instance
|
|
10
|
+
# variable.
|
|
11
|
+
#
|
|
12
|
+
# This mixin defines an alternative default implementation for `#inspect`,
|
|
13
|
+
# which should be significantly faster than the default Ruby implementation
|
|
14
|
+
# since it does not descend into the object.
|
|
15
|
+
#
|
|
16
|
+
module Inspect
|
|
17
|
+
# @return [String]
|
|
18
|
+
def inspect
|
|
19
|
+
if self.class.name.nil? or self.class.name !~ /\S/
|
|
20
|
+
"#<\#<Class:0x#{self.class.object_id.abs.to_s(16)}>"
|
|
21
|
+
else
|
|
22
|
+
"#<#{self.class.name}"
|
|
23
|
+
end + ":0x#{object_id.abs.to_s(16)} ...>"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
module Interchanges
|
|
6
|
+
module ElementTypes
|
|
7
|
+
class Separator < Versions::Common::ElementTypes::AN
|
|
8
|
+
def companion
|
|
9
|
+
SeparatorVal
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class SeparatorVal < Values::SimpleElementVal
|
|
14
|
+
def_delegators :@value, :to_s, :length, :==
|
|
15
|
+
|
|
16
|
+
def initialize(value, usage, position)
|
|
17
|
+
@value = value
|
|
18
|
+
super(usage, position)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [SeparatorVal]
|
|
22
|
+
def copy(changes = {})
|
|
23
|
+
SeparatorVal.new \
|
|
24
|
+
changes.fetch(:value, @value),
|
|
25
|
+
changes.fetch(:usage, usage),
|
|
26
|
+
changes.fetch(:position, position)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def valid?
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def empty?
|
|
34
|
+
@value.blank?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def too_short?
|
|
38
|
+
@value.length < 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def too_long?
|
|
42
|
+
@value.length > 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def separator?
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [String]
|
|
50
|
+
def to_x12(truncate = true)
|
|
51
|
+
@value.to_s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def inspect
|
|
55
|
+
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
|
56
|
+
ansi.element("SeparatorVal.value#{id}") + "(#{@value || "nil"})"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class << SeparatorVal
|
|
61
|
+
# @group Constructors
|
|
62
|
+
###################################################################
|
|
63
|
+
|
|
64
|
+
# @raise NoMethodError
|
|
65
|
+
def empty(usage, position)
|
|
66
|
+
SeparatorVal.new(nil, usage, position)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @return [SeparatorVal]
|
|
70
|
+
def value(character, usage, position)
|
|
71
|
+
SeparatorVal.new(character, usage, position)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @endgroup
|
|
75
|
+
###################################################################
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
module Interchanges
|
|
6
|
+
module ElementTypes
|
|
7
|
+
AN = Versions::Common::ElementTypes::AN
|
|
8
|
+
StringVal = Versions::Common::ElementTypes::StringVal
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# The specifications declare ISA02 and ISA04 are required elements, but
|
|
12
|
+
# they only have "meaningful information" when ISA01 and ISA03 qualifiers
|
|
13
|
+
# aren't "00".
|
|
14
|
+
#
|
|
15
|
+
# Without specifications regarding what should be entered in these
|
|
16
|
+
# required elements, our best option is to defer to convention, which
|
|
17
|
+
# seems to be that these elements should have 10 spaces -- which means
|
|
18
|
+
# they're blank. So we can't really make these elements required! Even
|
|
19
|
+
# stupider, these are the only blank elements that should be written out
|
|
20
|
+
# space-padded to the min_length -- every other element should be
|
|
21
|
+
# collapsed to an empty string.
|
|
22
|
+
#
|
|
23
|
+
# So this "Special" class overrides to_x12 for empty values, but it
|
|
24
|
+
# otherwise looks and acts like a normal AN and StringVal
|
|
25
|
+
#
|
|
26
|
+
class SpecialAN < AN
|
|
27
|
+
def companion
|
|
28
|
+
SpecialVal
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class SpecialVal < StringVal
|
|
33
|
+
class Empty < StringVal::Empty
|
|
34
|
+
# @return [String]
|
|
35
|
+
def to_x12
|
|
36
|
+
" " * definition.min_length
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class NonEmpty < StringVal::NonEmpty
|
|
41
|
+
def too_short?
|
|
42
|
+
false
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Interchanges
|
|
4
|
+
module ElementTypes
|
|
5
|
+
autoload :SpecialAN, "stupidedi/interchanges/element_types/special_val"
|
|
6
|
+
autoload :SpecialVal, "stupidedi/interchanges/element_types/special_val"
|
|
7
|
+
autoload :Separator, "stupidedi/interchanges/element_types/separator_val"
|
|
8
|
+
autoload :SeparatorVal, "stupidedi/interchanges/element_types/separator_val"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Interchanges
|
|
4
|
+
autoload :ElementTypes, "stupidedi/interchanges/element_types"
|
|
5
|
+
|
|
6
|
+
# Per-era envelope namespaces that lived under +Stupidedi::Interchanges+
|
|
7
|
+
# in the upstream stupidedi gem. tediparse does not ship them; if user
|
|
8
|
+
# code references one by name we surface a helpful error rather than the
|
|
9
|
+
# bare +NameError+ Ruby would raise for an undefined constant.
|
|
10
|
+
REMOVED_ERAS = %i[TwoHundred ThreeHundred FourHundred FourOhOne FiveOhOne].freeze
|
|
11
|
+
private_constant :REMOVED_ERAS
|
|
12
|
+
|
|
13
|
+
def self.const_missing(name)
|
|
14
|
+
if REMOVED_ERAS.include?(name.to_sym)
|
|
15
|
+
raise Stupidedi::Exceptions::MissingGrammarError.new("#{self}::#{name}")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|