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,655 @@
|
|
|
1
|
+
module Stupidedi
|
|
2
|
+
module Builder
|
|
3
|
+
|
|
4
|
+
module Navigation
|
|
5
|
+
|
|
6
|
+
# @group Querying the Current Position
|
|
7
|
+
#########################################################################
|
|
8
|
+
|
|
9
|
+
# @return [Array<InstructionTable>]
|
|
10
|
+
def successors
|
|
11
|
+
@active.map{|a| a.node.instructions }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Is there exactly one valid parse tree in the current state?
|
|
15
|
+
def deterministic?
|
|
16
|
+
@active.length == 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def empty?
|
|
20
|
+
value = @active.head.node.zipper
|
|
21
|
+
|
|
22
|
+
until value.root?
|
|
23
|
+
value = value.up
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
value.node.children.empty?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Is this the first segment?
|
|
30
|
+
def first?
|
|
31
|
+
value = @active.head.node.zipper
|
|
32
|
+
|
|
33
|
+
until value.root?
|
|
34
|
+
return false unless value.first?
|
|
35
|
+
value = value.up
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Is this the last segment?
|
|
42
|
+
def last?
|
|
43
|
+
value = @active.head.node.zipper
|
|
44
|
+
|
|
45
|
+
until value.root?
|
|
46
|
+
return false unless value.last?
|
|
47
|
+
value = value.up
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
return true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns the number of segments apart the current state is from the
|
|
54
|
+
# given `StateMachine`'s state. Note the direction is not indicated by
|
|
55
|
+
# the return value, so `a.distance(b) == b.distance(a)` for all states
|
|
56
|
+
# `a` and `b`.
|
|
57
|
+
#
|
|
58
|
+
# @example
|
|
59
|
+
# m.distance(m) #=> Either.success(0)
|
|
60
|
+
# m.next(10).flatmap{|n| n.distance(m) } #=> Either.success(10)
|
|
61
|
+
#
|
|
62
|
+
# @return [Either<Integer>]
|
|
63
|
+
#
|
|
64
|
+
# @note This method uses AbstractCursor#between, which assumes the two
|
|
65
|
+
# cursors point to the same tree. If that is not the case, the results
|
|
66
|
+
# are undefined.
|
|
67
|
+
def distance(other)
|
|
68
|
+
zipper.flatmap do |a|
|
|
69
|
+
other.zipper.map do |b|
|
|
70
|
+
a.between(b).count(&:segment?) - 1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @group Accessing the Current Node
|
|
76
|
+
#########################################################################
|
|
77
|
+
|
|
78
|
+
# Returns the current position within the parse tree, if the current state
|
|
79
|
+
# is deterministic.
|
|
80
|
+
#
|
|
81
|
+
# @return [Either<Zipper::AbstractCursor<Values::AbstractVal>>]
|
|
82
|
+
def zipper
|
|
83
|
+
if deterministic?
|
|
84
|
+
Either.success(@active.head.node.zipper)
|
|
85
|
+
else
|
|
86
|
+
Either.failure("non-deterministic state")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Extracts the segment from the current state, if the current state is
|
|
91
|
+
# deterministic and positioned on a segment.
|
|
92
|
+
#
|
|
93
|
+
# @return [Either<Zipper::AbstractCursor<Values::SegmentVal>>]
|
|
94
|
+
def segment
|
|
95
|
+
zipper.flatmap do |z|
|
|
96
|
+
if z.node.segment?
|
|
97
|
+
Either.success(z)
|
|
98
|
+
else
|
|
99
|
+
Either.failure("not a segment")
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Extracts the *mth* element from the current segment, if the current
|
|
105
|
+
# state is deterministic. Accepts optional arguments to extract a specific
|
|
106
|
+
# occurrence of a repeated element and/or a specific component from a
|
|
107
|
+
# composite element.
|
|
108
|
+
#
|
|
109
|
+
# @return [Either<Zipper::AbstractCursor<Values::AbstractElementVal>>]
|
|
110
|
+
def element(m, n = nil, o = nil)
|
|
111
|
+
segment.flatmap do |s|
|
|
112
|
+
unless m >= 1
|
|
113
|
+
raise ArgumentError,
|
|
114
|
+
"argument must be positive"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if s.node.invalid?
|
|
118
|
+
# InvalidSegmentVal doesn't have child AbstractElementVals, its
|
|
119
|
+
# children are SimpleElementTok, CompositeElementTok, etc, which
|
|
120
|
+
# are not parsed values.
|
|
121
|
+
return Either.failure("invalid segment")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
designator = s.node.id.to_s
|
|
125
|
+
definition = s.node.definition
|
|
126
|
+
length = definition.element_uses.length
|
|
127
|
+
|
|
128
|
+
unless m <= length
|
|
129
|
+
raise ArgumentError,
|
|
130
|
+
"#{designator} segment has only #{length} elements"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
designator << "%02d" % m
|
|
134
|
+
value = s.child(m - 1)
|
|
135
|
+
|
|
136
|
+
if n.nil?
|
|
137
|
+
return Either.success(value)
|
|
138
|
+
elsif value.node.repeated?
|
|
139
|
+
unless n >= 1
|
|
140
|
+
raise ArgumentError,
|
|
141
|
+
"argument must be positive"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
limit = value.node.definition.repeat_count
|
|
145
|
+
unless limit.include?(n)
|
|
146
|
+
raise ArgumentError,
|
|
147
|
+
"#{designator} can only occur #{limit.max} times"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
unless value.node.children.defined_at?(n - 1)
|
|
151
|
+
return Either.failure("#{designator} occurs only #{value.node.children.length} times")
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
value = value.child(n - 1)
|
|
155
|
+
n, o = o, nil
|
|
156
|
+
|
|
157
|
+
return Either.success(value) if n.nil?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
unless value.node.composite?
|
|
161
|
+
raise ArgumentError,
|
|
162
|
+
"#{designator} is a simple element"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
unless o.nil?
|
|
166
|
+
raise ArgumentError,
|
|
167
|
+
"#{designator} is a non-repeatable composite element"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
unless n >= 1
|
|
171
|
+
raise ArgumentError,
|
|
172
|
+
"argument must be positive"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
length = definition.element_uses.at(m - 1).definition.component_uses.length
|
|
176
|
+
unless n <= length
|
|
177
|
+
raise ArgumentError,
|
|
178
|
+
"#{designator} has only #{length} components"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if value.node.empty?
|
|
182
|
+
Either.failure("#{designator} is empty")
|
|
183
|
+
else
|
|
184
|
+
Either.success(value.child(n - 1))
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# @group Navigating the Tree
|
|
190
|
+
#########################################################################
|
|
191
|
+
|
|
192
|
+
# Returns a new `StateMachine` positioned on the first segment in
|
|
193
|
+
# the parse tree, if there are any segments in the parse tree.
|
|
194
|
+
#
|
|
195
|
+
# @return [Either<StateMachine>]
|
|
196
|
+
def first
|
|
197
|
+
active = roots.map do |zipper|
|
|
198
|
+
state = zipper
|
|
199
|
+
value = zipper.node.zipper
|
|
200
|
+
|
|
201
|
+
until value.node.segment? or value.leaf?
|
|
202
|
+
value = value.down
|
|
203
|
+
state = state.down
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
unless value.node.segment?
|
|
207
|
+
return Either.failure("no segments")
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Synchronize the two parallel state and value nodes
|
|
211
|
+
unless value.eql?(state.node.zipper)
|
|
212
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
state
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
Either.success(StateMachine.new(@config, active))
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Returns a new `StateMachine` positioned on the last segment in
|
|
222
|
+
# the parse tree, if there are any segments in the parse tree.
|
|
223
|
+
#
|
|
224
|
+
# @return [Either<StateMachine>]
|
|
225
|
+
def last
|
|
226
|
+
active = roots.map do |zipper|
|
|
227
|
+
state = zipper
|
|
228
|
+
value = zipper.node.zipper
|
|
229
|
+
|
|
230
|
+
until value.node.segment? or value.leaf?
|
|
231
|
+
value = value.down.last
|
|
232
|
+
state = state.down.last
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
unless value.node.segment?
|
|
236
|
+
return Either.failure("no segments")
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Synchronize the two parallel state and value nodes
|
|
240
|
+
unless value.eql?(state.node.zipper)
|
|
241
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
state
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
Either.success(StateMachine.new(@config, active))
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Returns a new `StateMachine` positioned on the first segment of the
|
|
251
|
+
# parent structure. For example, when the current segment belongs to a
|
|
252
|
+
# loop but it's not the first segment in that loop, this method will
|
|
253
|
+
# rewind to the first segment in the loop. If the current position is
|
|
254
|
+
# the first segment of a loop, this method will rewind to the first
|
|
255
|
+
# segment in the loop's parent structure.
|
|
256
|
+
#
|
|
257
|
+
# @return [Either<StateMachine>]
|
|
258
|
+
def parent
|
|
259
|
+
active = []
|
|
260
|
+
|
|
261
|
+
@active.each do |zipper|
|
|
262
|
+
state = zipper
|
|
263
|
+
value = zipper.node.zipper
|
|
264
|
+
|
|
265
|
+
while value.first? and not value.root?
|
|
266
|
+
value = value.up
|
|
267
|
+
state = state.up
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
if value.root?
|
|
271
|
+
break
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
value = value.first
|
|
275
|
+
state = state.first
|
|
276
|
+
|
|
277
|
+
until value.node.segment?
|
|
278
|
+
value = value.down
|
|
279
|
+
state = state.down
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Synchronize the two parallel state and value nodes
|
|
283
|
+
unless value.eql?(state.node.zipper)
|
|
284
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
active << state
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
if active.empty?
|
|
291
|
+
Either.failure("no parent segment")
|
|
292
|
+
else
|
|
293
|
+
Either.success(StateMachine.new(@config, active))
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Returns a new `StateMachine` positioned on the next segment, if
|
|
298
|
+
# there is a next segment. Optionally, a `count` argument may be
|
|
299
|
+
# provided that indicates how many segments to advance.
|
|
300
|
+
#
|
|
301
|
+
# @return [StateMachine]
|
|
302
|
+
def next(count = 1)
|
|
303
|
+
unless count > 0
|
|
304
|
+
raise ArgumentError,
|
|
305
|
+
"count must be positive"
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
active = @active.map do |zipper|
|
|
309
|
+
state = zipper
|
|
310
|
+
value = zipper.node.zipper
|
|
311
|
+
|
|
312
|
+
count.times do
|
|
313
|
+
while not value.root? and value.last?
|
|
314
|
+
value = value.up
|
|
315
|
+
state = state.up
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
if value.root?
|
|
319
|
+
return Either.failure("cannot move to next after last segment")
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
value = value.next
|
|
323
|
+
state = state.next
|
|
324
|
+
|
|
325
|
+
until value.node.segment?
|
|
326
|
+
value = value.down
|
|
327
|
+
state = state.down
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Synchronize the two parallel state and value nodes
|
|
332
|
+
unless value.eql?(state.node.zipper)
|
|
333
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
state
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
Either.success(StateMachine.new(@config, active))
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Returns a new `StateMachine` positioned on the previous segment, if
|
|
343
|
+
# there is a previous segment. Optionally, a `count` argument may be
|
|
344
|
+
# provided that indicates how many segments to rewind.
|
|
345
|
+
#
|
|
346
|
+
# @return [Either<StateMachine>]
|
|
347
|
+
def prev(count = 1)
|
|
348
|
+
unless count > 0
|
|
349
|
+
raise ArgumentError,
|
|
350
|
+
"count must be positive"
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
active = @active.map do |zipper|
|
|
354
|
+
state = zipper
|
|
355
|
+
value = zipper.node.zipper
|
|
356
|
+
|
|
357
|
+
count.times do
|
|
358
|
+
while not value.root? and value.first?
|
|
359
|
+
value = value.up
|
|
360
|
+
state = state.up
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
if value.root?
|
|
364
|
+
return Either.failure("cannot move to prev before first segment")
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
state = state.prev
|
|
368
|
+
value = value.prev
|
|
369
|
+
|
|
370
|
+
until value.node.segment?
|
|
371
|
+
value = value.down.last
|
|
372
|
+
state = state.down.last
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Synchronize the two parallel state and value nodes
|
|
377
|
+
unless value.eql?(state.node.zipper)
|
|
378
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
state
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
Either.success(StateMachine.new(@config, active))
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Returns a `StateMachine` positioned on the next matching segment,
|
|
388
|
+
# excluding {InvalidSegmentVal}s, that satisfies the given element
|
|
389
|
+
# constraints. The search space is limited to certain related elements
|
|
390
|
+
# described in [Navigating.md]
|
|
391
|
+
#
|
|
392
|
+
# @example
|
|
393
|
+
# machine.find(:ST, nil, nil, "005010X222")
|
|
394
|
+
#
|
|
395
|
+
# @return [Either<StateMachine>]
|
|
396
|
+
def find(id, *elements)
|
|
397
|
+
__find(false, id, elements)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Returns a `StateMachine` positioned on the next matching segment,
|
|
401
|
+
# including {InvalidSegmentVal}s, that satisfies the given element
|
|
402
|
+
# constraints. The search space is limited to certain related elements
|
|
403
|
+
# described in [Navigating.md]
|
|
404
|
+
#
|
|
405
|
+
# @example
|
|
406
|
+
# machine.find!(:ST, nil, nil, "005010X222")
|
|
407
|
+
#
|
|
408
|
+
# @return [Either<StateMachine>]
|
|
409
|
+
def find!(id, *elements)
|
|
410
|
+
__find(true, id, elements)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# @return [Integer]
|
|
414
|
+
def count(id, *elements)
|
|
415
|
+
__count(false, id, elements)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
# @return [Integer]
|
|
419
|
+
def count!(id, *elements)
|
|
420
|
+
__count(true, id, elements)
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def iterate(id, *elements)
|
|
424
|
+
m = find(id, *elements)
|
|
425
|
+
while m.defined?
|
|
426
|
+
m = m.flatmap do |n|
|
|
427
|
+
yield(n)
|
|
428
|
+
n.find(id, *elements)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
private
|
|
434
|
+
|
|
435
|
+
# @return [Either<StateMachine>]
|
|
436
|
+
def __find(invalid, id, elements)
|
|
437
|
+
reachable = false
|
|
438
|
+
matches = []
|
|
439
|
+
|
|
440
|
+
@active.each do |zipper|
|
|
441
|
+
matched = false
|
|
442
|
+
filter_tok = mksegment_tok(zipper.node.segment_dict, id, elements, nil)
|
|
443
|
+
|
|
444
|
+
instructions = zipper.node.instructions.matches(filter_tok, true)
|
|
445
|
+
reachable ||= !instructions.empty?
|
|
446
|
+
|
|
447
|
+
instructions.each do |op|
|
|
448
|
+
break if matched
|
|
449
|
+
|
|
450
|
+
# Every transition follows the same shape
|
|
451
|
+
# 1. Move upward a number of nodes
|
|
452
|
+
# 2. Move left a number of nodes
|
|
453
|
+
# 3. Move downward a number of nodes
|
|
454
|
+
# 4. Stop on a segment
|
|
455
|
+
|
|
456
|
+
state = zipper
|
|
457
|
+
value = zipper.node.zipper
|
|
458
|
+
|
|
459
|
+
# 1. Move upward (possibly zero times)
|
|
460
|
+
op.pop_count.times do
|
|
461
|
+
value = value.up
|
|
462
|
+
state = state.up
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# 2. We know from the instruction `op` the *maximum* number of
|
|
466
|
+
# nodes to move left, but not exactly how many. Instead, we
|
|
467
|
+
# know what the InstructionTable is when we get there.
|
|
468
|
+
target = zipper.node.instructions.pop(op.pop_count).drop(op.drop_count)
|
|
469
|
+
|
|
470
|
+
until state.last?
|
|
471
|
+
state = state.next
|
|
472
|
+
value = value.next
|
|
473
|
+
|
|
474
|
+
# 2. Even if the InstructionTable matches, we still need to
|
|
475
|
+
# descend to some segment and compare it to the criteria. In
|
|
476
|
+
# most circumstances, this segment is directly below this
|
|
477
|
+
if target.eql?(state.node.instructions)
|
|
478
|
+
|
|
479
|
+
# 3. Move downward a number of nodes. Ultimately, we need to
|
|
480
|
+
# descend to a segment, but we have to be careful...
|
|
481
|
+
_value = value
|
|
482
|
+
_state = state
|
|
483
|
+
|
|
484
|
+
# 3. If the segment we're searching for belongs in a new subtree,
|
|
485
|
+
# but it's not the only segment that might have "opened" that
|
|
486
|
+
# subtree (eg, Summary Table in 835 can begin with PLB or SE)
|
|
487
|
+
# then maybe the segment we're looking for comes *after* the
|
|
488
|
+
# first segment in this subtree.
|
|
489
|
+
single = op.push.nil?
|
|
490
|
+
single ||= op.segment_use.nil?
|
|
491
|
+
single ||= 1 >= zipper.node.instructions.instructions.count do |x|
|
|
492
|
+
x.push.present? and
|
|
493
|
+
(# This is hairy, but we know the instruction is pushing some
|
|
494
|
+
# number of nested subtrees. We know from each AbstractState
|
|
495
|
+
# subclass that we both either push a single subtree
|
|
496
|
+
op.segment_use.parent.eql?(x.segment_use.try(:parent)) or
|
|
497
|
+
# Or this instruction pushes one subtree while the other one
|
|
498
|
+
# pushes two (eg, a new loop inside of a table)
|
|
499
|
+
op.segment_use.parent.eql?(x.segment_use.try(:parent).try(:parent)) or
|
|
500
|
+
# Or this instruction pushes two subtrees (eg, a new loop in
|
|
501
|
+
# a new table) and the other also pushes two subtrees.
|
|
502
|
+
op.segment_use.parent.parent.eql?(x.segment_use.try(:parent)))
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
unless _value.node.segment?
|
|
506
|
+
_value = _value.down
|
|
507
|
+
_state = _state.down
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
while true
|
|
511
|
+
__value = _value
|
|
512
|
+
__state = _state
|
|
513
|
+
|
|
514
|
+
# Descend to the first segment
|
|
515
|
+
until __value.node.segment?
|
|
516
|
+
__value = __value.down
|
|
517
|
+
__state = __state.down
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
matched =
|
|
521
|
+
if __value.node.invalid?
|
|
522
|
+
invalid and not __filter?(filter_tok, __value.node)
|
|
523
|
+
else
|
|
524
|
+
# Note op.segment_use.nil? is true when searching for ISA,
|
|
525
|
+
# GS, and ST, because we can't know the SegmentUse until we
|
|
526
|
+
# deconstruct the token and looked up the versions numbers
|
|
527
|
+
# in the Config.
|
|
528
|
+
(op.segment_use.nil? or op.segment_use.eql?(__value.node.usage)) \
|
|
529
|
+
and not filter?(filter_tok, __value.node)
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
# 4. Stop on a segment
|
|
533
|
+
if matched
|
|
534
|
+
unless __value.eql?(__state.node.zipper)
|
|
535
|
+
__state = __state.replace(__state.node.copy(:zipper => __value))
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
matches << __state
|
|
539
|
+
break
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
break if single
|
|
543
|
+
break if _value.last?
|
|
544
|
+
|
|
545
|
+
_value = _value.next
|
|
546
|
+
_state = _state.next
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
# 4. Stop on a segment
|
|
550
|
+
break if matched
|
|
551
|
+
|
|
552
|
+
elsif target.length > state.node.instructions.length
|
|
553
|
+
# The ancestor state can't be one of the rightward siblings,
|
|
554
|
+
# since the length of instruction tables is non-increasing as
|
|
555
|
+
# we move rightward
|
|
556
|
+
break
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
if not reachable
|
|
563
|
+
raise Exceptions::ParseError,
|
|
564
|
+
"#{id} segment cannot be reached from the current state"
|
|
565
|
+
elsif matches.empty?
|
|
566
|
+
Either.failure("#{id}(#{elements.map(&:inspect).join(", ")}) segment does not occur")
|
|
567
|
+
else
|
|
568
|
+
Either.success(StateMachine.new(@config, matches))
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
# Returns true if the constraints modeled in `filter_tok` are not
|
|
573
|
+
# satisfied by the given `segment_val`, otherwise returns false.
|
|
574
|
+
def filter?(filter_tok, segment_val)
|
|
575
|
+
return true unless filter_tok.id == segment_val.id
|
|
576
|
+
|
|
577
|
+
filter_tok.element_toks.zip(segment_val.children) do |f_tok, e_val|
|
|
578
|
+
if f_tok.simple?
|
|
579
|
+
return true unless f_tok.blank? or e_val == f_tok.value
|
|
580
|
+
elsif f_tok.composite?
|
|
581
|
+
f_tok.component_toks.zip(e_val.children) do |c_tok, c_val|
|
|
582
|
+
return true unless c_tok.blank? or c_val == c_tok.value
|
|
583
|
+
end
|
|
584
|
+
elsif f_tok.present?
|
|
585
|
+
raise Exceptions::ParseError,
|
|
586
|
+
"only simple and component elements can be filtered"
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
false
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
# Returns true if the constraints modeled in `filter_tok` are not
|
|
594
|
+
# satisfied by the given `invalid_val`, otherwise returns false.
|
|
595
|
+
def __filter?(filter_tok, invalid_val)
|
|
596
|
+
return true unless filter_tok.id == invalid_val.id
|
|
597
|
+
|
|
598
|
+
children = invalid_val.segment_tok.element_toks
|
|
599
|
+
filter_tok.element_toks.zip(children) do |f_tok, e_tok|
|
|
600
|
+
if f_tok.simple?
|
|
601
|
+
return true unless f_tok.blank? or f_tok.value == e_tok.value
|
|
602
|
+
elsif f_tok.composite?
|
|
603
|
+
children = e_tok.component_toks
|
|
604
|
+
f_tok.component_toks.zip(children) do |f_com, e_com|
|
|
605
|
+
return true unless f_com.blank? or f_com.value == e_com.value
|
|
606
|
+
end
|
|
607
|
+
elsif f_tok.present?
|
|
608
|
+
raise Exceptions::ParseError,
|
|
609
|
+
"only simple and component elements can be filtered"
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
false
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
# @return [Integer]
|
|
617
|
+
def __count(invalid, id, elements)
|
|
618
|
+
cursor = __find(invalid, id, elements)
|
|
619
|
+
count = 0
|
|
620
|
+
|
|
621
|
+
while cursor.defined?
|
|
622
|
+
count += 1
|
|
623
|
+
cursor = cursor.flatmap{|c| c.send(:__find, invalid, id, elements) }
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
count
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
# Returns the cursor positioned at the root of the parse tree linked
|
|
630
|
+
# from each state.
|
|
631
|
+
#
|
|
632
|
+
# @return [Array<Zipper::RootCursor>]
|
|
633
|
+
def roots
|
|
634
|
+
@active.map do |zipper|
|
|
635
|
+
state = zipper
|
|
636
|
+
value = zipper.node.zipper
|
|
637
|
+
|
|
638
|
+
zipper.depth.times do
|
|
639
|
+
value = value.up
|
|
640
|
+
state = state.up
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
# Synchronize the two parallel state and value nodes
|
|
644
|
+
unless value.eql?(state.node.zipper)
|
|
645
|
+
state = state.replace(state.node.copy(:zipper => value))
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
state
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
end
|
|
655
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Stupidedi
|
|
2
|
+
module Builder
|
|
3
|
+
|
|
4
|
+
class StateMachine
|
|
5
|
+
include Inspect
|
|
6
|
+
include Navigation
|
|
7
|
+
include Generation
|
|
8
|
+
include Tokenization
|
|
9
|
+
|
|
10
|
+
# @return [Config]
|
|
11
|
+
attr_reader :config
|
|
12
|
+
|
|
13
|
+
# @return [Array<Zipper::AbstractCursor>]
|
|
14
|
+
attr_reader :active
|
|
15
|
+
|
|
16
|
+
def initialize(config, active)
|
|
17
|
+
@config, @active = config, active
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [Reader::Separators]
|
|
21
|
+
def separators
|
|
22
|
+
@active.head.node.separators
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [void]
|
|
26
|
+
def pretty_print(q)
|
|
27
|
+
q.text "StateMachine[#{@active.length}]"
|
|
28
|
+
q.group 2, "(", ")" do
|
|
29
|
+
q.breakable ""
|
|
30
|
+
@active.each do |s|
|
|
31
|
+
unless q.current_group.first?
|
|
32
|
+
q.text ","
|
|
33
|
+
q.breakable
|
|
34
|
+
end
|
|
35
|
+
q.pp s.node.zipper.node
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class << StateMachine
|
|
42
|
+
# @group Constructors
|
|
43
|
+
#########################################################################
|
|
44
|
+
|
|
45
|
+
# @return [StateMachine]
|
|
46
|
+
def build(config)
|
|
47
|
+
StateMachine.new(config, InitialState.start.cons)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @endgroup
|
|
51
|
+
#########################################################################
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|