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.
Files changed (500) hide show
  1. data/README.md +215 -0
  2. data/Rakefile +108 -0
  3. data/bin/edi-ed +71 -0
  4. data/bin/edi-pp +81 -0
  5. data/doc/Defining.md +0 -0
  6. data/doc/Generating.md +321 -0
  7. data/doc/LICENSE.md +0 -0
  8. data/doc/Navigating.md +645 -0
  9. data/doc/Parsing.md +0 -0
  10. data/doc/Serializing.md +7 -0
  11. data/doc/Tokenizing.md +0 -0
  12. data/doc/Validating.md +0 -0
  13. data/doc/design/Parser.md +0 -0
  14. data/doc/design/Reader.md +0 -0
  15. data/lib/ruby/array.rb +164 -0
  16. data/lib/ruby/blank.rb +67 -0
  17. data/lib/ruby/enumerable.rb +35 -0
  18. data/lib/ruby/exception.rb +33 -0
  19. data/lib/ruby/hash.rb +4 -0
  20. data/lib/ruby/instance_exec.rb +26 -0
  21. data/lib/ruby/module.rb +79 -0
  22. data/lib/ruby/object.rb +63 -0
  23. data/lib/ruby/string.rb +73 -0
  24. data/lib/ruby/symbol.rb +24 -0
  25. data/lib/ruby/to_d.rb +81 -0
  26. data/lib/ruby/to_date.rb +33 -0
  27. data/lib/ruby/to_time.rb +24 -0
  28. data/lib/ruby/try.rb +43 -0
  29. data/lib/stupidedi/blank_slate.rb +11 -0
  30. data/lib/stupidedi/builder/builder_dsl.rb +281 -0
  31. data/lib/stupidedi/builder/constraint_table.rb +418 -0
  32. data/lib/stupidedi/builder/generation.rb +112 -0
  33. data/lib/stupidedi/builder/instruction.rb +102 -0
  34. data/lib/stupidedi/builder/instruction_table.rb +204 -0
  35. data/lib/stupidedi/builder/navigation.rb +655 -0
  36. data/lib/stupidedi/builder/state_machine.rb +55 -0
  37. data/lib/stupidedi/builder/states/abstract_state.rb +332 -0
  38. data/lib/stupidedi/builder/states/failure_state.rb +69 -0
  39. data/lib/stupidedi/builder/states/functional_group_state.rb +97 -0
  40. data/lib/stupidedi/builder/states/initial_state.rb +63 -0
  41. data/lib/stupidedi/builder/states/interchange_state.rb +94 -0
  42. data/lib/stupidedi/builder/states/loop_state.rb +79 -0
  43. data/lib/stupidedi/builder/states/table_state.rb +96 -0
  44. data/lib/stupidedi/builder/states/transaction_set_state.rb +112 -0
  45. data/lib/stupidedi/builder/states/transmission_state.rb +59 -0
  46. data/lib/stupidedi/builder/tokenization.rb +196 -0
  47. data/lib/stupidedi/builder.rb +23 -0
  48. data/lib/stupidedi/color.rb +93 -0
  49. data/lib/stupidedi/config/code_list_config.rb +42 -0
  50. data/lib/stupidedi/config/editor_config.rb +51 -0
  51. data/lib/stupidedi/config/functional_group_config.rb +62 -0
  52. data/lib/stupidedi/config/interchange_config.rb +79 -0
  53. data/lib/stupidedi/config/transaction_set_config.rb +91 -0
  54. data/lib/stupidedi/config.rb +101 -0
  55. data/lib/stupidedi/editor/00501.rb +341 -0
  56. data/lib/stupidedi/editor/005010/N2.rb +0 -0
  57. data/lib/stupidedi/editor/005010/N3.rb +0 -0
  58. data/lib/stupidedi/editor/005010/N4.rb +63 -0
  59. data/lib/stupidedi/editor/005010/NM1.rb +0 -0
  60. data/lib/stupidedi/editor/005010.rb +469 -0
  61. data/lib/stupidedi/editor/X222-HC837.rb +195 -0
  62. data/lib/stupidedi/editor/abstract_ed.rb +36 -0
  63. data/lib/stupidedi/editor/claim_ack.rb +9 -0
  64. data/lib/stupidedi/editor/implementation_ack.rb +213 -0
  65. data/lib/stupidedi/editor/interchange_ack.rb +9 -0
  66. data/lib/stupidedi/editor/result.rb +100 -0
  67. data/lib/stupidedi/editor/result_set.rb +69 -0
  68. data/lib/stupidedi/editor/transaction_set_ed.rb +275 -0
  69. data/lib/stupidedi/editor/transmission_ed.rb +90 -0
  70. data/lib/stupidedi/editor.rb +37 -0
  71. data/lib/stupidedi/either.rb +287 -0
  72. data/lib/stupidedi/exceptions/invalid_element_error.rb +8 -0
  73. data/lib/stupidedi/exceptions/invalid_schema_error.rb +8 -0
  74. data/lib/stupidedi/exceptions/output_error.rb +8 -0
  75. data/lib/stupidedi/exceptions/parse_error.rb +8 -0
  76. data/lib/stupidedi/exceptions/stupidedi_error.rb +8 -0
  77. data/lib/stupidedi/exceptions/tokenize_error.rb +8 -0
  78. data/lib/stupidedi/exceptions/zipper_error.rb +8 -0
  79. data/lib/stupidedi/exceptions.rb +11 -0
  80. data/lib/stupidedi/guides/005010/X214-HN277.rb +409 -0
  81. data/lib/stupidedi/guides/005010/X221-HP835.rb +613 -0
  82. data/lib/stupidedi/guides/005010/X221A1-HP835.rb +613 -0
  83. data/lib/stupidedi/guides/005010/X222-HC837P.rb +2291 -0
  84. data/lib/stupidedi/guides/005010/X222A1-HC837P.rb +2297 -0
  85. data/lib/stupidedi/guides/005010/X231-FA999.rb +123 -0
  86. data/lib/stupidedi/guides/005010/X231A1-FA999.rb +119 -0
  87. data/lib/stupidedi/guides/005010/element_reqs.rb +38 -0
  88. data/lib/stupidedi/guides/005010/guide_builder.rb +180 -0
  89. data/lib/stupidedi/guides/005010/segment_reqs.rb +32 -0
  90. data/lib/stupidedi/guides/005010.rb +64 -0
  91. data/lib/stupidedi/guides.rb +5 -0
  92. data/lib/stupidedi/inspect.rb +26 -0
  93. data/lib/stupidedi/reader/input/abstract_input.rb +133 -0
  94. data/lib/stupidedi/reader/input/delegated_input.rb +111 -0
  95. data/lib/stupidedi/reader/input/file_input.rb +155 -0
  96. data/lib/stupidedi/reader/input.rb +30 -0
  97. data/lib/stupidedi/reader/position.rb +69 -0
  98. data/lib/stupidedi/reader/result.rb +168 -0
  99. data/lib/stupidedi/reader/segment_dict.rb +175 -0
  100. data/lib/stupidedi/reader/separators.rb +85 -0
  101. data/lib/stupidedi/reader/stream_reader.rb +172 -0
  102. data/lib/stupidedi/reader/token_reader.rb +466 -0
  103. data/lib/stupidedi/reader/tokens/component_element_tok.rb +56 -0
  104. data/lib/stupidedi/reader/tokens/composite_element_tok.rb +64 -0
  105. data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +64 -0
  106. data/lib/stupidedi/reader/tokens/segment_tok.rb +51 -0
  107. data/lib/stupidedi/reader/tokens/simple_element_tok.rb +63 -0
  108. data/lib/stupidedi/reader.rb +121 -0
  109. data/lib/stupidedi/schema/abstract_def.rb +74 -0
  110. data/lib/stupidedi/schema/abstract_use.rb +73 -0
  111. data/lib/stupidedi/schema/code_list.rb +94 -0
  112. data/lib/stupidedi/schema/element_def.rb +173 -0
  113. data/lib/stupidedi/schema/element_req.rb +56 -0
  114. data/lib/stupidedi/schema/element_use.rb +251 -0
  115. data/lib/stupidedi/schema/functional_group_def.rb +114 -0
  116. data/lib/stupidedi/schema/interchange_def.rb +93 -0
  117. data/lib/stupidedi/schema/loop_def.rb +152 -0
  118. data/lib/stupidedi/schema/repeat_count.rb +85 -0
  119. data/lib/stupidedi/schema/segment_def.rb +108 -0
  120. data/lib/stupidedi/schema/segment_req.rb +43 -0
  121. data/lib/stupidedi/schema/segment_use.rb +98 -0
  122. data/lib/stupidedi/schema/syntax_note.rb +63 -0
  123. data/lib/stupidedi/schema/table_def.rb +139 -0
  124. data/lib/stupidedi/schema/transaction_set_def.rb +88 -0
  125. data/lib/stupidedi/schema.rb +28 -0
  126. data/lib/stupidedi/sets/absolute_set.rb +297 -0
  127. data/lib/stupidedi/sets/abstract_set.rb +174 -0
  128. data/lib/stupidedi/sets/null_set.rb +125 -0
  129. data/lib/stupidedi/sets/relative_complement.rb +137 -0
  130. data/lib/stupidedi/sets/relative_set.rb +269 -0
  131. data/lib/stupidedi/sets/universal_set.rb +104 -0
  132. data/lib/stupidedi/sets.rb +57 -0
  133. data/lib/stupidedi/tail_call.rb +109 -0
  134. data/lib/stupidedi/thread_local.rb +174 -0
  135. data/lib/stupidedi/values/abstract_element_val.rb +19 -0
  136. data/lib/stupidedi/values/abstract_val.rb +130 -0
  137. data/lib/stupidedi/values/composite_element_val.rb +95 -0
  138. data/lib/stupidedi/values/functional_group_val.rb +102 -0
  139. data/lib/stupidedi/values/interchange_val.rb +86 -0
  140. data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
  141. data/lib/stupidedi/values/invalid_segment_val.rb +78 -0
  142. data/lib/stupidedi/values/loop_val.rb +70 -0
  143. data/lib/stupidedi/values/repeated_element_val.rb +105 -0
  144. data/lib/stupidedi/values/segment_val.rb +104 -0
  145. data/lib/stupidedi/values/segment_val_group.rb +20 -0
  146. data/lib/stupidedi/values/simple_element_val.rb +80 -0
  147. data/lib/stupidedi/values/table_val.rb +66 -0
  148. data/lib/stupidedi/values/transaction_set_val.rb +66 -0
  149. data/lib/stupidedi/values/transmission_val.rb +52 -0
  150. data/lib/stupidedi/values.rb +21 -0
  151. data/lib/stupidedi/version.rb +3 -0
  152. data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +54 -0
  153. data/lib/stupidedi/versions/functional_groups/004010/element_reqs.rb +18 -0
  154. data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +527 -0
  155. data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +335 -0
  156. data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +299 -0
  157. data/lib/stupidedi/versions/functional_groups/004010/element_types/identifier_val.rb +287 -0
  158. data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +338 -0
  159. data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +309 -0
  160. data/lib/stupidedi/versions/functional_groups/004010/element_types.rb +124 -0
  161. data/lib/stupidedi/versions/functional_groups/004010/functional_group_def.rb +30 -0
  162. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GE.rb +20 -0
  163. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GS.rb +27 -0
  164. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/SE.rb +20 -0
  165. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/ST.rb +20 -0
  166. data/lib/stupidedi/versions/functional_groups/004010/segment_defs.rb +23 -0
  167. data/lib/stupidedi/versions/functional_groups/004010/segment_reqs.rb +18 -0
  168. data/lib/stupidedi/versions/functional_groups/004010/syntax_notes.rb +174 -0
  169. data/lib/stupidedi/versions/functional_groups/004010.rb +38 -0
  170. data/lib/stupidedi/versions/functional_groups/005010/element_defs.rb +1405 -0
  171. data/lib/stupidedi/versions/functional_groups/005010/element_reqs.rb +18 -0
  172. data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +577 -0
  173. data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +322 -0
  174. data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +354 -0
  175. data/lib/stupidedi/versions/functional_groups/005010/element_types/identifier_val.rb +368 -0
  176. data/lib/stupidedi/versions/functional_groups/005010/element_types/operators.rb +117 -0
  177. data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +398 -0
  178. data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +327 -0
  179. data/lib/stupidedi/versions/functional_groups/005010/element_types.rb +132 -0
  180. data/lib/stupidedi/versions/functional_groups/005010/functional_group_def.rb +30 -0
  181. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK1.rb +21 -0
  182. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK2.rb +21 -0
  183. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK9.rb +28 -0
  184. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AMT.rb +21 -0
  185. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BHT.rb +24 -0
  186. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BPR.rb +49 -0
  187. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CAS.rb +56 -0
  188. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CL1.rb +22 -0
  189. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLM.rb +41 -0
  190. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLP.rb +34 -0
  191. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CN1.rb +24 -0
  192. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR1.rb +32 -0
  193. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR2.rb +35 -0
  194. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR3.rb +25 -0
  195. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CRC.rb +26 -0
  196. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTP.rb +36 -0
  197. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTX.rb +24 -0
  198. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CUR.rb +57 -0
  199. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DMG.rb +34 -0
  200. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN1.rb +22 -0
  201. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN2.rb +24 -0
  202. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTM.rb +24 -0
  203. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTP.rb +21 -0
  204. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/FRM.rb +25 -0
  205. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GE.rb +20 -0
  206. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GS.rb +27 -0
  207. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HCP.rb +39 -0
  208. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HI.rb +31 -0
  209. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HL.rb +22 -0
  210. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK3.rb +22 -0
  211. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK4.rb +22 -0
  212. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK5.rb +24 -0
  213. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/K3.rb +21 -0
  214. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LIN.rb +69 -0
  215. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LQ.rb +22 -0
  216. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LX.rb +19 -0
  217. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MEA.rb +39 -0
  218. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MIA.rb +45 -0
  219. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MOA.rb +28 -0
  220. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N1.rb +24 -0
  221. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N2.rb +20 -0
  222. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N3.rb +20 -0
  223. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N4.rb +30 -0
  224. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NM1.rb +35 -0
  225. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NTE.rb +20 -0
  226. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/OI.rb +24 -0
  227. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PAT.rb +31 -0
  228. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PER.rb +32 -0
  229. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PLB.rb +40 -0
  230. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PRV.rb +26 -0
  231. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PS1.rb +21 -0
  232. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PWK.rb +30 -0
  233. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/QTY.rb +25 -0
  234. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/RDM.rb +23 -0
  235. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/REF.rb +23 -0
  236. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SBR.rb +28 -0
  237. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SE.rb +20 -0
  238. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/ST.rb +21 -0
  239. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/STC.rb +30 -0
  240. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV1.rb +44 -0
  241. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV2.rb +29 -0
  242. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV3.rb +30 -0
  243. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV5.rb +29 -0
  244. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVC.rb +26 -0
  245. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVD.rb +24 -0
  246. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TOO.rb +21 -0
  247. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TRN.rb +22 -0
  248. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS2.rb +40 -0
  249. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS3.rb +45 -0
  250. data/lib/stupidedi/versions/functional_groups/005010/segment_defs.rb +227 -0
  251. data/lib/stupidedi/versions/functional_groups/005010/segment_reqs.rb +18 -0
  252. data/lib/stupidedi/versions/functional_groups/005010/syntax_notes.rb +165 -0
  253. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/FA999.rb +38 -0
  254. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HB271.rb +85 -0
  255. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HC837.rb +163 -0
  256. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HI278.rb +64 -0
  257. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HN277.rb +74 -0
  258. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HP835.rb +68 -0
  259. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HR276.rb +57 -0
  260. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HS270.rb +53 -0
  261. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/RA820.rb +240 -0
  262. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs.rb +68 -0
  263. data/lib/stupidedi/versions/functional_groups/005010.rb +38 -0
  264. data/lib/stupidedi/versions/functional_groups.rb +8 -0
  265. data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +224 -0
  266. data/lib/stupidedi/versions/interchanges/00401/interchange_def.rb +45 -0
  267. data/lib/stupidedi/versions/interchanges/00401/segment_defs/IEA.rb +20 -0
  268. data/lib/stupidedi/versions/interchanges/00401/segment_defs/ISA.rb +34 -0
  269. data/lib/stupidedi/versions/interchanges/00401/segment_defs/TA1.rb +23 -0
  270. data/lib/stupidedi/versions/interchanges/00401/segment_defs.rb +28 -0
  271. data/lib/stupidedi/versions/interchanges/00401.rb +23 -0
  272. data/lib/stupidedi/versions/interchanges/00501/element_defs.rb +269 -0
  273. data/lib/stupidedi/versions/interchanges/00501/interchange_def.rb +47 -0
  274. data/lib/stupidedi/versions/interchanges/00501/segment_defs/IEA.rb +20 -0
  275. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISA.rb +34 -0
  276. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISB.rb +18 -0
  277. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISE.rb +18 -0
  278. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA1.rb +23 -0
  279. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA3.rb +18 -0
  280. data/lib/stupidedi/versions/interchanges/00501/segment_defs.rb +37 -0
  281. data/lib/stupidedi/versions/interchanges/00501.rb +23 -0
  282. data/lib/stupidedi/versions/interchanges.rb +8 -0
  283. data/lib/stupidedi/versions.rb +6 -0
  284. data/lib/stupidedi/writer/claredi.rb +142 -0
  285. data/lib/stupidedi/writer/default.rb +124 -0
  286. data/lib/stupidedi/writer.rb +6 -0
  287. data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
  288. data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
  289. data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
  290. data/lib/stupidedi/zipper/memoized_cursor.rb +131 -0
  291. data/lib/stupidedi/zipper/path.rb +124 -0
  292. data/lib/stupidedi/zipper/root_cursor.rb +120 -0
  293. data/lib/stupidedi/zipper.rb +25 -0
  294. data/lib/stupidedi.rb +66 -0
  295. data/spec/examples/integration/generating.example +551 -0
  296. data/spec/examples/integration/navigating.example +214 -0
  297. data/spec/examples/integration/parsing.example +445 -0
  298. data/spec/examples/ruby/array.example +476 -0
  299. data/spec/examples/ruby/blank.example +62 -0
  300. data/spec/examples/ruby/count.example +68 -0
  301. data/spec/examples/ruby/object.example +99 -0
  302. data/spec/examples/ruby/string.example +111 -0
  303. data/spec/examples/ruby/symbol.example +117 -0
  304. data/spec/examples/ruby/to_d.example +90 -0
  305. data/spec/examples/ruby/try.example +50 -0
  306. data/spec/examples/stupidedi/either.example +375 -0
  307. data/spec/examples/stupidedi/reader/failure.example +68 -0
  308. data/spec/examples/stupidedi/reader/input/delegated_input.example +292 -0
  309. data/spec/examples/stupidedi/reader/separators.example +73 -0
  310. data/spec/examples/stupidedi/reader/stream_reader.example +48 -0
  311. data/spec/examples/stupidedi/reader/success.example +34 -0
  312. data/spec/examples/stupidedi/reader/token_reader.example +775 -0
  313. data/spec/examples/stupidedi/reader.example +168 -0
  314. data/spec/examples/stupidedi/sets/absolute_set.example +1577 -0
  315. data/spec/examples/stupidedi/sets/null_set.example +2 -0
  316. data/spec/examples/stupidedi/sets/relative_set.example +2 -0
  317. data/spec/examples/stupidedi/sets/universal_set.example +1 -0
  318. data/spec/examples/stupidedi/versions/005010/element_types/an.example +201 -0
  319. data/spec/examples/stupidedi/versions/005010/element_types/dt.example +258 -0
  320. data/spec/examples/stupidedi/versions/005010/element_types/id.example +192 -0
  321. data/spec/examples/stupidedi/versions/005010/element_types/nn.example +177 -0
  322. data/spec/examples/stupidedi/versions/005010/element_types/r.example +178 -0
  323. data/spec/examples/stupidedi/versions/005010/element_types/tm.example +2 -0
  324. data/spec/examples/stupidedi/zipper/abstract_cursor.example +417 -0
  325. data/spec/examples/stupidedi/zipper.example +9 -0
  326. data/spec/fixtures/X186-AG824/1-bad.txt +21 -0
  327. data/spec/fixtures/X186-AG824/1-good.txt +17 -0
  328. data/spec/fixtures/X186-AG824/2-bad.txt +26 -0
  329. data/spec/fixtures/X186-AG824/2-good.txt +21 -0
  330. data/spec/fixtures/X186-AG824/3-bad.txt +87 -0
  331. data/spec/fixtures/X186-AG824/3-good.txt +61 -0
  332. data/spec/fixtures/X212-HN277/1-bad.txt +54 -0
  333. data/spec/fixtures/X212-HN277/1-good.txt +46 -0
  334. data/spec/fixtures/X212-HN277/2-bad.txt +37 -0
  335. data/spec/fixtures/X212-HN277/2-good.txt +29 -0
  336. data/spec/fixtures/X212-HN277/3-bad.txt +22 -0
  337. data/spec/fixtures/X212-HN277/3-good.txt +17 -0
  338. data/spec/fixtures/X212-HN277/4-bad.txt +30 -0
  339. data/spec/fixtures/X212-HN277/4-good.txt +24 -0
  340. data/spec/fixtures/X212-HR276/1-bad.txt +53 -0
  341. data/spec/fixtures/X212-HR276/1-good.txt +46 -0
  342. data/spec/fixtures/X212-HR276/2-bad.txt +45 -0
  343. data/spec/fixtures/X212-HR276/2-good.txt +38 -0
  344. data/spec/fixtures/X212-HR276/3-bad.txt +32 -0
  345. data/spec/fixtures/X212-HR276/3-good.txt +26 -0
  346. data/spec/fixtures/X212-HR276/4-bad.txt +32 -0
  347. data/spec/fixtures/X212-HR276/4-good.txt +26 -0
  348. data/spec/fixtures/X214-HN277/1-bad.txt +58 -0
  349. data/spec/fixtures/X214-HN277/1-good.txt +47 -0
  350. data/spec/fixtures/X214-HN277/2-bad.txt +34 -0
  351. data/spec/fixtures/X214-HN277/2-good.txt +22 -0
  352. data/spec/fixtures/X214-HN277/3-bad.txt +64 -0
  353. data/spec/fixtures/X214-HN277/3-good.txt +54 -0
  354. data/spec/fixtures/X214-HN277/4-bad.txt +77 -0
  355. data/spec/fixtures/X214-HN277/4-good.txt +63 -0
  356. data/spec/fixtures/X216-HI278/1-bad.txt +42 -0
  357. data/spec/fixtures/X216-HI278/1-good.txt +27 -0
  358. data/spec/fixtures/X216-HI278/2-bad.txt +43 -0
  359. data/spec/fixtures/X216-HI278/2-good.txt +29 -0
  360. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1.txt +24 -0
  361. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1_Clean.txt +20 -0
  362. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2.txt +46 -0
  363. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2_Clean.txt +30 -0
  364. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3.txt +38 -0
  365. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3_Clean.txt +24 -0
  366. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a.txt +39 -0
  367. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a_Clean.txt +24 -0
  368. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b.txt +43 -0
  369. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b_Clean.txt +25 -0
  370. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5.txt +63 -0
  371. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5_Clean.txt +41 -0
  372. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6.txt +36 -0
  373. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6_Clean.txt +20 -0
  374. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r.txt +34 -0
  375. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r_Clean.txt +23 -0
  376. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r.txt +46 -0
  377. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r_Clean.txt +31 -0
  378. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r.txt +44 -0
  379. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r_Clean.txt +26 -0
  380. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4ar_Clean.txt +28 -0
  381. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4br_Clean.txt +35 -0
  382. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r.txt +60 -0
  383. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r_Clean.txt +42 -0
  384. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r.txt +40 -0
  385. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r_Clean.txt +24 -0
  386. data/spec/fixtures/X218-RA820/1-bad.txt +31 -0
  387. data/spec/fixtures/X218-RA820/1-good.txt +25 -0
  388. data/spec/fixtures/X218-RA820/2-bad.txt +37 -0
  389. data/spec/fixtures/X218-RA820/2-good.txt +29 -0
  390. data/spec/fixtures/X218-RA820/3-bad.txt +29 -0
  391. data/spec/fixtures/X218-RA820/3-good.txt +23 -0
  392. data/spec/fixtures/X218-RA820/4-bad.txt +36 -0
  393. data/spec/fixtures/X218-RA820/4-good.txt +27 -0
  394. data/spec/fixtures/X220-BE834/1-bad.txt +35 -0
  395. data/spec/fixtures/X220-BE834/1-good.txt +29 -0
  396. data/spec/fixtures/X220-BE834/10-bad.txt +26 -0
  397. data/spec/fixtures/X220-BE834/10-good.txt +19 -0
  398. data/spec/fixtures/X220-BE834/2-bad.txt +31 -0
  399. data/spec/fixtures/X220-BE834/2-good.txt +23 -0
  400. data/spec/fixtures/X220-BE834/3-bad.txt +36 -0
  401. data/spec/fixtures/X220-BE834/3-good.txt +26 -0
  402. data/spec/fixtures/X220-BE834/4-bad.txt +27 -0
  403. data/spec/fixtures/X220-BE834/4-good.txt +21 -0
  404. data/spec/fixtures/X220-BE834/5-bad.txt +26 -0
  405. data/spec/fixtures/X220-BE834/5-good.txt +17 -0
  406. data/spec/fixtures/X220-BE834/6-bad.txt +25 -0
  407. data/spec/fixtures/X220-BE834/6-good.txt +20 -0
  408. data/spec/fixtures/X220-BE834/7-bad.txt +25 -0
  409. data/spec/fixtures/X220-BE834/7-good.txt +20 -0
  410. data/spec/fixtures/X220-BE834/8-bad.txt +25 -0
  411. data/spec/fixtures/X220-BE834/8-good.txt +20 -0
  412. data/spec/fixtures/X220-BE834/9-bad.txt +27 -0
  413. data/spec/fixtures/X220-BE834/9-good.txt +21 -0
  414. data/spec/fixtures/X221-HP835/1-bad.txt +58 -0
  415. data/spec/fixtures/X221-HP835/1-good.txt +40 -0
  416. data/spec/fixtures/X221-HP835/2-bad.txt +51 -0
  417. data/spec/fixtures/X221-HP835/2-good.txt +40 -0
  418. data/spec/fixtures/X221-HP835/3a-bad.txt +78 -0
  419. data/spec/fixtures/X221-HP835/3a-good.txt +49 -0
  420. data/spec/fixtures/X221-HP835/3b-bad.txt +60 -0
  421. data/spec/fixtures/X221-HP835/3b-good.txt +32 -0
  422. data/spec/fixtures/X221-HP835/3c-bad.txt +55 -0
  423. data/spec/fixtures/X221-HP835/3c-good.txt +34 -0
  424. data/spec/fixtures/X222-HC837/1-bad.txt +60 -0
  425. data/spec/fixtures/X222-HC837/1-good.txt +53 -0
  426. data/spec/fixtures/X222-HC837/10a-bad.txt +52 -0
  427. data/spec/fixtures/X222-HC837/10a-good.txt +40 -0
  428. data/spec/fixtures/X222-HC837/10b-bad.txt +99 -0
  429. data/spec/fixtures/X222-HC837/10b-good.txt +80 -0
  430. data/spec/fixtures/X222-HC837/10c-bad.txt +105 -0
  431. data/spec/fixtures/X222-HC837/10c-good.txt +80 -0
  432. data/spec/fixtures/X222-HC837/11-bad.txt +69 -0
  433. data/spec/fixtures/X222-HC837/11-good.txt +45 -0
  434. data/spec/fixtures/X222-HC837/12-bad.txt +73 -0
  435. data/spec/fixtures/X222-HC837/12-good.txt +51 -0
  436. data/spec/fixtures/X222-HC837/13-bad.txt +64 -0
  437. data/spec/fixtures/X222-HC837/13-good.txt +46 -0
  438. data/spec/fixtures/X222-HC837/3a-bad.txt +83 -0
  439. data/spec/fixtures/X222-HC837/3a-good.txt +59 -0
  440. data/spec/fixtures/X222-HC837/3b-bad.txt +97 -0
  441. data/spec/fixtures/X222-HC837/3b-good.txt +70 -0
  442. data/spec/fixtures/X222-HC837/3c-bad.txt +95 -0
  443. data/spec/fixtures/X222-HC837/3c-good.txt +74 -0
  444. data/spec/fixtures/X222-HC837/4-bad.txt +67 -0
  445. data/spec/fixtures/X222-HC837/4-good.txt +48 -0
  446. data/spec/fixtures/X222-HC837/5-bad.txt +73 -0
  447. data/spec/fixtures/X222-HC837/5-good.txt +60 -0
  448. data/spec/fixtures/X222-HC837/6-bad.txt +50 -0
  449. data/spec/fixtures/X222-HC837/6-good.txt +39 -0
  450. data/spec/fixtures/X222-HC837/7-bad.txt +93 -0
  451. data/spec/fixtures/X222-HC837/7-good.txt +78 -0
  452. data/spec/fixtures/X222-HC837/8-bad.txt +64 -0
  453. data/spec/fixtures/X222-HC837/8-good.txt +52 -0
  454. data/spec/fixtures/X222-HC837/9-bad.txt +56 -0
  455. data/spec/fixtures/X222-HC837/9-good.txt +38 -0
  456. data/spec/fixtures/X223-HC837/1-bad.txt +66 -0
  457. data/spec/fixtures/X223-HC837/1-good.txt +53 -0
  458. data/spec/fixtures/X223-HC837/2-bad.txt +69 -0
  459. data/spec/fixtures/X223-HC837/2-good.txt +60 -0
  460. data/spec/fixtures/X223-HC837/3-bad.txt +89 -0
  461. data/spec/fixtures/X223-HC837/3-good.txt +61 -0
  462. data/spec/fixtures/X223-HC837/4-bad.txt +60 -0
  463. data/spec/fixtures/X223-HC837/4-good.txt +40 -0
  464. data/spec/fixtures/X223-HC837/5-bad.txt +75 -0
  465. data/spec/fixtures/X223-HC837/5-good.txt +58 -0
  466. data/spec/fixtures/X224-HC837/1-bad.txt +54 -0
  467. data/spec/fixtures/X224-HC837/1-good.txt +44 -0
  468. data/spec/fixtures/X224-HC837/2a-bad.txt +52 -0
  469. data/spec/fixtures/X224-HC837/2a-good.txt +42 -0
  470. data/spec/fixtures/X224-HC837/2b-bad.txt +67 -0
  471. data/spec/fixtures/X224-HC837/2b-good.txt +52 -0
  472. data/spec/fixtures/X224-HC837/3-bad.txt +67 -0
  473. data/spec/fixtures/X224-HC837/3-good.txt +51 -0
  474. data/spec/fixtures/X224-HC837/4-bad.txt +49 -0
  475. data/spec/fixtures/X224-HC837/4-good.txt +40 -0
  476. data/spec/fixtures/X230-FA997/1-bad.txt +19 -0
  477. data/spec/fixtures/X230-FA997/1-good.txt +16 -0
  478. data/spec/fixtures/X231-FA999/1-bad.txt +20 -0
  479. data/spec/fixtures/X231-FA999/1-good.txt +20 -0
  480. data/spec/fixtures/X279-HB271/1-bad.txt +36 -0
  481. data/spec/fixtures/X279-HB271/1-good.txt +30 -0
  482. data/spec/fixtures/X279-HB271/2-bad.txt +22 -0
  483. data/spec/fixtures/X279-HB271/2-good.txt +16 -0
  484. data/spec/fixtures/X279-HB271/3-bad.txt +44 -0
  485. data/spec/fixtures/X279-HB271/3-good.txt +36 -0
  486. data/spec/fixtures/X279-HS270/1-bad.txt +29 -0
  487. data/spec/fixtures/X279-HS270/1-good.txt +23 -0
  488. data/spec/fixtures/X279-HS270/2-bad.txt +32 -0
  489. data/spec/fixtures/X279-HS270/2-good.txt +25 -0
  490. data/spec/spec_helper.rb +34 -0
  491. data/spec/support/fixtures.rb +26 -0
  492. data/spec/support/matchers/either_matchers.rb +26 -0
  493. data/spec/support/matchers/navigation_matchers.rb +247 -0
  494. data/spec/support/node.rb +41 -0
  495. data/spec/support/quickcheck/characters.rb +28 -0
  496. data/spec/support/quickcheck/property.rb +105 -0
  497. data/spec/support/quickcheck/serialized_edi.rb +399 -0
  498. data/spec/support/quickcheck.rb +302 -0
  499. data/spec/support/rcov.rb +34 -0
  500. metadata +577 -0
@@ -0,0 +1,466 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class TokenReader
5
+
6
+ # @private
7
+ SEGMENT_ID = /\A[A-Z][A-Z0-9]{1,2}\Z/
8
+
9
+ include Inspect
10
+
11
+ # @return [String, Input]
12
+ attr_reader :input
13
+
14
+ # @return [Separators]
15
+ attr_reader :separators
16
+
17
+ # @return [SegmentDict]
18
+ attr_accessor :segment_dict
19
+
20
+ def initialize(input, separators, segment_dict = SegmentDict.empty)
21
+ @input, @separators, @segment_dict =
22
+ input, separators, segment_dict
23
+ end
24
+
25
+ # @return [TokenReader]
26
+ def copy(changes = {})
27
+ TokenReader.new \
28
+ changes.fetch(:input, @input),
29
+ changes.fetch(:separators, @separators),
30
+ changes.fetch(:segment_dict, @segment_dict)
31
+ end
32
+
33
+ # @return false
34
+ def stream?
35
+ false
36
+ end
37
+
38
+ # @return [StreamReader]
39
+ def stream
40
+ StreamReader.new(@input)
41
+ end
42
+
43
+ def empty?
44
+ @input.empty?
45
+ end
46
+
47
+ # If `s` is a prefix of {#input}, then `s` is skipped and the remaining
48
+ # input is returned as a new `TokenReader` wrapped by `Either.success`.
49
+ # Otherwise, an {Either::Failure} is returned.
50
+ #
51
+ # @return [Either<TokenReader>]
52
+ def consume_prefix(s)
53
+ return success(self) if s.empty?
54
+
55
+ position = 0
56
+ buffer = ""
57
+
58
+ while @input.defined_at?(position)
59
+ character = @input.at(position)
60
+ position += 1
61
+
62
+ unless is_control?(character)
63
+ buffer << character
64
+
65
+ if s.length == buffer.length
66
+ if s == buffer
67
+ return success(advance(position))
68
+ else
69
+ return failure("found #{buffer.inspect} instead of #{s.inspect}")
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ failure("reached end of input without finding #{s.inspect}")
76
+ end
77
+
78
+ def consume_control_chars
79
+ position = 0
80
+
81
+ while @input.defined_at?(position) and is_control?(@input.at(position))
82
+ position += 1
83
+ end
84
+
85
+ if position.zero?
86
+ success(self)
87
+ else
88
+ success(advance(position))
89
+ end
90
+ end
91
+
92
+ # If `s` occurs within {#input}, then the input up to and including `s`
93
+ # is skipped and the remaining input is returned as a new `TokenReader`
94
+ # wrapped by `Either.success`. Otherwise, {Either::Failure} is returned.
95
+ #
96
+ # @return [Either<TokenReader>]
97
+ def consume(s)
98
+ return success(self) if s.empty?
99
+
100
+ position = 0
101
+ buffer = " " * s.length
102
+
103
+ while @input.defined_at?(position)
104
+ character = @input.at(position)
105
+
106
+ unless is_control?(character)
107
+ # Slide the "window" forward one character
108
+ buffer = buffer.slice(1..-1) << character
109
+ end
110
+
111
+ position += 1
112
+
113
+ if s == buffer
114
+ return success(advance(position))
115
+ end
116
+ end
117
+
118
+ failure("reached end of input without finding #{s.inspect}")
119
+ end
120
+
121
+ # Returns a single character and the remaining input as a {Result} with
122
+ # a `value` of the character and a `remainder` of the reamining input as
123
+ # a new instance of {TokenReader}. If {#input} has less than a single
124
+ # character, returns an {Either::Failure}
125
+ #
126
+ # @return [Either<Result<String>>]
127
+ def read_character
128
+ position = 0
129
+ buffer = ""
130
+
131
+ while @input.defined_at?(position)
132
+ character = @input.at(position)
133
+ position += 1
134
+
135
+ if is_control?(character)
136
+ next
137
+ end
138
+
139
+ return result(character, advance(position))
140
+ end
141
+
142
+ failure("less than one character available")
143
+ end
144
+
145
+ # @return [Either<Result<SegmentTok, TokenReader>>]
146
+ def read_segment
147
+ consume_control_chars.flatmap do |start|
148
+ # We might start reading a segment at "\nNM1...", where the "\n" is on
149
+ # line 5, but "NM1" is on line 6. So to ensure the segment position is
150
+ # line 6, we start with consume_control_characters.
151
+ start.read_segment_id.flatmap do |segment_id, aR|
152
+ if @segment_dict.defined_at?(segment_id)
153
+ element_uses = @segment_dict.at(segment_id).element_uses
154
+ else
155
+ element_uses = []
156
+ end
157
+
158
+ aR.read_delimiter.flatmap do |delim, bR|
159
+ case delim
160
+ when @separators.element
161
+ rest = bR.read_elements(segment_id, element_uses)
162
+ rest.map{|es, cR| segment(segment_id, start.input, cR.input, es) }
163
+ when @separators.segment
164
+ remainder =
165
+ if segment_id == :IEA
166
+ bR.stream
167
+ else
168
+ bR
169
+ end
170
+
171
+ # Consume the segment terminator
172
+ result(segment(segment_id, start.input, bR.input), remainder)
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ # @return [Either<Result<Array<SimpleElementTok, CompositeElementTok>, TokenReader>>]
180
+ def read_elements(segment_id, element_uses)
181
+ if element_uses.empty?
182
+ read_simple_element
183
+ else
184
+ element_use = element_uses.head
185
+ repeatable = element_use.repeatable?
186
+
187
+ if element_use.composite?
188
+ read_composite_element(repeatable)
189
+ else
190
+ read_simple_element(repeatable)
191
+ end
192
+ end.flatmap do |element, aR|
193
+ aR.read_delimiter.flatmap do |delim, bR|
194
+ case delim
195
+ when @separators.segment
196
+ remainder =
197
+ if segment_id == :IEA
198
+ bR.stream
199
+ else
200
+ bR
201
+ end
202
+
203
+ # This is the last element before the segment terminator, make
204
+ # it into a singleton list and _do_ consume the delimiter
205
+ result(element.cons, remainder)
206
+ when @separators.element
207
+ # There is another element following the delimiter
208
+ rest = bR.read_elements(segment_id, element_uses.tail)
209
+ rest.map{|es, _| element.cons(es) }
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ # @return [Either<Result<Array<ComponentElementTok, TokenReader>>>]
216
+ def read_component_elements(repeatable = false)
217
+ read_component_element(repeatable).flatmap do |component, aR|
218
+ aR.read_delimiter.flatmap do |delim, bR|
219
+ case delim
220
+ when @separators.segment,
221
+ @separators.element,
222
+ @separators.repetition
223
+ # This is the last component element within the composite element,
224
+ # so make it into a singleton list and don't consume the delimiter
225
+ result(component.cons, aR)
226
+ when @separators.component
227
+ rest = bR.read_component_elements(repeatable)
228
+ rest.map{|es, _| component.cons(es) }
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+ # @return [Either<Result<Symbol, TokenReader>>]
235
+ def read_segment_id
236
+ position = 0
237
+ buffer = ""
238
+
239
+ while true
240
+ unless @input.defined_at?(position)
241
+ return eof("reached end of input without finding a segment identifier")
242
+ end
243
+
244
+ character = @input.at(position)
245
+ position += 1
246
+
247
+ if is_delimiter?(character)
248
+ break
249
+ end
250
+
251
+ unless is_control?(character)
252
+ if buffer.length == 3
253
+ break
254
+ end
255
+
256
+ buffer << character
257
+ end
258
+ end
259
+
260
+ # We only arrive here if {character} is a delimiter, or if we read
261
+ # three characters into {buffer} and an additional into {character}
262
+ if buffer =~ SEGMENT_ID
263
+ remainder = advance(position - 1)
264
+
265
+ case character
266
+ when @separators.segment,
267
+ @separators.element
268
+ # Don't consume the delimiter
269
+ result(buffer.upcase.to_sym, remainder)
270
+ else
271
+ failure("found #{character.inspect} following segment identifier")
272
+ end
273
+ else
274
+ failure("found #{(buffer + character).inspect} instead of segment identifier")
275
+ end
276
+ end
277
+
278
+ # @return [Either<Result<Character, TokenReader>>]
279
+ def read_delimiter
280
+ position = 0
281
+
282
+ while @input.defined_at?(position)
283
+ character = @input.at(position)
284
+ position += 1
285
+
286
+ if is_control?(character)
287
+ next
288
+ end
289
+
290
+ if is_delimiter?(character)
291
+ return result(character, advance(position))
292
+ else
293
+ return failure("found #{character.inspect} instead of a delimiter")
294
+ end
295
+ end
296
+
297
+ failure("reached end of input without finding a delimiter")
298
+ end
299
+
300
+ # @return [Either<Result<SimpleElementToken, TokenReader>>]
301
+ def read_simple_element(repeatable = false)
302
+ position = 0
303
+ buffer = ""
304
+
305
+ while @input.defined_at?(position)
306
+ character = @input.at(position)
307
+ position += 1
308
+
309
+ if is_control?(character)
310
+ next
311
+ end
312
+
313
+ case character
314
+ when @separators.segment,
315
+ @separators.element
316
+ # These delimiters mark the end of the element. We don't consume
317
+ # the delimiter because the next reader can use the delimiter to
318
+ # know which token to next expect.
319
+ token = simple(buffer, @input, @input.drop(position))
320
+ token = token.repeated if repeatable
321
+ return result(token, advance(position - 1))
322
+ when @separators.repetition
323
+ if repeatable
324
+ token = simple(buffer, @input, @input.drop(position))
325
+ rest = advance(position).read_simple_element(repeatable)
326
+ return rest.map{|e, _| e.repeated(token) }
327
+ # else
328
+ # # @todo: Read this as data but sound the alarms
329
+ end
330
+ # when @separators.component
331
+ # # @todo: Read this as data but sound the alarms
332
+ end
333
+
334
+ buffer << character
335
+ end
336
+
337
+ failure("reached end of input without finding a simple data element")
338
+ end
339
+
340
+ # @return [Either<Result<ComponentElementTok, TokenReader>>]
341
+ def read_component_element(repeatable = false)
342
+ position = 0
343
+ buffer = ""
344
+
345
+ while @input.defined_at?(position)
346
+ character = @input.at(position)
347
+ position += 1
348
+
349
+ if is_control?(character)
350
+ next
351
+ end
352
+
353
+ case character
354
+ when @separators.element,
355
+ @separators.segment,
356
+ @separators.component
357
+ # Don't consume the separator/terminator
358
+ token = component(buffer, @input, @input.drop(position))
359
+ return result(token, advance(position - 1))
360
+ when @separators.repetition
361
+ if repeatable
362
+ # Don't consume the repetition separator
363
+ token = component(buffer, @input, @input.drop(position))
364
+ return result(token, advance(position - 1))
365
+ # else
366
+ # # @todo: Read this as data but sound the alarms
367
+ end
368
+ end
369
+
370
+ buffer << character
371
+ end
372
+
373
+ failure("reached end of input without finding a component data element")
374
+ end
375
+
376
+ # @return [Either<Result<CompositeElementTok, TokenReader>>]
377
+ def read_composite_element(repeatable = false)
378
+ read_component_elements(repeatable).flatmap do |components, aR|
379
+ token = composite(components, @input, aR.input)
380
+
381
+ aR.read_delimiter.flatmap do |delim, bR|
382
+ case delim
383
+ when @separators.segment,
384
+ @separators.element
385
+ token = token.repeated if repeatable
386
+ result(token, aR)
387
+ when @separators.repetition
388
+ bR.read_composite_element(repeatable).map do |c, cR|
389
+ c.repeated(token)
390
+ end
391
+ end
392
+ end
393
+ end
394
+ end
395
+
396
+ # @return [void]
397
+ def pretty_print(q)
398
+ q.text("TokenReader")
399
+ q.group(2, "(", ")") do
400
+ q.breakable ""
401
+
402
+ q.pp @input
403
+ q.text ","
404
+ q.breakable
405
+
406
+ q.pp @separators
407
+ end
408
+ end
409
+
410
+ private
411
+
412
+ # @return [TokenReader]
413
+ def advance(n)
414
+ unless @input.defined_at?(n-1)
415
+ raise IndexError, "less than #{n} characters available"
416
+ else
417
+ TokenReader.new(@input.drop(n), @separators, @segment_dict)
418
+ end
419
+ end
420
+
421
+ def is_delimiter?(character)
422
+ character == @separators.segment or
423
+ character == @separators.element or
424
+ character == @separators.component or
425
+ character == @separators.repetition
426
+ end
427
+
428
+ def is_control?(character)
429
+ Reader.is_control_character?(character) and not is_delimiter?(character)
430
+ end
431
+
432
+ def failure(message, remainder = @input)
433
+ Result.failure(message, remainder, true)
434
+ end
435
+
436
+ def eof(message, remainder = @input)
437
+ Result.failure(message, remainder, false)
438
+ end
439
+
440
+ def success(value)
441
+ Either.success(value)
442
+ end
443
+
444
+ def result(value, remainder)
445
+ Result.success(value, remainder)
446
+ end
447
+
448
+ def segment(segment_id, input, remainder, elements = [])
449
+ SegmentTok.build(segment_id, elements, input.position, remainder.position)
450
+ end
451
+
452
+ def simple(value, input, remainder)
453
+ SimpleElementTok.build(value, input.position, remainder.position)
454
+ end
455
+
456
+ def component(value, input, remainder)
457
+ ComponentElementTok.build(value, input.position, remainder.position)
458
+ end
459
+
460
+ def composite(value, input, remainder)
461
+ CompositeElementTok.build(value, input.position, remainder.position)
462
+ end
463
+ end
464
+
465
+ end
466
+ end
@@ -0,0 +1,56 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class ComponentElementTok
5
+ include Inspect
6
+
7
+ # @return [String]
8
+ attr_reader :value
9
+
10
+ # @return [Position]
11
+ attr_reader :position
12
+
13
+ # @return [Position]
14
+ attr_reader :remainder
15
+
16
+ def initialize(value, position, remainder)
17
+ @value, @position, @remainder =
18
+ value, position, remainder
19
+ end
20
+
21
+ def pretty_print(q)
22
+ q.pp(:component.cons(@value.cons))
23
+ end
24
+
25
+ def blank?
26
+ @value.blank?
27
+ end
28
+
29
+ def present?
30
+ not blank?
31
+ end
32
+
33
+ def simple?
34
+ true
35
+ end
36
+
37
+ def composite?
38
+ false
39
+ end
40
+ end
41
+
42
+ class << ComponentElementTok
43
+ # @group Constructors
44
+ #########################################################################
45
+
46
+ # @return [ComponentElementTok]
47
+ def build(value, position, remainder)
48
+ new(value, position, remainder)
49
+ end
50
+
51
+ # @endgroup
52
+ #########################################################################
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,64 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class CompositeElementTok
5
+ include Inspect
6
+
7
+ # @return [Array<ComponentElementTok>]
8
+ attr_reader :component_toks
9
+
10
+ # @return [Position]
11
+ attr_reader :position
12
+
13
+ # @return [Position]
14
+ attr_reader :remainder
15
+
16
+ def initialize(component_toks, position, remainder)
17
+ @component_toks, @position, @remainder =
18
+ component_toks, position, remainder
19
+ end
20
+
21
+ def pretty_print(q)
22
+ q.pp(:composite.cons(@component_toks))
23
+ end
24
+
25
+ def repeated
26
+ RepeatedElementTok.new(self.cons, @position)
27
+ end
28
+
29
+ def repeated?
30
+ false
31
+ end
32
+
33
+ def blank?
34
+ @component_toks.all?(&:blank?)
35
+ end
36
+
37
+ def present?
38
+ not blank?
39
+ end
40
+
41
+ def simple?
42
+ false
43
+ end
44
+
45
+ def composite?
46
+ true
47
+ end
48
+ end
49
+
50
+ class << CompositeElementTok
51
+ # @group Constructors
52
+ #########################################################################
53
+
54
+ # @return [CompositeElementTok]
55
+ def build(component_toks, position, remainder)
56
+ new(component_toks, position, remainder)
57
+ end
58
+
59
+ # @endgroup
60
+ #########################################################################
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,64 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class RepeatedElementTok
5
+ include Inspect
6
+
7
+ # @return [Array<CompositeElementTok>]
8
+ # @return [Array<SimpleElementTok>]
9
+ attr_reader :element_toks
10
+
11
+ attr_reader :position
12
+
13
+ delegate :remainder, :to => "element_toks.last"
14
+
15
+ def initialize(element_toks, position)
16
+ @element_toks, @position =
17
+ element_toks, position
18
+ end
19
+
20
+ def repeated(element_tok)
21
+ @element_toks.unshift(element_tok)
22
+ self
23
+ end
24
+
25
+ def pretty_print(q)
26
+ q.pp(:repeated.cons(@element_toks))
27
+ end
28
+
29
+ def simple?
30
+ false
31
+ end
32
+
33
+ def repeated?
34
+ true
35
+ end
36
+
37
+ def blank?
38
+ @element_toks.all?(&:blank?)
39
+ end
40
+
41
+ def present?
42
+ not blank?
43
+ end
44
+
45
+ def composite?
46
+ false
47
+ end
48
+ end
49
+
50
+ class << RepeatedElementTok
51
+ # @group Constructors
52
+ #########################################################################
53
+
54
+ # @return [RepeatedElementTok]
55
+ def build(element_toks, position)
56
+ new(element_toks, position)
57
+ end
58
+
59
+ # @endgroup
60
+ #########################################################################
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,51 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class SegmentTok
5
+ include Inspect
6
+
7
+ # @return [Symbol]
8
+ attr_reader :id
9
+
10
+ # @return [Array<CompositeElementTok, SimpleElementTok>]
11
+ attr_reader :element_toks
12
+
13
+ # @return [Position]
14
+ attr_reader :position
15
+
16
+ # @return [Position]
17
+ attr_reader :remainder
18
+
19
+ def initialize(id, element_toks, position, remainder)
20
+ @id, @element_toks, @position, @remainder =
21
+ id, element_toks, position, remainder
22
+ end
23
+
24
+ def pretty_print(q)
25
+ q.pp(:segment.cons(@id.cons(@element_toks)))
26
+ end
27
+
28
+ def blank?
29
+ @element_toks.all(&:blank?)
30
+ end
31
+
32
+ def present?
33
+ not blank?
34
+ end
35
+ end
36
+
37
+ class << SegmentTok
38
+ # @group Constructors
39
+ #########################################################################
40
+
41
+ # @return [SegmentTok]
42
+ def build(id, element_toks, position, remainder)
43
+ new(id, element_toks, position, remainder)
44
+ end
45
+
46
+ # @endgroup
47
+ #########################################################################
48
+ end
49
+
50
+ end
51
+ end