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
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
module Stupidedi
|
|
2
|
+
module Builder
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# The {ConstraintTable} is a data structure that contains one or more
|
|
6
|
+
# {Instruction} values for the same segment identifier. Each concrete
|
|
7
|
+
# subclass implements different strategies for narrowing down the
|
|
8
|
+
# {Instruction} list.
|
|
9
|
+
#
|
|
10
|
+
# Reducing the number of valid {Instruction} values is important because
|
|
11
|
+
# executing more than one {Instruction} creates a non-deterministic state --
|
|
12
|
+
# more than one valid parse tree exists -- which slows the parser. Most
|
|
13
|
+
# often there is only one valid {Instruction} but the parser cannot
|
|
14
|
+
# (efficiently or at all) narrow the tree down without evaluating the
|
|
15
|
+
# constraints declared by each {Instruction}'s {Schema::SegmentUse}, which
|
|
16
|
+
# is done here.
|
|
17
|
+
#
|
|
18
|
+
class ConstraintTable
|
|
19
|
+
|
|
20
|
+
# @return [Array<Instruction>]
|
|
21
|
+
abstract :matches, :args => %w(segment_tok)
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Performs no filtering of the {Instruction} list. This is used when there
|
|
25
|
+
# already is a single {Instruction} or when a {Reader::SegmentTok} doesn't
|
|
26
|
+
# provide any more information to filter the list.
|
|
27
|
+
#
|
|
28
|
+
class Stub < ConstraintTable
|
|
29
|
+
def initialize(instructions)
|
|
30
|
+
@instructions = instructions
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @return [Array<Instruction>]
|
|
34
|
+
def matches(segment_tok, strict)
|
|
35
|
+
@instructions
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Chooses the {Instruction} that pops the fewest number of states. For
|
|
41
|
+
# example, in the X222 837P an HL segment signals the start of a new
|
|
42
|
+
# 2000 loop, but may or may not begin a new Table 2 -- the specifications
|
|
43
|
+
# aren't actually clear. This rule will avoid creating a new Table 2 if
|
|
44
|
+
# possible, and instead create a new 2000 loop under the current Table 2.
|
|
45
|
+
#
|
|
46
|
+
class DepthBased < ConstraintTable
|
|
47
|
+
def initialize(instructions)
|
|
48
|
+
@instructions = instructions
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [Array<Instruction>]
|
|
52
|
+
def matches(segment_tok, strict)
|
|
53
|
+
@__matches ||= begin
|
|
54
|
+
deepest = @instructions.head
|
|
55
|
+
|
|
56
|
+
@instructions.tail.each do |i|
|
|
57
|
+
if i.pop_count < deepest.pop_count
|
|
58
|
+
deepest = i
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
deepest.cons
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
# Chooses the subset of {Instruction} values based on the distinguishing
|
|
69
|
+
# values allowed by each {Schema::SegmentUse}. For instance, there are
|
|
70
|
+
# often several loops that begin with `NM1`, which are distinguished by
|
|
71
|
+
# the qualifier in element `NM101`.
|
|
72
|
+
#
|
|
73
|
+
class ValueBased < ConstraintTable
|
|
74
|
+
def initialize(instructions)
|
|
75
|
+
@instructions = instructions
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @return [Array<Instruction>]
|
|
79
|
+
def matches(segment_tok, strict)
|
|
80
|
+
invalid = true # Were all possibly distinguishing elements invalid?
|
|
81
|
+
present = false # Were any possibly distinguishing elements present?
|
|
82
|
+
|
|
83
|
+
@__basis ||= basis(deepest(@instructions))
|
|
84
|
+
@__basis.head.each do |(n, m), map|
|
|
85
|
+
value = deconstruct(segment_tok.element_toks, n, m)
|
|
86
|
+
|
|
87
|
+
case value
|
|
88
|
+
when nil, :not_used, :default
|
|
89
|
+
# ignore
|
|
90
|
+
else
|
|
91
|
+
singleton = map.at(value)
|
|
92
|
+
present = true
|
|
93
|
+
|
|
94
|
+
unless singleton.nil?
|
|
95
|
+
return singleton
|
|
96
|
+
else
|
|
97
|
+
if strict
|
|
98
|
+
designator = "#{segment_tok.id}#{'%02d' % (n + 1)}"
|
|
99
|
+
designator << "-%02d" % m unless m.nil?
|
|
100
|
+
|
|
101
|
+
raise ArgumentError,
|
|
102
|
+
"#{value.inspect} is not allowed in #{designator}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# If we reach this line, none of the present elements could, on its
|
|
109
|
+
# own, narrow the search space to a single Instruction. We now test
|
|
110
|
+
# the combination of elements to iteratively narrow the search space
|
|
111
|
+
space = @instructions
|
|
112
|
+
|
|
113
|
+
# @todo: These filters should be ordered by probable effectiveness,
|
|
114
|
+
# so we narrow the search space by the largest amount in the fewest
|
|
115
|
+
# number of steps.
|
|
116
|
+
@__basis.last.each do |(n, m), map|
|
|
117
|
+
value = deconstruct(segment_tok.element_toks, n, m)
|
|
118
|
+
|
|
119
|
+
unless value.nil?
|
|
120
|
+
subset = map.at(value)
|
|
121
|
+
present = true
|
|
122
|
+
|
|
123
|
+
unless subset.blank?
|
|
124
|
+
invalid = false
|
|
125
|
+
space &= subset
|
|
126
|
+
|
|
127
|
+
if space.length <= 1
|
|
128
|
+
return space
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
if strict
|
|
132
|
+
designator = "#{segment_tok.id}#{'%02d' % n}"
|
|
133
|
+
designator << "-%02d" % m unless m.nil?
|
|
134
|
+
|
|
135
|
+
raise ArgumentError,
|
|
136
|
+
"#{value.inspect} is not allowed in #{designator}"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if invalid and present
|
|
143
|
+
[]
|
|
144
|
+
else
|
|
145
|
+
space
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
private
|
|
150
|
+
|
|
151
|
+
# Resolve conflicts between instructions that have identical SegmentUse
|
|
152
|
+
# values. For each SegmentUse, this chooses the Instruction that pops
|
|
153
|
+
# the fewest number of states.
|
|
154
|
+
#
|
|
155
|
+
# @return [Array<Instruction>]
|
|
156
|
+
def deepest(instructions)
|
|
157
|
+
deepest = Hash.new
|
|
158
|
+
|
|
159
|
+
instructions.each do |i|
|
|
160
|
+
key = i.segment_use.object_id
|
|
161
|
+
|
|
162
|
+
if deepest.defined_at?(key)
|
|
163
|
+
if deepest.at(key).pop_count > i.pop_count
|
|
164
|
+
deepest[key] = i
|
|
165
|
+
end
|
|
166
|
+
else
|
|
167
|
+
deepest[key] = i
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
deepest.values
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @return [Array(Array<(Integer, Integer, Map)>, Array<(Integer, Integer, Map)>)]
|
|
175
|
+
def basis(instructions)
|
|
176
|
+
disjoint_elements = []
|
|
177
|
+
distinct_elements = []
|
|
178
|
+
|
|
179
|
+
# The first SegmentUse is used to represent the structure that must
|
|
180
|
+
# be shared by the others: number of elements and type of elements
|
|
181
|
+
element_uses = instructions.head.segment_use.definition.element_uses
|
|
182
|
+
|
|
183
|
+
# Iterate over each element across all SegmentUses (think columns)
|
|
184
|
+
# NM1*[IL]*[ ]*..*..*..*..*..*[ ]*..*..*{..}*..
|
|
185
|
+
# NM1*[40]*[ ]*..*..*..*..*..*[ ]*..*..*{..}*..
|
|
186
|
+
element_uses.length.times do |n|
|
|
187
|
+
if element_uses.at(n).composite?
|
|
188
|
+
ms = 0 .. element_uses.at(n).definition.component_uses.length - 1
|
|
189
|
+
else
|
|
190
|
+
ms = [nil]
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# If this is a composite element, we iterate over each component.
|
|
194
|
+
# Otherwise this loop iterates once with the index {m} set to nil.
|
|
195
|
+
ms.each do |m|
|
|
196
|
+
last = nil # the last subset we examined
|
|
197
|
+
total = Sets.empty # the union of all examined subsets
|
|
198
|
+
|
|
199
|
+
distinct = false
|
|
200
|
+
disjoint = true
|
|
201
|
+
|
|
202
|
+
instructions.each do |i|
|
|
203
|
+
element_use = i.segment_use.definition.element_uses.at(n)
|
|
204
|
+
|
|
205
|
+
unless m.nil?
|
|
206
|
+
element_use = element_use.definition.component_uses.at(m)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
allowed_vals = element_use.allowed_values
|
|
210
|
+
|
|
211
|
+
# We want to know if every instruction's set of allowed values
|
|
212
|
+
# is disjoint (with one another). Instead of comparing each set
|
|
213
|
+
# with every other set, which takes (N-1)! comparisons, we can
|
|
214
|
+
# do it in N steps.
|
|
215
|
+
disjoint &&= allowed_vals.disjoint?(total)
|
|
216
|
+
|
|
217
|
+
# We also want to know if one instruction's set of allowed vals
|
|
218
|
+
# contains elements that aren't present in at least one other
|
|
219
|
+
# set. The opposite condition is easy to test: all sets contain
|
|
220
|
+
# the same elements (are equal). So we can similarly, check this
|
|
221
|
+
# condition in N steps rather than (N-1)!
|
|
222
|
+
distinct ||= allowed_vals != last unless last.nil?
|
|
223
|
+
|
|
224
|
+
total = allowed_vals.union(total)
|
|
225
|
+
last = allowed_vals
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# puts "#{n}.#{m}: disjoint(#{disjoint}) distinct(#{distinct})"
|
|
229
|
+
|
|
230
|
+
if disjoint
|
|
231
|
+
# Since each instruction's set of allowed values is disjoint, we
|
|
232
|
+
# can build a function/hash that returns the single instruction,
|
|
233
|
+
# given one of the values. When given a value outside the set of
|
|
234
|
+
# all (combined) values, it returns nil.
|
|
235
|
+
disjoint_elements << [[n, m], build_disjoint(total, n, m, instructions)]
|
|
236
|
+
elsif distinct
|
|
237
|
+
# Not all instructions have the same set of allowed values. So
|
|
238
|
+
# we can build a function/hash that accepts one of the values
|
|
239
|
+
# and returns the subset of the instructions where that value
|
|
240
|
+
# can occur. This might be some, none, or all of the original
|
|
241
|
+
# instructions, so clearly this provides less information than
|
|
242
|
+
# if each allowed value set was disjoint.
|
|
243
|
+
|
|
244
|
+
# Currently disabled (and untested) because it doesn't look like
|
|
245
|
+
# any of the HIPAA schemas would use this -- so testing it would
|
|
246
|
+
# be a pain.
|
|
247
|
+
#
|
|
248
|
+
distinct_elements << [[n, m], build_distinct(total, n, m, instructions)]
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
[disjoint_elements, distinct_elements]
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# @return [Hash<String, Array<Instruction>>]
|
|
257
|
+
def build_disjoint(total, n, m, instructions)
|
|
258
|
+
if total.finite?
|
|
259
|
+
# The sum of all allowed value sets is finite, so we know that each
|
|
260
|
+
# individual allowed value set is finite (we can iterate over it).
|
|
261
|
+
map = Hash.new
|
|
262
|
+
|
|
263
|
+
instructions.each do |i|
|
|
264
|
+
element_use = i.segment_use.definition.element_uses.at(n)
|
|
265
|
+
|
|
266
|
+
unless m.nil?
|
|
267
|
+
element_use = element_use.definition.component_uses.at(m)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
allowed_vals = element_use.allowed_values
|
|
271
|
+
allowed_vals.each{|v| map[v] = i.cons }
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
map
|
|
275
|
+
else
|
|
276
|
+
# At least one of allowed value sets is infinite. This happens when
|
|
277
|
+
# it is RelativeComplement, which declares the values that are *not*
|
|
278
|
+
# allowed in the set.
|
|
279
|
+
map = Hash.new{|h,k| h[k] = instructions }
|
|
280
|
+
|
|
281
|
+
instructions.each do |i|
|
|
282
|
+
element_use = i.segment_use.definition.element_uses.at(n)
|
|
283
|
+
unless m.nil?
|
|
284
|
+
element_use = element_use.definition.component_uses.at(m)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
allowed_vals = element_use.allowed_values
|
|
288
|
+
|
|
289
|
+
unless allowed_vals.finite?
|
|
290
|
+
allowed_vals.complement.each{|v| map[v] -= i }
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Clear the default_proc so accesses don't change the Hash
|
|
295
|
+
map.default = instructions
|
|
296
|
+
map
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# @return [Hash<String, Array<Instruction>>]
|
|
301
|
+
def build_distinct(total, n, m, instructions)
|
|
302
|
+
if total.finite?
|
|
303
|
+
# The sum of all allowed value sets is finite, so we know that each
|
|
304
|
+
# individual allowed value set is finite (we can iterate over it).
|
|
305
|
+
map = Hash.new{|h,k| h[k] = [] }
|
|
306
|
+
|
|
307
|
+
instructions.each do |i|
|
|
308
|
+
element_use = i.segment_use.definition.element_uses.at(n)
|
|
309
|
+
|
|
310
|
+
unless m.nil?
|
|
311
|
+
element_use = element_use.definition.component_uses.at(m)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
allowed_vals = element_use.allowed_values
|
|
315
|
+
allowed_vals.each{|v| map[v] << i }
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Clear the default_proc so accesses don't change the Hash
|
|
319
|
+
map.default = []
|
|
320
|
+
map
|
|
321
|
+
else
|
|
322
|
+
# At least one of allowed value sets is infinite. This happens when
|
|
323
|
+
# it is RelativeComplement, which declares the values that are *not*
|
|
324
|
+
# allowed in the set.
|
|
325
|
+
map = Hash.new{|h,k| h[k] = instructions }
|
|
326
|
+
|
|
327
|
+
instructions.each do |i|
|
|
328
|
+
element_use = i.segment_use.definition.element_uses.at(n)
|
|
329
|
+
|
|
330
|
+
unless m.nil?
|
|
331
|
+
element_use = element_use.definition.component_uses.at(m)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
allowed_vals = element_use.allowed_values
|
|
335
|
+
|
|
336
|
+
unless allowed_vals.finite?
|
|
337
|
+
allowed_vals.complement.each{|v| map[v] -= i }
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Clear the default_proc so accesses don't change the Hash
|
|
342
|
+
map.default = instructions
|
|
343
|
+
map
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Return the value of the `m`-th elemnt, or if `n` is not nil, return
|
|
348
|
+
# the value of the `n`-th component from the `n`-th element. When the
|
|
349
|
+
# value is blank, the function returns `nil`.
|
|
350
|
+
#
|
|
351
|
+
# @param [Array<Reader::SimpleElementTok, Reader::CompositeElementTok>] element_toks
|
|
352
|
+
# @param [Integer] m
|
|
353
|
+
# @param [Integer, nil] n
|
|
354
|
+
#
|
|
355
|
+
# @return [String, nil]
|
|
356
|
+
def deconstruct(element_toks, m, n)
|
|
357
|
+
element_tok = element_toks.at(m)
|
|
358
|
+
element_tok = element_tok.element_toks.at(0) if element_tok.try(:repeated?)
|
|
359
|
+
|
|
360
|
+
if element_tok.blank?
|
|
361
|
+
nil
|
|
362
|
+
elsif n.nil?
|
|
363
|
+
element_tok.value
|
|
364
|
+
else
|
|
365
|
+
element_tok = element_tok.component_toks.at(n)
|
|
366
|
+
|
|
367
|
+
if element_tok.blank?
|
|
368
|
+
nil
|
|
369
|
+
else
|
|
370
|
+
element_tok.value
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
class << ConstraintTable
|
|
379
|
+
# @group Constructors
|
|
380
|
+
#########################################################################
|
|
381
|
+
|
|
382
|
+
# Given a list of {Instruction} values for the same segment identifier,
|
|
383
|
+
# this method constructs the appropriate concrete subclass of
|
|
384
|
+
# {ConstraintTable}.
|
|
385
|
+
#
|
|
386
|
+
# @param [Array<Instruction>] instructions
|
|
387
|
+
# @return [ConstraintTable]
|
|
388
|
+
def build(instructions)
|
|
389
|
+
if instructions.length <= 1
|
|
390
|
+
ConstraintTable::Stub.new(instructions)
|
|
391
|
+
elsif instructions.any?{|i| i.segment_use.nil? } and
|
|
392
|
+
not instructions.all?{|i| i.segment_use.nil? }
|
|
393
|
+
# When one of the instructions has a nil segment_use, it means
|
|
394
|
+
# the SegmentUse is determined when pushing the new state. There
|
|
395
|
+
# isn't a way to know the segment constraints from here.
|
|
396
|
+
ConstraintTable::Stub.new(instructions)
|
|
397
|
+
else
|
|
398
|
+
segment_uses = instructions.map{|i| i.segment_use }
|
|
399
|
+
|
|
400
|
+
if segment_uses.map{|u| u.object_id }.uniq.length <= 1
|
|
401
|
+
# The same SegmentUse may appear more than once, because the
|
|
402
|
+
# segment can be placed at different levels in the tree. If
|
|
403
|
+
# all the instructions have the same SegmentUse, they also have
|
|
404
|
+
# the same element constraints so we can't use them to narrow
|
|
405
|
+
# down the instruction list.
|
|
406
|
+
ConstraintTable::DepthBased.new(instructions)
|
|
407
|
+
else
|
|
408
|
+
ConstraintTable::ValueBased.new(instructions)
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# @endgroup
|
|
414
|
+
#########################################################################
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
end
|
|
418
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Stupidedi
|
|
2
|
+
module Builder
|
|
3
|
+
|
|
4
|
+
module Generation
|
|
5
|
+
|
|
6
|
+
# @return [(StateMachine, Either<Reader::TokenReader>)]
|
|
7
|
+
def read(reader)
|
|
8
|
+
machine = self
|
|
9
|
+
reader = reader.read_segment
|
|
10
|
+
|
|
11
|
+
while reader.defined?
|
|
12
|
+
reader = reader.flatmap do |segment_tok, reader|
|
|
13
|
+
machine, reader =
|
|
14
|
+
machine.insert(segment_tok, reader)
|
|
15
|
+
|
|
16
|
+
reader.read_segment
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
return machine, reader
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [(StateMachine, Reader::TokenReader)]
|
|
24
|
+
def insert(segment_tok, reader)
|
|
25
|
+
active = []
|
|
26
|
+
|
|
27
|
+
@active.each do |zipper|
|
|
28
|
+
state = zipper.node
|
|
29
|
+
instructions = state.instructions.matches(segment_tok)
|
|
30
|
+
|
|
31
|
+
if instructions.empty?
|
|
32
|
+
active << zipper.append(FailureState.mksegment(segment_tok, state))
|
|
33
|
+
next
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
instructions.each do |op|
|
|
37
|
+
if op.push.nil?
|
|
38
|
+
table = zipper.node.instructions
|
|
39
|
+
value = zipper.node.zipper
|
|
40
|
+
state = zipper
|
|
41
|
+
|
|
42
|
+
op.pop_count.times do
|
|
43
|
+
value = value.up
|
|
44
|
+
state = state.up
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create a new AbstractState node that has a new InstructionTable
|
|
48
|
+
# and also points to a new AbstractVal tree (with the new segment)
|
|
49
|
+
segment = AbstractState.mksegment(segment_tok, op.segment_use)
|
|
50
|
+
successor = state.append(state.node.copy(
|
|
51
|
+
:zipper => value.append(segment),
|
|
52
|
+
:instructions => table.pop(op.pop_count).drop(op.drop_count)))
|
|
53
|
+
|
|
54
|
+
unless op.pop_count.zero? or reader.stream?
|
|
55
|
+
# More general than checking if segment_tok is an ISE/GE segment
|
|
56
|
+
unless reader.separators.eql?(successor.node.separators) \
|
|
57
|
+
and reader.segment_dict.eql?(successor.node.segment_dict)
|
|
58
|
+
reader = reader.copy \
|
|
59
|
+
:separators => successor.node.separators,
|
|
60
|
+
:segment_dict => successor.node.segment_dict
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
table = zipper.node.instructions
|
|
65
|
+
value = zipper.node.zipper
|
|
66
|
+
state = zipper
|
|
67
|
+
|
|
68
|
+
op.pop_count.times do
|
|
69
|
+
value = value.up
|
|
70
|
+
state = state.up
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
parent = state.node.copy \
|
|
74
|
+
:zipper => value,
|
|
75
|
+
:children => [],
|
|
76
|
+
:separators => reader.separators,
|
|
77
|
+
:segment_dict => reader.segment_dict,
|
|
78
|
+
:instructions => table.pop(op.pop_count).drop(op.drop_count)
|
|
79
|
+
|
|
80
|
+
state = state.append(parent) unless state.root?
|
|
81
|
+
|
|
82
|
+
successor = op.push.push(state, parent, segment_tok, op.segment_use, @config)
|
|
83
|
+
|
|
84
|
+
# More general than checking if segment_tok is an ISA/GS segment
|
|
85
|
+
unless reader.separators.eql?(successor.node.separators) \
|
|
86
|
+
and reader.segment_dict.eql?(successor.node.segment_dict)
|
|
87
|
+
reader = reader.copy \
|
|
88
|
+
:separators => successor.node.separators,
|
|
89
|
+
:segment_dict => successor.node.segment_dict
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
active << successor
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
return StateMachine.new(@config, active), reader
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @return [StateMachine]
|
|
101
|
+
def replace(segment_tok, reader)
|
|
102
|
+
# @todo
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @return [StateMachine]
|
|
106
|
+
def remove
|
|
107
|
+
# @todo
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Stupidedi
|
|
2
|
+
module Builder
|
|
3
|
+
|
|
4
|
+
class Instruction
|
|
5
|
+
include Inspect
|
|
6
|
+
|
|
7
|
+
# The segment identifier to which this {Instruction} applies
|
|
8
|
+
#
|
|
9
|
+
# @return [Symbol]
|
|
10
|
+
attr_reader :segment_id
|
|
11
|
+
|
|
12
|
+
# The segment use contains helpful information about the context of the
|
|
13
|
+
# segment within a definition tree (eg the parent structure's definition).
|
|
14
|
+
# It also enumerates the allowed values for segment qualifiers, which is
|
|
15
|
+
# used to minimize non-determinism.
|
|
16
|
+
#
|
|
17
|
+
# @return [Schema::SegmentUse]
|
|
18
|
+
attr_reader :segment_use
|
|
19
|
+
|
|
20
|
+
# This indicates the number of levels to ascend and terminate within the
|
|
21
|
+
# tree before storing the segment.
|
|
22
|
+
#
|
|
23
|
+
# @return [Integer]
|
|
24
|
+
attr_reader :pop_count
|
|
25
|
+
|
|
26
|
+
# This controls the allowed order in which structures may occur, by
|
|
27
|
+
# indicating the number of instructions to remove from the beginning of
|
|
28
|
+
# the instruction table.
|
|
29
|
+
#
|
|
30
|
+
# Repeatable structures have a value that ensures that their instruction
|
|
31
|
+
# remains in the successor table.
|
|
32
|
+
#
|
|
33
|
+
# Sibling structures that have the same position (as defined by their
|
|
34
|
+
# {Schema::SegmentUse}) will have equal drop_count values such that all of
|
|
35
|
+
# the sibling instructions remain in the successor table when any one of
|
|
36
|
+
# them is executed.
|
|
37
|
+
#
|
|
38
|
+
# @return [Integer]
|
|
39
|
+
attr_reader :drop_count
|
|
40
|
+
|
|
41
|
+
# This indicates that a child node should be added to the tree, which
|
|
42
|
+
# will then contain the segment.
|
|
43
|
+
#
|
|
44
|
+
# When a segment indicates the start of a child structure, the class
|
|
45
|
+
# indicated by this attribute is expected to respond to `push` by
|
|
46
|
+
# creating a new {AbstractState}.
|
|
47
|
+
#
|
|
48
|
+
# @return [Zipper::AbstractCursor]
|
|
49
|
+
attr_reader :push
|
|
50
|
+
|
|
51
|
+
def initialize(segment_id, segment_use, pop, drop, push)
|
|
52
|
+
@segment_id, @segment_use, @pop_count, @drop_count, @push =
|
|
53
|
+
segment_id || segment_use.definition.id, segment_use, pop, drop, push
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [Instruction]
|
|
57
|
+
def copy(changes = {})
|
|
58
|
+
Instruction.new \
|
|
59
|
+
changes.fetch(:segment_id, @segment_id),
|
|
60
|
+
changes.fetch(:segment_use, @segment_use),
|
|
61
|
+
changes.fetch(:pop_count, @pop_count),
|
|
62
|
+
changes.fetch(:drop_count, @drop_count),
|
|
63
|
+
changes.fetch(:push, @push)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [void]
|
|
67
|
+
def pretty_print(q)
|
|
68
|
+
id = '% 3s' % @segment_id.to_s
|
|
69
|
+
|
|
70
|
+
unless @segment_use.nil?
|
|
71
|
+
width = 18
|
|
72
|
+
name = @segment_use.definition.name
|
|
73
|
+
|
|
74
|
+
# Truncate the segment name to `width` characters
|
|
75
|
+
if name.length > width - 2
|
|
76
|
+
id << ": #{name.slice(0, width - 2)}.."
|
|
77
|
+
else
|
|
78
|
+
id << ": #{name.ljust(width)}"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
q.text "Instruction[#{'% 3s' % id}]"
|
|
83
|
+
|
|
84
|
+
q.group(6, "(", ")") do
|
|
85
|
+
q.breakable ""
|
|
86
|
+
|
|
87
|
+
q.text "pop: #{@pop_count},"
|
|
88
|
+
q.breakable
|
|
89
|
+
|
|
90
|
+
q.text "drop: #{@drop_count}"
|
|
91
|
+
|
|
92
|
+
unless @push.nil?
|
|
93
|
+
q.text ","
|
|
94
|
+
q.breakable
|
|
95
|
+
q.text "push: #{@push.try{|c| c.name.split('::').last}}"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|