stupidedi 1.1.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.
- data/README.md +215 -0
- data/Rakefile +108 -0
- data/bin/edi-ed +71 -0
- data/bin/edi-pp +81 -0
- data/doc/Defining.md +0 -0
- data/doc/Generating.md +321 -0
- data/doc/LICENSE.md +0 -0
- data/doc/Navigating.md +645 -0
- data/doc/Parsing.md +0 -0
- data/doc/Serializing.md +7 -0
- data/doc/Tokenizing.md +0 -0
- data/doc/Validating.md +0 -0
- data/doc/design/Parser.md +0 -0
- data/doc/design/Reader.md +0 -0
- data/lib/ruby/array.rb +164 -0
- data/lib/ruby/blank.rb +67 -0
- data/lib/ruby/enumerable.rb +35 -0
- data/lib/ruby/exception.rb +33 -0
- data/lib/ruby/hash.rb +4 -0
- data/lib/ruby/instance_exec.rb +26 -0
- data/lib/ruby/module.rb +79 -0
- data/lib/ruby/object.rb +63 -0
- data/lib/ruby/string.rb +73 -0
- data/lib/ruby/symbol.rb +24 -0
- data/lib/ruby/to_d.rb +81 -0
- data/lib/ruby/to_date.rb +33 -0
- data/lib/ruby/to_time.rb +24 -0
- data/lib/ruby/try.rb +43 -0
- data/lib/stupidedi/blank_slate.rb +11 -0
- data/lib/stupidedi/builder/builder_dsl.rb +281 -0
- data/lib/stupidedi/builder/constraint_table.rb +418 -0
- data/lib/stupidedi/builder/generation.rb +112 -0
- data/lib/stupidedi/builder/instruction.rb +102 -0
- data/lib/stupidedi/builder/instruction_table.rb +204 -0
- data/lib/stupidedi/builder/navigation.rb +655 -0
- data/lib/stupidedi/builder/state_machine.rb +55 -0
- data/lib/stupidedi/builder/states/abstract_state.rb +332 -0
- data/lib/stupidedi/builder/states/failure_state.rb +69 -0
- data/lib/stupidedi/builder/states/functional_group_state.rb +97 -0
- data/lib/stupidedi/builder/states/initial_state.rb +63 -0
- data/lib/stupidedi/builder/states/interchange_state.rb +94 -0
- data/lib/stupidedi/builder/states/loop_state.rb +79 -0
- data/lib/stupidedi/builder/states/table_state.rb +96 -0
- data/lib/stupidedi/builder/states/transaction_set_state.rb +112 -0
- data/lib/stupidedi/builder/states/transmission_state.rb +59 -0
- data/lib/stupidedi/builder/tokenization.rb +196 -0
- data/lib/stupidedi/builder.rb +23 -0
- data/lib/stupidedi/color.rb +93 -0
- data/lib/stupidedi/config/code_list_config.rb +42 -0
- data/lib/stupidedi/config/editor_config.rb +51 -0
- data/lib/stupidedi/config/functional_group_config.rb +62 -0
- data/lib/stupidedi/config/interchange_config.rb +79 -0
- data/lib/stupidedi/config/transaction_set_config.rb +91 -0
- data/lib/stupidedi/config.rb +101 -0
- data/lib/stupidedi/editor/00501.rb +341 -0
- data/lib/stupidedi/editor/005010/N2.rb +0 -0
- data/lib/stupidedi/editor/005010/N3.rb +0 -0
- data/lib/stupidedi/editor/005010/N4.rb +63 -0
- data/lib/stupidedi/editor/005010/NM1.rb +0 -0
- data/lib/stupidedi/editor/005010.rb +469 -0
- data/lib/stupidedi/editor/X222-HC837.rb +195 -0
- data/lib/stupidedi/editor/abstract_ed.rb +36 -0
- data/lib/stupidedi/editor/claim_ack.rb +9 -0
- data/lib/stupidedi/editor/implementation_ack.rb +213 -0
- data/lib/stupidedi/editor/interchange_ack.rb +9 -0
- data/lib/stupidedi/editor/result.rb +100 -0
- data/lib/stupidedi/editor/result_set.rb +69 -0
- data/lib/stupidedi/editor/transaction_set_ed.rb +275 -0
- data/lib/stupidedi/editor/transmission_ed.rb +90 -0
- data/lib/stupidedi/editor.rb +37 -0
- data/lib/stupidedi/either.rb +287 -0
- data/lib/stupidedi/exceptions/invalid_element_error.rb +8 -0
- data/lib/stupidedi/exceptions/invalid_schema_error.rb +8 -0
- data/lib/stupidedi/exceptions/output_error.rb +8 -0
- data/lib/stupidedi/exceptions/parse_error.rb +8 -0
- data/lib/stupidedi/exceptions/stupidedi_error.rb +8 -0
- data/lib/stupidedi/exceptions/tokenize_error.rb +8 -0
- data/lib/stupidedi/exceptions/zipper_error.rb +8 -0
- data/lib/stupidedi/exceptions.rb +11 -0
- data/lib/stupidedi/guides/005010/X214-HN277.rb +409 -0
- data/lib/stupidedi/guides/005010/X221-HP835.rb +613 -0
- data/lib/stupidedi/guides/005010/X221A1-HP835.rb +613 -0
- data/lib/stupidedi/guides/005010/X222-HC837P.rb +2291 -0
- data/lib/stupidedi/guides/005010/X222A1-HC837P.rb +2297 -0
- data/lib/stupidedi/guides/005010/X231-FA999.rb +123 -0
- data/lib/stupidedi/guides/005010/X231A1-FA999.rb +119 -0
- data/lib/stupidedi/guides/005010/element_reqs.rb +38 -0
- data/lib/stupidedi/guides/005010/guide_builder.rb +180 -0
- data/lib/stupidedi/guides/005010/segment_reqs.rb +32 -0
- data/lib/stupidedi/guides/005010.rb +64 -0
- data/lib/stupidedi/guides.rb +5 -0
- data/lib/stupidedi/inspect.rb +26 -0
- data/lib/stupidedi/reader/input/abstract_input.rb +133 -0
- data/lib/stupidedi/reader/input/delegated_input.rb +111 -0
- data/lib/stupidedi/reader/input/file_input.rb +155 -0
- data/lib/stupidedi/reader/input.rb +30 -0
- data/lib/stupidedi/reader/position.rb +69 -0
- data/lib/stupidedi/reader/result.rb +168 -0
- data/lib/stupidedi/reader/segment_dict.rb +175 -0
- data/lib/stupidedi/reader/separators.rb +85 -0
- data/lib/stupidedi/reader/stream_reader.rb +172 -0
- data/lib/stupidedi/reader/token_reader.rb +466 -0
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +56 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +64 -0
- data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +64 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +51 -0
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +63 -0
- data/lib/stupidedi/reader.rb +121 -0
- data/lib/stupidedi/schema/abstract_def.rb +74 -0
- data/lib/stupidedi/schema/abstract_use.rb +73 -0
- data/lib/stupidedi/schema/code_list.rb +94 -0
- data/lib/stupidedi/schema/element_def.rb +173 -0
- data/lib/stupidedi/schema/element_req.rb +56 -0
- data/lib/stupidedi/schema/element_use.rb +251 -0
- data/lib/stupidedi/schema/functional_group_def.rb +114 -0
- data/lib/stupidedi/schema/interchange_def.rb +93 -0
- data/lib/stupidedi/schema/loop_def.rb +152 -0
- data/lib/stupidedi/schema/repeat_count.rb +85 -0
- data/lib/stupidedi/schema/segment_def.rb +108 -0
- data/lib/stupidedi/schema/segment_req.rb +43 -0
- data/lib/stupidedi/schema/segment_use.rb +98 -0
- data/lib/stupidedi/schema/syntax_note.rb +63 -0
- data/lib/stupidedi/schema/table_def.rb +139 -0
- data/lib/stupidedi/schema/transaction_set_def.rb +88 -0
- data/lib/stupidedi/schema.rb +28 -0
- data/lib/stupidedi/sets/absolute_set.rb +297 -0
- data/lib/stupidedi/sets/abstract_set.rb +174 -0
- data/lib/stupidedi/sets/null_set.rb +125 -0
- data/lib/stupidedi/sets/relative_complement.rb +137 -0
- data/lib/stupidedi/sets/relative_set.rb +269 -0
- data/lib/stupidedi/sets/universal_set.rb +104 -0
- data/lib/stupidedi/sets.rb +57 -0
- data/lib/stupidedi/tail_call.rb +109 -0
- data/lib/stupidedi/thread_local.rb +174 -0
- data/lib/stupidedi/values/abstract_element_val.rb +19 -0
- data/lib/stupidedi/values/abstract_val.rb +130 -0
- data/lib/stupidedi/values/composite_element_val.rb +95 -0
- data/lib/stupidedi/values/functional_group_val.rb +102 -0
- data/lib/stupidedi/values/interchange_val.rb +86 -0
- data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
- data/lib/stupidedi/values/invalid_segment_val.rb +78 -0
- data/lib/stupidedi/values/loop_val.rb +70 -0
- data/lib/stupidedi/values/repeated_element_val.rb +105 -0
- data/lib/stupidedi/values/segment_val.rb +104 -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 +66 -0
- data/lib/stupidedi/values/transaction_set_val.rb +66 -0
- data/lib/stupidedi/values/transmission_val.rb +52 -0
- data/lib/stupidedi/values.rb +21 -0
- data/lib/stupidedi/version.rb +3 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +54 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_reqs.rb +18 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +527 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +335 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +299 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/identifier_val.rb +287 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +338 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +309 -0
- data/lib/stupidedi/versions/functional_groups/004010/element_types.rb +124 -0
- data/lib/stupidedi/versions/functional_groups/004010/functional_group_def.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GE.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GS.rb +27 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_defs/SE.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_defs/ST.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_defs.rb +23 -0
- data/lib/stupidedi/versions/functional_groups/004010/segment_reqs.rb +18 -0
- data/lib/stupidedi/versions/functional_groups/004010/syntax_notes.rb +174 -0
- data/lib/stupidedi/versions/functional_groups/004010.rb +38 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_defs.rb +1405 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_reqs.rb +18 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +577 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +322 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +354 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/identifier_val.rb +368 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/operators.rb +117 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +398 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +327 -0
- data/lib/stupidedi/versions/functional_groups/005010/element_types.rb +132 -0
- data/lib/stupidedi/versions/functional_groups/005010/functional_group_def.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK1.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK2.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK9.rb +28 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AMT.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BHT.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BPR.rb +49 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CAS.rb +56 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CL1.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLM.rb +41 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLP.rb +34 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CN1.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR1.rb +32 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR2.rb +35 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR3.rb +25 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CRC.rb +26 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTP.rb +36 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTX.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CUR.rb +57 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DMG.rb +34 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN1.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN2.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTM.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTP.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/FRM.rb +25 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GE.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GS.rb +27 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HCP.rb +39 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HI.rb +31 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HL.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK3.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK4.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK5.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/K3.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LIN.rb +69 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LQ.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LX.rb +19 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MEA.rb +39 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MIA.rb +45 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MOA.rb +28 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N1.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N2.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N3.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N4.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NM1.rb +35 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NTE.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/OI.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PAT.rb +31 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PER.rb +32 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PLB.rb +40 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PRV.rb +26 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PS1.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PWK.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/QTY.rb +25 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/RDM.rb +23 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/REF.rb +23 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SBR.rb +28 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SE.rb +20 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/ST.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/STC.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV1.rb +44 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV2.rb +29 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV3.rb +30 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV5.rb +29 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVC.rb +26 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVD.rb +24 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TOO.rb +21 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TRN.rb +22 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS2.rb +40 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS3.rb +45 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_defs.rb +227 -0
- data/lib/stupidedi/versions/functional_groups/005010/segment_reqs.rb +18 -0
- data/lib/stupidedi/versions/functional_groups/005010/syntax_notes.rb +165 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/FA999.rb +38 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HB271.rb +85 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HC837.rb +163 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HI278.rb +64 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HN277.rb +74 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HP835.rb +68 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HR276.rb +57 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HS270.rb +53 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/RA820.rb +240 -0
- data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs.rb +68 -0
- data/lib/stupidedi/versions/functional_groups/005010.rb +38 -0
- data/lib/stupidedi/versions/functional_groups.rb +8 -0
- data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +224 -0
- data/lib/stupidedi/versions/interchanges/00401/interchange_def.rb +45 -0
- data/lib/stupidedi/versions/interchanges/00401/segment_defs/IEA.rb +20 -0
- data/lib/stupidedi/versions/interchanges/00401/segment_defs/ISA.rb +34 -0
- data/lib/stupidedi/versions/interchanges/00401/segment_defs/TA1.rb +23 -0
- data/lib/stupidedi/versions/interchanges/00401/segment_defs.rb +28 -0
- data/lib/stupidedi/versions/interchanges/00401.rb +23 -0
- data/lib/stupidedi/versions/interchanges/00501/element_defs.rb +269 -0
- data/lib/stupidedi/versions/interchanges/00501/interchange_def.rb +47 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/IEA.rb +20 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISA.rb +34 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISB.rb +18 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISE.rb +18 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA1.rb +23 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA3.rb +18 -0
- data/lib/stupidedi/versions/interchanges/00501/segment_defs.rb +37 -0
- data/lib/stupidedi/versions/interchanges/00501.rb +23 -0
- data/lib/stupidedi/versions/interchanges.rb +8 -0
- data/lib/stupidedi/versions.rb +6 -0
- data/lib/stupidedi/writer/claredi.rb +142 -0
- data/lib/stupidedi/writer/default.rb +124 -0
- data/lib/stupidedi/writer.rb +6 -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 +131 -0
- data/lib/stupidedi/zipper/path.rb +124 -0
- data/lib/stupidedi/zipper/root_cursor.rb +120 -0
- data/lib/stupidedi/zipper.rb +25 -0
- data/lib/stupidedi.rb +66 -0
- data/spec/examples/integration/generating.example +551 -0
- data/spec/examples/integration/navigating.example +214 -0
- data/spec/examples/integration/parsing.example +445 -0
- data/spec/examples/ruby/array.example +476 -0
- data/spec/examples/ruby/blank.example +62 -0
- data/spec/examples/ruby/count.example +68 -0
- data/spec/examples/ruby/object.example +99 -0
- data/spec/examples/ruby/string.example +111 -0
- data/spec/examples/ruby/symbol.example +117 -0
- data/spec/examples/ruby/to_d.example +90 -0
- data/spec/examples/ruby/try.example +50 -0
- data/spec/examples/stupidedi/either.example +375 -0
- data/spec/examples/stupidedi/reader/failure.example +68 -0
- data/spec/examples/stupidedi/reader/input/delegated_input.example +292 -0
- data/spec/examples/stupidedi/reader/separators.example +73 -0
- data/spec/examples/stupidedi/reader/stream_reader.example +48 -0
- data/spec/examples/stupidedi/reader/success.example +34 -0
- data/spec/examples/stupidedi/reader/token_reader.example +775 -0
- data/spec/examples/stupidedi/reader.example +168 -0
- data/spec/examples/stupidedi/sets/absolute_set.example +1577 -0
- data/spec/examples/stupidedi/sets/null_set.example +2 -0
- data/spec/examples/stupidedi/sets/relative_set.example +2 -0
- data/spec/examples/stupidedi/sets/universal_set.example +1 -0
- data/spec/examples/stupidedi/versions/005010/element_types/an.example +201 -0
- data/spec/examples/stupidedi/versions/005010/element_types/dt.example +258 -0
- data/spec/examples/stupidedi/versions/005010/element_types/id.example +192 -0
- data/spec/examples/stupidedi/versions/005010/element_types/nn.example +177 -0
- data/spec/examples/stupidedi/versions/005010/element_types/r.example +178 -0
- data/spec/examples/stupidedi/versions/005010/element_types/tm.example +2 -0
- data/spec/examples/stupidedi/zipper/abstract_cursor.example +417 -0
- data/spec/examples/stupidedi/zipper.example +9 -0
- data/spec/fixtures/X186-AG824/1-bad.txt +21 -0
- data/spec/fixtures/X186-AG824/1-good.txt +17 -0
- data/spec/fixtures/X186-AG824/2-bad.txt +26 -0
- data/spec/fixtures/X186-AG824/2-good.txt +21 -0
- data/spec/fixtures/X186-AG824/3-bad.txt +87 -0
- data/spec/fixtures/X186-AG824/3-good.txt +61 -0
- data/spec/fixtures/X212-HN277/1-bad.txt +54 -0
- data/spec/fixtures/X212-HN277/1-good.txt +46 -0
- data/spec/fixtures/X212-HN277/2-bad.txt +37 -0
- data/spec/fixtures/X212-HN277/2-good.txt +29 -0
- data/spec/fixtures/X212-HN277/3-bad.txt +22 -0
- data/spec/fixtures/X212-HN277/3-good.txt +17 -0
- data/spec/fixtures/X212-HN277/4-bad.txt +30 -0
- data/spec/fixtures/X212-HN277/4-good.txt +24 -0
- data/spec/fixtures/X212-HR276/1-bad.txt +53 -0
- data/spec/fixtures/X212-HR276/1-good.txt +46 -0
- data/spec/fixtures/X212-HR276/2-bad.txt +45 -0
- data/spec/fixtures/X212-HR276/2-good.txt +38 -0
- data/spec/fixtures/X212-HR276/3-bad.txt +32 -0
- data/spec/fixtures/X212-HR276/3-good.txt +26 -0
- data/spec/fixtures/X212-HR276/4-bad.txt +32 -0
- data/spec/fixtures/X212-HR276/4-good.txt +26 -0
- data/spec/fixtures/X214-HN277/1-bad.txt +58 -0
- data/spec/fixtures/X214-HN277/1-good.txt +47 -0
- data/spec/fixtures/X214-HN277/2-bad.txt +34 -0
- data/spec/fixtures/X214-HN277/2-good.txt +22 -0
- data/spec/fixtures/X214-HN277/3-bad.txt +64 -0
- data/spec/fixtures/X214-HN277/3-good.txt +54 -0
- data/spec/fixtures/X214-HN277/4-bad.txt +77 -0
- data/spec/fixtures/X214-HN277/4-good.txt +63 -0
- data/spec/fixtures/X216-HI278/1-bad.txt +42 -0
- data/spec/fixtures/X216-HI278/1-good.txt +27 -0
- data/spec/fixtures/X216-HI278/2-bad.txt +43 -0
- data/spec/fixtures/X216-HI278/2-good.txt +29 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1.txt +24 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1_Clean.txt +20 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2.txt +46 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2_Clean.txt +30 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3.txt +38 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3_Clean.txt +24 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a.txt +39 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a_Clean.txt +24 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b.txt +43 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b_Clean.txt +25 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5.txt +63 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5_Clean.txt +41 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6.txt +36 -0
- data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6_Clean.txt +20 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r.txt +34 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r_Clean.txt +23 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r.txt +46 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r_Clean.txt +31 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r.txt +44 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r_Clean.txt +26 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4ar_Clean.txt +28 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4br_Clean.txt +35 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r.txt +60 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r_Clean.txt +42 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r.txt +40 -0
- data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r_Clean.txt +24 -0
- data/spec/fixtures/X218-RA820/1-bad.txt +31 -0
- data/spec/fixtures/X218-RA820/1-good.txt +25 -0
- data/spec/fixtures/X218-RA820/2-bad.txt +37 -0
- data/spec/fixtures/X218-RA820/2-good.txt +29 -0
- data/spec/fixtures/X218-RA820/3-bad.txt +29 -0
- data/spec/fixtures/X218-RA820/3-good.txt +23 -0
- data/spec/fixtures/X218-RA820/4-bad.txt +36 -0
- data/spec/fixtures/X218-RA820/4-good.txt +27 -0
- data/spec/fixtures/X220-BE834/1-bad.txt +35 -0
- data/spec/fixtures/X220-BE834/1-good.txt +29 -0
- data/spec/fixtures/X220-BE834/10-bad.txt +26 -0
- data/spec/fixtures/X220-BE834/10-good.txt +19 -0
- data/spec/fixtures/X220-BE834/2-bad.txt +31 -0
- data/spec/fixtures/X220-BE834/2-good.txt +23 -0
- data/spec/fixtures/X220-BE834/3-bad.txt +36 -0
- data/spec/fixtures/X220-BE834/3-good.txt +26 -0
- data/spec/fixtures/X220-BE834/4-bad.txt +27 -0
- data/spec/fixtures/X220-BE834/4-good.txt +21 -0
- data/spec/fixtures/X220-BE834/5-bad.txt +26 -0
- data/spec/fixtures/X220-BE834/5-good.txt +17 -0
- data/spec/fixtures/X220-BE834/6-bad.txt +25 -0
- data/spec/fixtures/X220-BE834/6-good.txt +20 -0
- data/spec/fixtures/X220-BE834/7-bad.txt +25 -0
- data/spec/fixtures/X220-BE834/7-good.txt +20 -0
- data/spec/fixtures/X220-BE834/8-bad.txt +25 -0
- data/spec/fixtures/X220-BE834/8-good.txt +20 -0
- data/spec/fixtures/X220-BE834/9-bad.txt +27 -0
- data/spec/fixtures/X220-BE834/9-good.txt +21 -0
- data/spec/fixtures/X221-HP835/1-bad.txt +58 -0
- data/spec/fixtures/X221-HP835/1-good.txt +40 -0
- data/spec/fixtures/X221-HP835/2-bad.txt +51 -0
- data/spec/fixtures/X221-HP835/2-good.txt +40 -0
- data/spec/fixtures/X221-HP835/3a-bad.txt +78 -0
- data/spec/fixtures/X221-HP835/3a-good.txt +49 -0
- data/spec/fixtures/X221-HP835/3b-bad.txt +60 -0
- data/spec/fixtures/X221-HP835/3b-good.txt +32 -0
- data/spec/fixtures/X221-HP835/3c-bad.txt +55 -0
- data/spec/fixtures/X221-HP835/3c-good.txt +34 -0
- data/spec/fixtures/X222-HC837/1-bad.txt +60 -0
- data/spec/fixtures/X222-HC837/1-good.txt +53 -0
- data/spec/fixtures/X222-HC837/10a-bad.txt +52 -0
- data/spec/fixtures/X222-HC837/10a-good.txt +40 -0
- data/spec/fixtures/X222-HC837/10b-bad.txt +99 -0
- data/spec/fixtures/X222-HC837/10b-good.txt +80 -0
- data/spec/fixtures/X222-HC837/10c-bad.txt +105 -0
- data/spec/fixtures/X222-HC837/10c-good.txt +80 -0
- data/spec/fixtures/X222-HC837/11-bad.txt +69 -0
- data/spec/fixtures/X222-HC837/11-good.txt +45 -0
- data/spec/fixtures/X222-HC837/12-bad.txt +73 -0
- data/spec/fixtures/X222-HC837/12-good.txt +51 -0
- data/spec/fixtures/X222-HC837/13-bad.txt +64 -0
- data/spec/fixtures/X222-HC837/13-good.txt +46 -0
- data/spec/fixtures/X222-HC837/3a-bad.txt +83 -0
- data/spec/fixtures/X222-HC837/3a-good.txt +59 -0
- data/spec/fixtures/X222-HC837/3b-bad.txt +97 -0
- data/spec/fixtures/X222-HC837/3b-good.txt +70 -0
- data/spec/fixtures/X222-HC837/3c-bad.txt +95 -0
- data/spec/fixtures/X222-HC837/3c-good.txt +74 -0
- data/spec/fixtures/X222-HC837/4-bad.txt +67 -0
- data/spec/fixtures/X222-HC837/4-good.txt +48 -0
- data/spec/fixtures/X222-HC837/5-bad.txt +73 -0
- data/spec/fixtures/X222-HC837/5-good.txt +60 -0
- data/spec/fixtures/X222-HC837/6-bad.txt +50 -0
- data/spec/fixtures/X222-HC837/6-good.txt +39 -0
- data/spec/fixtures/X222-HC837/7-bad.txt +93 -0
- data/spec/fixtures/X222-HC837/7-good.txt +78 -0
- data/spec/fixtures/X222-HC837/8-bad.txt +64 -0
- data/spec/fixtures/X222-HC837/8-good.txt +52 -0
- data/spec/fixtures/X222-HC837/9-bad.txt +56 -0
- data/spec/fixtures/X222-HC837/9-good.txt +38 -0
- data/spec/fixtures/X223-HC837/1-bad.txt +66 -0
- data/spec/fixtures/X223-HC837/1-good.txt +53 -0
- data/spec/fixtures/X223-HC837/2-bad.txt +69 -0
- data/spec/fixtures/X223-HC837/2-good.txt +60 -0
- data/spec/fixtures/X223-HC837/3-bad.txt +89 -0
- data/spec/fixtures/X223-HC837/3-good.txt +61 -0
- data/spec/fixtures/X223-HC837/4-bad.txt +60 -0
- data/spec/fixtures/X223-HC837/4-good.txt +40 -0
- data/spec/fixtures/X223-HC837/5-bad.txt +75 -0
- data/spec/fixtures/X223-HC837/5-good.txt +58 -0
- data/spec/fixtures/X224-HC837/1-bad.txt +54 -0
- data/spec/fixtures/X224-HC837/1-good.txt +44 -0
- data/spec/fixtures/X224-HC837/2a-bad.txt +52 -0
- data/spec/fixtures/X224-HC837/2a-good.txt +42 -0
- data/spec/fixtures/X224-HC837/2b-bad.txt +67 -0
- data/spec/fixtures/X224-HC837/2b-good.txt +52 -0
- data/spec/fixtures/X224-HC837/3-bad.txt +67 -0
- data/spec/fixtures/X224-HC837/3-good.txt +51 -0
- data/spec/fixtures/X224-HC837/4-bad.txt +49 -0
- data/spec/fixtures/X224-HC837/4-good.txt +40 -0
- data/spec/fixtures/X230-FA997/1-bad.txt +19 -0
- data/spec/fixtures/X230-FA997/1-good.txt +16 -0
- data/spec/fixtures/X231-FA999/1-bad.txt +20 -0
- data/spec/fixtures/X231-FA999/1-good.txt +20 -0
- data/spec/fixtures/X279-HB271/1-bad.txt +36 -0
- data/spec/fixtures/X279-HB271/1-good.txt +30 -0
- data/spec/fixtures/X279-HB271/2-bad.txt +22 -0
- data/spec/fixtures/X279-HB271/2-good.txt +16 -0
- data/spec/fixtures/X279-HB271/3-bad.txt +44 -0
- data/spec/fixtures/X279-HB271/3-good.txt +36 -0
- data/spec/fixtures/X279-HS270/1-bad.txt +29 -0
- data/spec/fixtures/X279-HS270/1-good.txt +23 -0
- data/spec/fixtures/X279-HS270/2-bad.txt +32 -0
- data/spec/fixtures/X279-HS270/2-good.txt +25 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/fixtures.rb +26 -0
- data/spec/support/matchers/either_matchers.rb +26 -0
- data/spec/support/matchers/navigation_matchers.rb +247 -0
- data/spec/support/node.rb +41 -0
- data/spec/support/quickcheck/characters.rb +28 -0
- data/spec/support/quickcheck/property.rb +105 -0
- data/spec/support/quickcheck/serialized_edi.rb +399 -0
- data/spec/support/quickcheck.rb +302 -0
- data/spec/support/rcov.rb +34 -0
- metadata +577 -0
data/doc/Navigating.md
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
Navigating the Parse Tree
|
|
2
|
+
=========================
|
|
3
|
+
|
|
4
|
+
Fundamentally, the [`StateMachine`][1] presents an interface for iterating the
|
|
5
|
+
syntax tree as if it were merely a linear sequence of segments. Purely
|
|
6
|
+
syntactical values like [`LoopVal`][2]s and [`TableVal`][3]s are hidden from the
|
|
7
|
+
programmer. While the interface only exposes segments and elements, the
|
|
8
|
+
information hidden by [`StateMachine`][1] provides an efficient means to search
|
|
9
|
+
the parse tree for specific segments.
|
|
10
|
+
|
|
11
|
+
For information on how to construct a parse tree programmatically, see the
|
|
12
|
+
document on {file:Generating.md Generating X12}. The [`StateMachine`][1] can be
|
|
13
|
+
accessed via the [`BuilderDsl#machine`][4] method. For information about how
|
|
14
|
+
to construct a parse tree from an input stream, see {file:Parsing.md Parsing X12}.
|
|
15
|
+
|
|
16
|
+
Iterating Segments
|
|
17
|
+
------------------
|
|
18
|
+
|
|
19
|
+
### Current Segment
|
|
20
|
+
|
|
21
|
+
When you want to access the current [`SegmentVal`][5], use the [`#segment`][6]
|
|
22
|
+
method. It returns an [`AbstractCursor`][7], which is a read-only pointer to the
|
|
23
|
+
current segment within the parse tree, wrapped by [`Either`][8]. When the parse
|
|
24
|
+
tree is empty, a failure will be returned.
|
|
25
|
+
|
|
26
|
+
# Success
|
|
27
|
+
machine.segment
|
|
28
|
+
#=> Either.success(#<Zipper::AbstractCursor ...>)
|
|
29
|
+
|
|
30
|
+
# Failure
|
|
31
|
+
machine.segment
|
|
32
|
+
#=> Either.failure("not a segment")
|
|
33
|
+
|
|
34
|
+
You may be wondering why the [`SegmentVal`][5] is wrapped by two wrappers. The
|
|
35
|
+
first, [`Either`][8], provides a manner to distinguish error return values from
|
|
36
|
+
normal return values. It is more sophisticated and less error-prone than using
|
|
37
|
+
conventions like returning `nil` on failure, because it supports chaining,
|
|
38
|
+
detailed error information can be returned, and the risk of neglecting to test
|
|
39
|
+
for an error is mitigated.
|
|
40
|
+
|
|
41
|
+
This [`Either`][8] value wraps an [`AbstractCursor`][7], which points to the
|
|
42
|
+
[`SegmentVal`][5] via its `#node` method. Because [`SegmentVal`][5] does not
|
|
43
|
+
have information about its parent or siblings (it only is aware of its
|
|
44
|
+
`#children`), returning only a [`SegmentVal`][5] does not always provide enough
|
|
45
|
+
information. The [`AbstractCursor`][7], on the other hand, allows access to any
|
|
46
|
+
related `AbstractVal` node.
|
|
47
|
+
|
|
48
|
+
# Success
|
|
49
|
+
machine.segment.map(&:node)
|
|
50
|
+
#=> Either.success(SegmentVal[IEA](...))
|
|
51
|
+
|
|
52
|
+
machine.segment.map(&:parent).map(&:node)
|
|
53
|
+
#=> Either.success(InterchangeVal[00501](...))
|
|
54
|
+
|
|
55
|
+
# Failure
|
|
56
|
+
machine.segment.map(&:node)
|
|
57
|
+
#=> Either.failure("not a segment")
|
|
58
|
+
|
|
59
|
+
For another example, the current segment identifier can be accessed like any
|
|
60
|
+
other method of [`SegmentVal`][5].
|
|
61
|
+
|
|
62
|
+
# When machine.segment fails, nothing is printed
|
|
63
|
+
machine.segment.tap do |s|
|
|
64
|
+
puts "Hello, #{s.node.id}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
### Going Forward
|
|
68
|
+
|
|
69
|
+
The [`#next`][9] method returns a [`StateMachine`][1] positioned at the segment
|
|
70
|
+
immediately following the current segment. Optionally, you may specify how many
|
|
71
|
+
segments to advance, which defaults to `1`. You can check if the current segment
|
|
72
|
+
is the last segment using the `#last?` method.
|
|
73
|
+
|
|
74
|
+
# Success
|
|
75
|
+
machine.last?
|
|
76
|
+
#=> false
|
|
77
|
+
|
|
78
|
+
machine.next
|
|
79
|
+
#=> Either.success(StateMachine[1](SegmentVal[GS](...)))
|
|
80
|
+
|
|
81
|
+
# Success
|
|
82
|
+
machine.next(3)
|
|
83
|
+
#=> Either.success(StateMachine[1](SegmentVal[BHT](...)))
|
|
84
|
+
|
|
85
|
+
# Failure
|
|
86
|
+
machine.last?
|
|
87
|
+
#=> true
|
|
88
|
+
|
|
89
|
+
machine.next
|
|
90
|
+
#=> Either.failure("cannot move to next after last segment")
|
|
91
|
+
|
|
92
|
+
### Going Backward
|
|
93
|
+
|
|
94
|
+
The [`#prev`][10] method returns a [`StateMachine`][1] positioned at the segment
|
|
95
|
+
immediately preceeding the current segment. Optionally, you may specify how many
|
|
96
|
+
segments to rewind, which defaults to `1`. You can check if the current segment
|
|
97
|
+
is the first segment using the `#first?` method.
|
|
98
|
+
|
|
99
|
+
# Success
|
|
100
|
+
machine.first?
|
|
101
|
+
#=> false
|
|
102
|
+
|
|
103
|
+
machine.prev
|
|
104
|
+
#=> Either.success(StateMachine[1](SegmentVal[GS](...)))
|
|
105
|
+
|
|
106
|
+
# Success
|
|
107
|
+
machine.prev(2)
|
|
108
|
+
#=> Either.success(StateMachine[1](SegmentVal[ISA](...)))
|
|
109
|
+
|
|
110
|
+
# Failure
|
|
111
|
+
machine.first?
|
|
112
|
+
#=> true
|
|
113
|
+
|
|
114
|
+
machine.prev
|
|
115
|
+
#=> Either.failure("cannot move to prev before first segment")
|
|
116
|
+
|
|
117
|
+
Accessing Elements
|
|
118
|
+
------------------
|
|
119
|
+
|
|
120
|
+
Elements can be accessed using the [`#element`][11] method, which accepts up to
|
|
121
|
+
three numeric arguments and requires at least one. Like [`#segment`][6], the
|
|
122
|
+
return value is a [`AbstractCursor`][7] wrapped by an [`Either`][8].
|
|
123
|
+
|
|
124
|
+
### Simple Elements
|
|
125
|
+
|
|
126
|
+
To access the first element of the current segment, call `#element(1)`. Notice
|
|
127
|
+
elements are counted starting at `1`, not `0`. Beware that [`#element`][11] will
|
|
128
|
+
raise an `ArgumentError` if you attempt to access the fifth element of a segment
|
|
129
|
+
whose declaration only indicates four elements, for instance.
|
|
130
|
+
|
|
131
|
+
# Success
|
|
132
|
+
machine.element(1).map(&:node)
|
|
133
|
+
#=> Either.success(Nn.value[ I16: Number of Included Functional Groups](1))
|
|
134
|
+
|
|
135
|
+
# Error
|
|
136
|
+
machine.element(3).map(&:node)
|
|
137
|
+
#=> IEA has only 2 elements (ArgumentError)
|
|
138
|
+
|
|
139
|
+
### Composite Elements
|
|
140
|
+
|
|
141
|
+
If the first element of the current segment is a `CompositeElementVal`, calling
|
|
142
|
+
`#element(1)` will return the entire composite value. To access a specific
|
|
143
|
+
component, call `#element(1, n)` which will return the *nth* `SimpleElementVal`.
|
|
144
|
+
Beware that [`#element`][11] will raise an `ArgumentError` if you attempt, for
|
|
145
|
+
instance, to access the third component of a composite whose declaration only
|
|
146
|
+
indicates two components.
|
|
147
|
+
|
|
148
|
+
# Success
|
|
149
|
+
machine.element(5).map(&:node)
|
|
150
|
+
#=> Either.success(CompositeElementVal[C023: HEALTH CARE SERVICE LOCATION INFORMATION](...))
|
|
151
|
+
|
|
152
|
+
# Success
|
|
153
|
+
machine.element(5, 1).map(&:node)
|
|
154
|
+
#=> Either.success(AN.value[E1331: Place of Service Code](11))
|
|
155
|
+
|
|
156
|
+
# Error
|
|
157
|
+
machine.element(5, 4).map(&:node)
|
|
158
|
+
#=> CLM05 has only 3 components (ArgumentError)
|
|
159
|
+
|
|
160
|
+
### Repeated Elements
|
|
161
|
+
|
|
162
|
+
When the first element of the current segment is a `RepeatedElementVal`, calling
|
|
163
|
+
`#element(1)` will return the entire sequence of element vals. To access a
|
|
164
|
+
specific occurrence of the element, call `#element(1, n)` which will return the
|
|
165
|
+
*nth* occurrence if it exists. If the element is a repeating *composite* element,
|
|
166
|
+
an optional third argument can be given to select a specific component. Beware
|
|
167
|
+
that [`#element`][11] will raise an `ArgumentError` if, for instance, you try to
|
|
168
|
+
access the sixth occurrence when the element definition declares the element can
|
|
169
|
+
occur a maximum of five times.
|
|
170
|
+
|
|
171
|
+
Taking Bigger Steps
|
|
172
|
+
-------------------
|
|
173
|
+
|
|
174
|
+
### First Segment
|
|
175
|
+
|
|
176
|
+
You can position the [`StateMachine`][1] at the first segment in the parse tree
|
|
177
|
+
by calling [`#first`][12]. When there are no segments in the parse tree, this
|
|
178
|
+
method returns a failure. This will typically position the [`StateMachine`][1]
|
|
179
|
+
at the first `ISA` segment.
|
|
180
|
+
|
|
181
|
+
machine.first.map(&:first?)
|
|
182
|
+
#=> Either.success(true)
|
|
183
|
+
|
|
184
|
+
### Last Segment
|
|
185
|
+
|
|
186
|
+
Likewise, the [`#last`][13] method will position the [`StateMachine`][1] at the
|
|
187
|
+
first segment in the parse tree if there is one. When the parse tree is empty,
|
|
188
|
+
a failure is returned instead. This will typically position the [`StateMachine`][1]
|
|
189
|
+
at the last `IEA` segment.
|
|
190
|
+
|
|
191
|
+
machine.last.map(&:last?)
|
|
192
|
+
#=> Either.success(true)
|
|
193
|
+
|
|
194
|
+
### Searching for Segments
|
|
195
|
+
|
|
196
|
+
The [`#find`][14] method performs an efficient context-sensitive search based
|
|
197
|
+
on the current position. Being context-sensitive places restrictions on which
|
|
198
|
+
segments are reachable from the current state, unlike iterating segments one
|
|
199
|
+
at a time. These restrictions prevent complicated problems, like mistakenly
|
|
200
|
+
finding an `NM1` segment from the next interchange because there were no more
|
|
201
|
+
`NM1` segments in the current interchange.
|
|
202
|
+
|
|
203
|
+
The *next* matching segment is returned, or a failure if no segments matched.
|
|
204
|
+
Searching for a segment that, according to the definition tree, cannot exist or
|
|
205
|
+
is not reachable will cause [`#find`][14] to raise an exception. To be clear,
|
|
206
|
+
[`#find`][14] only searches *forward* for segments, not backward.
|
|
207
|
+
|
|
208
|
+
#### Sibling Segments
|
|
209
|
+
|
|
210
|
+
<iframe src="images/837P-siblings.png" frameborder="no" scrolling="yes" height="430" width="100%"></iframe>
|
|
211
|
+
|
|
212
|
+
Segments connected directly by a horizontal dashed black line are siblings and
|
|
213
|
+
are reachable using [`#find`][14]. For instance, from the third `NM1`, the `N3`,
|
|
214
|
+
`N4`, and `REF` segments are reachable.
|
|
215
|
+
|
|
216
|
+
# From 2010AA NM1 right one segment to N3
|
|
217
|
+
machine.find(:N3)
|
|
218
|
+
#=> Either.success(StateMachine[1](N3(...)))
|
|
219
|
+
|
|
220
|
+
# Right two segments to N4
|
|
221
|
+
machine.find(:N4)
|
|
222
|
+
#=> Either.success(StateMachine[1](N4(...)))
|
|
223
|
+
|
|
224
|
+
# Right three segments to REF
|
|
225
|
+
machine.find(:REF)
|
|
226
|
+
#=> Either.success(StateMachine[1](REF(...)))
|
|
227
|
+
|
|
228
|
+
Likewise, `N4` and `REF` are reachable from `N3`; however, the third `NM1` is
|
|
229
|
+
_not_ reachable from `N3` because it preceeds `N3`.
|
|
230
|
+
|
|
231
|
+
#### Uncle Segments
|
|
232
|
+
|
|
233
|
+
Segments that occur as siblings of an ancestor node are uncles (remember that
|
|
234
|
+
[`#find`][14] only proceeds forward). Common uncle segments are `GE` and `IEA`,
|
|
235
|
+
which are analogous to "closing tags" for envelope structures. Other examples
|
|
236
|
+
include the `IK5` and `AK9` segments from the *999 Functional Acknowledgement*
|
|
237
|
+
transaction set.
|
|
238
|
+
|
|
239
|
+
# From BHT ascend twice and move left to GE
|
|
240
|
+
machine.find(:GE)
|
|
241
|
+
|
|
242
|
+
# From PRV ascend four times and move left to IEA
|
|
243
|
+
machine.find(:IEA)
|
|
244
|
+
|
|
245
|
+
Uncles are relatively rare in X12 transaction sets, because most child
|
|
246
|
+
structures, like loops, are _not_ wrapped by segments at both ends. For instance
|
|
247
|
+
there are no segments in Loop 2000A that follow the child loops.
|
|
248
|
+
|
|
249
|
+
#### Nephew Segments
|
|
250
|
+
|
|
251
|
+
<iframe src="images/837P-nephews.png" frameborder="no" scrolling="yes" height="450" width="100%"></iframe>
|
|
252
|
+
|
|
253
|
+
Segments that occur as the _first_ direct child of a sibling node are nephews.
|
|
254
|
+
The siblings that _follow_ the first child are not directly reachable, but they
|
|
255
|
+
can be reached indirectly by [chaining](#Chaining_Method_Calls) two calls to
|
|
256
|
+
[`#find`][14]. For example, `GS` is a nephew of `ISA`, and `ST` has two nephews
|
|
257
|
+
named `NM1`; but `BHT` is _not_ a nephew of `GS` because it is not the first
|
|
258
|
+
child of its parent node.
|
|
259
|
+
|
|
260
|
+
# From ST move left twice and down to NM1
|
|
261
|
+
machine.find(:NM1)
|
|
262
|
+
|
|
263
|
+
# From 2000A PRV move left and down to NM1
|
|
264
|
+
machine.find(:NM1)
|
|
265
|
+
|
|
266
|
+
# From 2300 CLM move left three times and down to NM1
|
|
267
|
+
machine.find(:NM1)
|
|
268
|
+
|
|
269
|
+
The first-child restriction prevents potential problems of ambiguity with
|
|
270
|
+
certain grammars. Consider the possibility that Table 1 could be defined to
|
|
271
|
+
have a 1100 `PER` loop in addition to its two `NM1` loops. From the `ST`
|
|
272
|
+
segment, without the restriction, there would be two possibly reachable `PER`
|
|
273
|
+
segments. One is the sibling of 1000A `NM1`, and the other is the 1100 `PER`
|
|
274
|
+
that we made up. Because [`#find`][14] returns the first matching segment, it
|
|
275
|
+
would return 1000A `PER` if it occurred, otherwise it would return the 1100
|
|
276
|
+
`PER`. The caller would have to check which one it was -- the necessity of this
|
|
277
|
+
test is not apparent without studying the grammar. Changing the grammar to add
|
|
278
|
+
Loop 1100 would break existing code. The first-child restriction solves these
|
|
279
|
+
problems.
|
|
280
|
+
|
|
281
|
+
#### Cousin Segments
|
|
282
|
+
|
|
283
|
+
<iframe src="images/837P-cousins.png" frameborder="no" scrolling="yes" height="470" width="100%"></iframe>
|
|
284
|
+
|
|
285
|
+
Segments that occurr as the _first_ child of a sibling of the parent node are
|
|
286
|
+
cousins of the current segment. Similar to the restriction on nephew segments,
|
|
287
|
+
siblings that follow the first child are _not_ directly reachable. For example,
|
|
288
|
+
the second `NM1` is a cousin of the first `NM1` and `PER` segments, the 2000AB
|
|
289
|
+
`NM1` is a cousin of all segments in Loop 2010AA, and each `HL` is a cousin of
|
|
290
|
+
all segments in Table 1.
|
|
291
|
+
|
|
292
|
+
# From 1000A PER to 2000A HL
|
|
293
|
+
machine.find(:HL)
|
|
294
|
+
|
|
295
|
+
# From 2000BA NM1 to 2000BB NM1
|
|
296
|
+
machine.find(:NM1)
|
|
297
|
+
|
|
298
|
+
You may have noticed, in some cases there are more than one cousin with the same
|
|
299
|
+
segment identifier -- there are three cousins of `BHT` named `HL`, for instance.
|
|
300
|
+
See [Element Constraints](#Element_Constraints) for information on how to find a
|
|
301
|
+
*specific* occurrence of `HL` segment based on its qualifier elements, or
|
|
302
|
+
[Chaining Method Calls](#Chaining_Method_Calls) for details on iterating each
|
|
303
|
+
`HL` segment, one-at-a-time.
|
|
304
|
+
|
|
305
|
+
#### Parent Segments
|
|
306
|
+
|
|
307
|
+
<iframe src="images/837P-parents.png" frameborder="no" scrolling="yes" height="450" width="100%"></iframe>
|
|
308
|
+
|
|
309
|
+
Internal knowledge of the underlying tree structure makes it possible to
|
|
310
|
+
*rewind* to the first segment of a parent structure, using the [`#parent`][15]
|
|
311
|
+
method. The parent may be the first segment of a loop, table, functional group,
|
|
312
|
+
or interchange, but never a transaction set, because they do not parent segments
|
|
313
|
+
directly.
|
|
314
|
+
|
|
315
|
+
# From PRV up two nodes, left one node, and down to ST
|
|
316
|
+
machine.parent
|
|
317
|
+
|
|
318
|
+
# From PER left one node to NM1
|
|
319
|
+
machine.parent
|
|
320
|
+
|
|
321
|
+
Traversing to the parent segment, unlike [`#find`][14], always traverses
|
|
322
|
+
backwards in the sequence of segments. The [`#parent`][15] method can only
|
|
323
|
+
rewind to the segment defined by the grammar, so it will always find the same
|
|
324
|
+
segment from a given starting position.
|
|
325
|
+
|
|
326
|
+
#### Element Constraints
|
|
327
|
+
|
|
328
|
+
Finding the next segment by identifier alone is often not specific enough. For
|
|
329
|
+
example, there are several different `NM1` segments that each have a different
|
|
330
|
+
meaning -- one is a provider, another is the insurance company, another is the
|
|
331
|
+
patient, etc. In the case of `NM1`, the first element is a qualifier that
|
|
332
|
+
indicates the meaning. To find `NM1*QC` "Patient Name", you can iterate the
|
|
333
|
+
reachable `NM1` segments and stop when you find the occurrence whose first
|
|
334
|
+
element equals `41` or when there are no more `NM1` occurrences,
|
|
335
|
+
|
|
336
|
+
# Find the NM1 occurrence with "41" in the first element
|
|
337
|
+
position = Either.success(machine)
|
|
338
|
+
searching = true
|
|
339
|
+
|
|
340
|
+
while searching and position.defined?
|
|
341
|
+
# Move position to the next NM1 segment
|
|
342
|
+
position = position.flatmap{|m| m.find(:NM1) }
|
|
343
|
+
|
|
344
|
+
# Check the constraint
|
|
345
|
+
position.tap do |nm1|
|
|
346
|
+
nm1.element(1).tap do |element|
|
|
347
|
+
# Stop the while loop if we found the match
|
|
348
|
+
searching = element.node != "QC"
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# Success
|
|
354
|
+
searching
|
|
355
|
+
#=> false
|
|
356
|
+
position
|
|
357
|
+
#=> Either.success(StateMachine[1](SegmentVal[NM1](...)))
|
|
358
|
+
|
|
359
|
+
# Failure
|
|
360
|
+
searching
|
|
361
|
+
#=> true
|
|
362
|
+
position
|
|
363
|
+
#=> Either.failure("NM1 segment does not occur")
|
|
364
|
+
|
|
365
|
+
There is a much simpler and less error-prone way, however. The [`#find`][14]
|
|
366
|
+
method accepts a variable number of filter arguments. For instance, the above
|
|
367
|
+
filter can be accomplished by calling,
|
|
368
|
+
|
|
369
|
+
machine.find(:NM1, "QC")
|
|
370
|
+
|
|
371
|
+
Multiple constraints can be specified and `#blank` or `nil` should be used to
|
|
372
|
+
indicate a wildcard, if needed. For instance to find the `NM1*PR` "Payer Name"
|
|
373
|
+
that has a certain organization name in element `NM103`,
|
|
374
|
+
|
|
375
|
+
machine.find(:NM1, "PR", nil, "MEDICARE")
|
|
376
|
+
|
|
377
|
+
#### Syntactic Constraints
|
|
378
|
+
|
|
379
|
+
In addition to improving readability, [`#find`][14] checks the validity of your
|
|
380
|
+
element constraints and raises an exception when you ask for something that is
|
|
381
|
+
guaranteed never to occur in a valid parse tree. For instance, if you called
|
|
382
|
+
`#find(:NM1, "XX")` from a position where there are no reachable `NM1` segments,
|
|
383
|
+
|
|
384
|
+
machine.find(:NM1, "XX")
|
|
385
|
+
#=> NM1 segment cannot be reached from the current state (ArgumentError)
|
|
386
|
+
|
|
387
|
+
Or from a position where every reachable `NM1` segment is defined such that
|
|
388
|
+
`"XX"` is not allowed,
|
|
389
|
+
|
|
390
|
+
machine.find(:NM1, "XX")
|
|
391
|
+
#=> "XX" is not allowed in NM101 (ArgumentError)
|
|
392
|
+
|
|
393
|
+
You can get a list of potentially reachable segments from the current position
|
|
394
|
+
by calling [`#successors`][22], which returns one [`InstructionTable`][23] per
|
|
395
|
+
active state. That is, when the machine is in a deterministic state, a single
|
|
396
|
+
[`InstructionTable`][23] will be returned. See the section on
|
|
397
|
+
[Non-determinism](#Non-determinism) for more information.
|
|
398
|
+
|
|
399
|
+
pp b.successors
|
|
400
|
+
|
|
401
|
+
[InstructionTable(
|
|
402
|
+
1: Instruction[REF: Subscriber Secon..](pop: 0, drop: 0),
|
|
403
|
+
2: Instruction[REF: Property and Cas..](pop: 0, drop: 0),
|
|
404
|
+
3: Instruction[PER: Property and Cas..](pop: 0, drop: 3),
|
|
405
|
+
4: Instruction[NM1: Subscriber Name ](pop: 1, drop: 0, push: LoopState),
|
|
406
|
+
5: Instruction[NM1: Payer Name ](pop: 1, drop: 0, push: LoopState),
|
|
407
|
+
6: Instruction[CLM: Claim Informatio..](pop: 1, drop: 2, push: LoopState),
|
|
408
|
+
7: Instruction[ HL: Subscriber Hiera..](pop: 2, drop: 0, push: LoopState),
|
|
409
|
+
8: Instruction[ HL: Billing Provider..](pop: 3, drop: 0, push: TableState),
|
|
410
|
+
9: Instruction[ HL: Subscriber Hiera..](pop: 3, drop: 0, push: TableState),
|
|
411
|
+
10: Instruction[ HL: Patient Hierachi..](pop: 3, drop: 0, push: TableState),
|
|
412
|
+
11: Instruction[ SE: Transaction Set ..](pop: 3, drop: 4, push: TableState),
|
|
413
|
+
12: Instruction[ ST](pop: 4, drop: 0, push: TransactionSetState),
|
|
414
|
+
13: Instruction[ GE: Functional Group..](pop: 4, drop: 2),
|
|
415
|
+
14: Instruction[ GS](pop: 5, drop: 0, push: FunctionalGroupState),
|
|
416
|
+
15: Instruction[IEA: Interchange Cont..](pop: 5, drop: 2),
|
|
417
|
+
16: Instruction[ISA](pop: 6, drop: 0, push: InterchangeState))]
|
|
418
|
+
|
|
419
|
+
### Chaining Method Calls
|
|
420
|
+
|
|
421
|
+
The [`Either`][8] datatype allows chaining via the [`#map`][16], [`#or`][18],
|
|
422
|
+
[`#flatmap`][17], and [`#tap`][19] methods. The use of each method is
|
|
423
|
+
demonstrated in the following examples.
|
|
424
|
+
|
|
425
|
+
#### Map
|
|
426
|
+
|
|
427
|
+
The [`#map`][16] method transforms one `Either.success` into another
|
|
428
|
+
`Either.success`. It leaves `Either.failure` values unaltered, passing
|
|
429
|
+
them through.
|
|
430
|
+
|
|
431
|
+
result = machine.find(:REF).map do |ref|
|
|
432
|
+
# When a REF segment was found, this block is
|
|
433
|
+
# executed. The return value of this block is
|
|
434
|
+
# wrapped by Either.success. If a REF segment
|
|
435
|
+
# was not found, this block is not executed and
|
|
436
|
+
# the Either.failure is propogated by #map
|
|
437
|
+
ref.id
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# Briefer syntax, implementing Symbol#to_proc
|
|
441
|
+
machine.find(:REF).map(&:id)
|
|
442
|
+
#=> Either.success(:REF)
|
|
443
|
+
|
|
444
|
+
machine.find(:REF).map(&:id).map(&:to_s)
|
|
445
|
+
#=> Either.success("REF")
|
|
446
|
+
|
|
447
|
+
machine.find(:REF).map(&:id).map(&:to_s).map(&:length)
|
|
448
|
+
#=> Either.success(3)
|
|
449
|
+
|
|
450
|
+
#### Flatmap
|
|
451
|
+
|
|
452
|
+
To transform one `Either.success` into another `Either`, which may be a success
|
|
453
|
+
or failure, use the [`#flatmap`][17] method. Like [`#map`][16], it also leaves
|
|
454
|
+
`Either.failure` values unaltered. This is an important technique to traverse
|
|
455
|
+
the parse tree. For instance, the following shows how to locate the "Billing
|
|
456
|
+
Provider Organization" of the first claim in the parse tree.
|
|
457
|
+
|
|
458
|
+
machine.first.
|
|
459
|
+
flatmap{|x| x.find(:GS) }.
|
|
460
|
+
flatmap{|x| x.find(:ST) }.
|
|
461
|
+
flatmap{|x| x.find(:HL, nil, nil, "20") }.
|
|
462
|
+
flatmap{|x| x.find(:NM1, "85") }.
|
|
463
|
+
flatmap{|x| x.element(3) }.
|
|
464
|
+
map(&:node)
|
|
465
|
+
#=> Either.success(AN.value[E1035: Billing Provider Last or Organizational Name](BEN KILDARE SERVICE))
|
|
466
|
+
|
|
467
|
+
You can use [`#flatmap`][17] to iterate a sequence of segments with the same
|
|
468
|
+
identifier, or use [`#iterate`][25] which does the same thing.
|
|
469
|
+
|
|
470
|
+
# Find the first HL segment
|
|
471
|
+
position = machine.first.
|
|
472
|
+
flatmap{|x| x.find(:GS) }.
|
|
473
|
+
flatmap{|x| x.find(:ST) }.
|
|
474
|
+
flatmap{|x| x.find(:HL) }
|
|
475
|
+
|
|
476
|
+
while position.defined?
|
|
477
|
+
position = position.flatmap do |hl|
|
|
478
|
+
# Process the HL segment
|
|
479
|
+
...
|
|
480
|
+
|
|
481
|
+
# Find the next HL segment
|
|
482
|
+
hl.find(:HL)
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
Note that the value returned by the block given to [`#flatmap`][17] must return
|
|
487
|
+
an instance of `Either` or a `TypeError` will be raised. The [`Object#try`][20]
|
|
488
|
+
method is similar to [`#flatmap`][17] in many ways.
|
|
489
|
+
|
|
490
|
+
#### Iterate
|
|
491
|
+
|
|
492
|
+
The [`#iterate`][25] method is a convenience method that calls [`#find`][14]
|
|
493
|
+
repeatedly with the given arguments, yielding its result to a block.
|
|
494
|
+
|
|
495
|
+
# Process each ST in the first ISA envelope
|
|
496
|
+
machine.first.flatmap do |isa|
|
|
497
|
+
isa.iterate(:GS) do |gs|
|
|
498
|
+
gs.iterate(:ST) do |st|
|
|
499
|
+
# ...
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
Note that the search starts *ahead* of the current position, so the following
|
|
505
|
+
`machine.first.flatmap{|m| m.iterate(:ISA) {|isa| ... }}` will never yield the
|
|
506
|
+
first ISA segment in the document, because it started searching *after* `m`,
|
|
507
|
+
which is the first ISA.
|
|
508
|
+
|
|
509
|
+
Since [`#iterate`][25] calls [`#find`][14], it enforces the same [syntactic
|
|
510
|
+
constraints](#Syntactic_Constraints).
|
|
511
|
+
|
|
512
|
+
#### Side Effects
|
|
513
|
+
|
|
514
|
+
In cases where you do not want to transform the `Either` value, but only need to
|
|
515
|
+
execute a side effect on `Either.success`, the [`#tap`][19] method is suitable.
|
|
516
|
+
On `Either.success` values, it passes the wrapped value to the block and returns
|
|
517
|
+
the original value, and it passes `Either.failure` values along without calling
|
|
518
|
+
the block.
|
|
519
|
+
|
|
520
|
+
# Record GS06 Group Control Number
|
|
521
|
+
machine.first.flatmap{|x| x.find(:GS) }.tap do |gs|
|
|
522
|
+
# The return value of this block is discarded
|
|
523
|
+
gs.element(6).tap do |control|
|
|
524
|
+
@numbers << control.node.to_s
|
|
525
|
+
end
|
|
526
|
+
end #=> Either.success(StateMachine[1](SegmentVal[GS](...)))
|
|
527
|
+
|
|
528
|
+
# Contrived example
|
|
529
|
+
machine.first.
|
|
530
|
+
flatmap{|x| x.find(:GS) }.tap{|x| puts "Hi, GS" }
|
|
531
|
+
flatmap{|x| x.find(:ST) }.tap{|x| puts "Hi, ST" }
|
|
532
|
+
#=> Either.success(StateMachine[1](SegmentVal[ST](...)))
|
|
533
|
+
|
|
534
|
+
The [`Object#tap`][21] method is similar to [`Either#tap`][19] except `#tap`
|
|
535
|
+
always calls the block, even on `nil`, while `#tap` does not call the block
|
|
536
|
+
on `Either.failure` values.
|
|
537
|
+
|
|
538
|
+
#### Error Recovery
|
|
539
|
+
|
|
540
|
+
When a method call earlier in the chain returns a `Either.failure`, the error
|
|
541
|
+
will be propogated through the chain unless it the [`#or`][18] method is used to
|
|
542
|
+
recover from the error.
|
|
543
|
+
|
|
544
|
+
result = machine.find(:ST).map do |st|
|
|
545
|
+
st.class
|
|
546
|
+
end.or do |reason|
|
|
547
|
+
# This block is executed if #find failed. The
|
|
548
|
+
# block must return an instance of Either, or
|
|
549
|
+
# a TypeError will be raised
|
|
550
|
+
Either.success(FalseClass)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
# Result is guaranteed to be Either.success because
|
|
554
|
+
# of the block given to #or. The wrapped value then
|
|
555
|
+
# is StateMachine or FalseClass
|
|
556
|
+
result.defined?
|
|
557
|
+
#=> true
|
|
558
|
+
|
|
559
|
+
### Word of Caution
|
|
560
|
+
|
|
561
|
+
Beware that the [`#find`][14] method only searches _forward_ in the sequence
|
|
562
|
+
of segments. In some cases, you will need to save the current position to let
|
|
563
|
+
you restart another search from that position, rather than chaining successive
|
|
564
|
+
searches together.
|
|
565
|
+
|
|
566
|
+
For instance, in the X222 837P transaction set, there are sixteen different
|
|
567
|
+
consecutive `DTP` segments in Loop 2300. While the X222 implementation guide
|
|
568
|
+
arranges them in what appears to be a sequence, there is no restriction on
|
|
569
|
+
the order in which the `DTP` segments occur -- they all have the same position.
|
|
570
|
+
Thus `DTP*439` "Accident Date" can follow or preceed `DTP*096` "Discharge Date",
|
|
571
|
+
and one or both might not be present.
|
|
572
|
+
|
|
573
|
+
clm = machine.first.
|
|
574
|
+
flatmap{|x| x.find(:GS) }.
|
|
575
|
+
flatmap{|x| x.find(:ST) }.
|
|
576
|
+
flatmap{|x| x.find(:HL, nil, nil, nil, "0") }.
|
|
577
|
+
flatmap{|x| x.find(:CLM) }
|
|
578
|
+
|
|
579
|
+
clm. # Wrong: this assumes DTP*439 occurs before DTP*096
|
|
580
|
+
flatmap{|x| x.find(:DTP, "439") }.tap{|x| puts "accident ..." }
|
|
581
|
+
flatmap{|x| x.find(:DTP, "096") }.tap{|x| puts "discharge ..." }
|
|
582
|
+
|
|
583
|
+
# Correct: no order is assumed among the DTP segments
|
|
584
|
+
clm.flatmap{|x| x.find(:DTP, "439") }.tap{|x| puts "accident ..." }
|
|
585
|
+
clm.flatmap{|x| x.find(:DTP, "096") }.tap{|x| puts "accident ..." }
|
|
586
|
+
|
|
587
|
+
In general, siblings following the first segment in a purely syntactic node,
|
|
588
|
+
like a table, loop, or envelope structure cannot exist unless the syntactic node
|
|
589
|
+
exists -- and the syntactic node cannot exist unless an _entry segment_ from the
|
|
590
|
+
definition of that node occurs. With few exceptions, the entry segment of a
|
|
591
|
+
syntactic node is the first segment in its definition. Therefore, the 2300 `DTP`
|
|
592
|
+
segments cannot exist unless the 2300 `CLM` segment occurs; that is why it is
|
|
593
|
+
best to save the `CLM` position and use it as a starting point.
|
|
594
|
+
|
|
595
|
+
Non-determinism
|
|
596
|
+
---------------
|
|
597
|
+
|
|
598
|
+
Certain sequences of input segments can be described by more than one parse
|
|
599
|
+
tree. Often these sequences are malformed. For instance, in an X222 837P
|
|
600
|
+
transaction, an `HL` segment that has an empty `HL03` qualifier could
|
|
601
|
+
potentially be the `HL` segment describing the "Billing Provider Detail",
|
|
602
|
+
"Subscriber Detail", or "Patient Detail". In this case the parser will construct
|
|
603
|
+
three parse trees: one for each possibility. The parser will respond to
|
|
604
|
+
[`#deterministic?`][24] with `false` when it is in a non-deterministic state.
|
|
605
|
+
|
|
606
|
+
In a non-determistic state, methods that normally return a single node will
|
|
607
|
+
return `Either.failure("non-deterministic state")`. These are [`#segment`][6],
|
|
608
|
+
[`#element`][11], and `#zipper`. Traversal methods, however, like [`#next`][9]
|
|
609
|
+
[`#first`][12], [`#last`][13], [`#find`][14], and [`#parent`][15], operate on
|
|
610
|
+
each parse tree in parallel.
|
|
611
|
+
|
|
612
|
+
These traversal methods will position the parser on parallel segments within
|
|
613
|
+
each parse tree. To use the `HL` example again, the parser would point to
|
|
614
|
+
each tree's version of the `HL` segment, one named "Patient Detail", one named
|
|
615
|
+
"Bililng Provider Detail", and another named "Subscriber Detail". These segments
|
|
616
|
+
all have the same element values, but have a different meaning.
|
|
617
|
+
|
|
618
|
+
### Resolution
|
|
619
|
+
|
|
620
|
+
[1]: Stupidedi/Builder/StateMachine.html
|
|
621
|
+
[2]: Stupidedi/Values/LoopVal.html
|
|
622
|
+
[3]: Stupidedi/Values/TableVal.html
|
|
623
|
+
[4]: Stupidedi/Builder/BuilderDsl.html#machine-instance_method
|
|
624
|
+
[5]: Stupidedi/Values/SegmentVal.html
|
|
625
|
+
[6]: Stupidedi/Builder/Navigation.html#segment-instance_method
|
|
626
|
+
[7]: Stupidedi/Zipper/AbstractCursor.html
|
|
627
|
+
[8]: Stupidedi/Either.html
|
|
628
|
+
[9]: Stupidedi/Builder/Navigation.html#next-instance_method
|
|
629
|
+
[10]: Stupidedi/Builder/Navigation.html#prev-instance_method
|
|
630
|
+
[11]: Stupidedi/Builder/Navigation.html#element-instance_method
|
|
631
|
+
[12]: Stupidedi/Builder/Navigation.html#first-instance_method
|
|
632
|
+
[13]: Stupidedi/Builder/Navigation.html#last-instance_method
|
|
633
|
+
[14]: Stupidedi/Builder/Navigation.html#find-instance_method
|
|
634
|
+
[15]: Stupidedi/Builder/Navigation.html#parent-instance_method
|
|
635
|
+
[16]: Stupidedi/Either.html#map-instance_method
|
|
636
|
+
[17]: Stupidedi/Either.html#flatmap-instance_method
|
|
637
|
+
[18]: Stupidedi/Either.html#or-instance_method
|
|
638
|
+
[19]: Stupidedi/Either.html#tap-instance_method
|
|
639
|
+
[20]: Object.html#try-instance_method
|
|
640
|
+
[21]: Object.html#tap-instance_method
|
|
641
|
+
[22]: Stupidedi/Builder/InstructionTable.html
|
|
642
|
+
[23]: Stupidedi/Builder/StateMachine.html#successors-instance_method
|
|
643
|
+
[24]: Stupidedi/Builder/StateMachine.html#deterministic%3F-instance_method
|
|
644
|
+
[25]: Stupidedi/Builder/Navigation.html#iterate-instance_method
|
|
645
|
+
|
data/doc/Parsing.md
ADDED
|
File without changes
|
data/doc/Serializing.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Serializing X12
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Once you have built a parse tree, either by generating one programatically (see
|
|
5
|
+
{file:Generating.md Generating}) or parsing serialized input (see
|
|
6
|
+
{file:Parsing.md}), you can serialize it back to a string using one of the
|
|
7
|
+
classes in [`Stupidedi::Writer`][1].
|
data/doc/Tokenizing.md
ADDED
|
File without changes
|
data/doc/Validating.md
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|