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,133 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ #
5
+ # Provides an abstract interface for a positioned cursor within an
6
+ # element-based input stream. The main operations are implemented by the
7
+ # {#take} and {#drop} methods.
8
+ #
9
+ # The {DelegatedInput} subclass wraps values that already implement the
10
+ # interface, like {String} and {Array}. The {FileInput} subclass wraps
11
+ # opened `IO` streams like `File`, and possibly others.
12
+ #
13
+ # @example Reading the input
14
+ # input = Input.build("abc")
15
+ # input.at(0) #=> "a"
16
+ # input.take(3) #=> "abc"
17
+ #
18
+ # input = input.drop(1) #=> #<DelegatedInput ...>
19
+ # input.at(0) #=> "b"
20
+ # input.take(3) #=> "bc"
21
+ #
22
+ # input = input.drop(1) #=> #<DelegatedInput ...>
23
+ # input.at(0) #=> "c"
24
+ # input.take(3) #=> "c"
25
+ #
26
+ # @example Querying the position
27
+ # input = Input.build("abc\ndef\nghi")
28
+ # input.offset #=> 0
29
+ # input.line #=> 1
30
+ # input.column #=> 1
31
+ #
32
+ # input.drop(3).bind do |in|
33
+ # in.offset #=> 3
34
+ # in.line #=> 1
35
+ # in.column #=> 4
36
+ # end
37
+ #
38
+ # input.drop(4).bind do |in|
39
+ # in.offset #=> 4
40
+ # in.line #=> 2
41
+ # in.column #=> 1
42
+ # end
43
+ #
44
+ # @note The monkey-patched classes {String} and {Array} provide compatible
45
+ # implementations of the abstract methods, so code written to target
46
+ # this interface is backward-compatable with plain unwrapped {String}
47
+ # and {Array} values.
48
+ #
49
+ class AbstractInput
50
+ include Inspect
51
+
52
+ # @group Querying the Position
53
+ ########################################################################
54
+
55
+ # The {Position} value that describes the position of the input stream
56
+ #
57
+ # @return [Position]
58
+ abstract :position
59
+
60
+ # The current position as the number of elements previously read
61
+ #
62
+ # @return [Integer]
63
+ delegate :offset, :to => :position
64
+
65
+ # The line of the current position
66
+ #
67
+ # @return [Integer]
68
+ delegate :line, :to => :position
69
+
70
+ # The column of the current position. The column resets to `1` each time
71
+ # a newline is read
72
+ #
73
+ # @return [Integer]
74
+ delegate :column, :to => :position
75
+
76
+ # The file name, URI, etc that identifies the input stream
77
+ #
78
+ # @return [String]
79
+ delegate :path, :to => :position
80
+
81
+ # @group Reading the Input
82
+ ########################################################################
83
+
84
+ # Read the first `n` elements
85
+ #
86
+ # @param [Integer] n number of elements to read (`n >= 0`)
87
+ abstract :take, :args => %w(n)
88
+
89
+ # Read a single element at the given index. Result is undefined unless
90
+ # the input contains enough elements, which can be tested with
91
+ # {#defined_at?}
92
+ #
93
+ # @param [Integer] n the index of the element to read (`n >= 0`)
94
+ abstract :at, :args => %w(n)
95
+
96
+ # Returns the smallest `n`, where {#at}`(n)` == `element`
97
+ #
98
+ # @param [Object] element the element to find in the input
99
+ #
100
+ # @return [Integer]
101
+ # @return nil if `element` is not present in the input
102
+ abstract :index, :args => %w(value)
103
+
104
+ # @group Advancing the Cursor
105
+ ########################################################################
106
+
107
+ # Advance the cursor forward `n` elements
108
+ #
109
+ # @param [Integer] n the number of elements to advance (`n >= 0`)
110
+ #
111
+ # @return [AbstractInput] new object with the remaining input
112
+ abstract :drop, :args => %w(n)
113
+
114
+ # @group Testing the Input
115
+ ########################################################################
116
+
117
+ # True if the input contains enough elements such that {#at}`(n)` is
118
+ # defined
119
+ #
120
+ # @param [Integer] n the index to test (`n >= 0`)
121
+ abstract :defined_at?, :args => %w(n)
122
+
123
+ # True if no elements remain in the input
124
+ abstract :empty?
125
+
126
+ # True if `other` equals the remaining input
127
+ #
128
+ # @return [Boolean]
129
+ abstract :==, :args => %w(other)
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,111 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class DelegatedInput < AbstractInput
5
+
6
+ def initialize(delegate, offset = 0, line = 1, column = 1)
7
+ @delegate, @offset, @line, @column =
8
+ delegate, offset, line, column
9
+ end
10
+
11
+ # @group Querying the Position
12
+ ########################################################################
13
+
14
+ # (see AbstractInput#offset)
15
+ attr_reader :offset
16
+
17
+ # (see AbstractInput#line)
18
+ attr_reader :line
19
+
20
+ # (see AbstractInput#column)
21
+ attr_reader :column
22
+
23
+ # (see AbstractInput#position)
24
+ def position
25
+ Position.new(@offset, @line, @column, nil)
26
+ end
27
+
28
+ # @group Reading the Input
29
+ ########################################################################
30
+
31
+ # (see AbstractInput#take)
32
+ delegate :take, :to => :@delegate
33
+
34
+ # (see AbstractInput#at)
35
+ delegate :at, :to => :@delegate
36
+
37
+ # (see AbstractInput#index)
38
+ delegate :index, :to => :@delegate
39
+
40
+ # @group Advancing the Cursor
41
+ ########################################################################
42
+
43
+ # (see AbstractInput#drop)
44
+ def drop(n)
45
+ raise ArgumentError, "n must be positive" unless n >= 0
46
+
47
+ suffix = @delegate.drop(n)
48
+ prefix = @delegate.take(n)
49
+
50
+ length = prefix.length
51
+ count = prefix.count("\n")
52
+
53
+ column = unless count.zero?
54
+ length - prefix.rindex("\n")
55
+ else
56
+ @column + length
57
+ end
58
+
59
+ copy(:delegate => suffix,
60
+ :offset => @offset + length,
61
+ :line => @line + count,
62
+ :column => column)
63
+ end
64
+
65
+ # @group Testing the Input
66
+ ########################################################################
67
+
68
+ # (see AbstractInput#defined_at?)
69
+ delegate :defined_at?, :to => :@delegate
70
+
71
+ # (see AbstractInput#empty?)
72
+ delegate :empty?, :to => :@delegate
73
+
74
+ # (see AbstractInput#==)
75
+ delegate :==, :to => :@delegate
76
+
77
+ # @endgroup
78
+ ########################################################################
79
+
80
+ # @return [void]
81
+ def pretty_print(q)
82
+ q.text("DelegateInput")
83
+ q.group(2, "(", ")") do
84
+ preview = @delegate.take(4)
85
+ preview = if preview.empty?
86
+ "EOF"
87
+ elsif preview.length <= 3
88
+ preview.inspect
89
+ else
90
+ (preview.take(3) << "...").inspect
91
+ end
92
+
93
+ q.text preview
94
+ q.text " at line #{@line}, column #{@column}, offset #{@offset}"
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ # @return [DelegatedInput]
101
+ def copy(changes = {})
102
+ DelegatedInput.new \
103
+ changes.fetch(:delegate, @delegate),
104
+ changes.fetch(:offset, @offset),
105
+ changes.fetch(:line, @line),
106
+ changes.fetch(:column, @column)
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,155 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ #
5
+ # @note This class is not thread-safe. If more than one `Thread` has access
6
+ # to the same instance, and they simultaneously call methods on that
7
+ # instance, the methods may produce incorrect results and the object might
8
+ # be left in an inconsistent state.
9
+ #
10
+ class FileInput < AbstractInput
11
+
12
+ # @return [IO]
13
+ attr_reader :io
14
+
15
+ def initialize(io, offset = 0, line = 1, column = 1, size = io.stat.size)
16
+ @io, @offset, @line, @column, @size =
17
+ io, offset, line, column, size
18
+ end
19
+
20
+ # @group Querying the Position
21
+ ########################################################################
22
+
23
+ # (see AbstractInput#offset)
24
+ attr_reader :offset
25
+
26
+ # @return [Integer]
27
+ # (see AbstractInput#line)
28
+ attr_reader :line
29
+
30
+ # (see AbstractInput#column)
31
+ attr_reader :column
32
+
33
+ # (see AbstractInput#path)
34
+ attr_reader :path
35
+
36
+ # (see AbstractInput#position)
37
+ def position
38
+ Position.new(@offset, @line, @column, @io.path)
39
+ end
40
+
41
+ # @group Reading the Input
42
+ ########################################################################
43
+
44
+ # (see AbstractInput#take)
45
+ # @return [String]
46
+ def take(n)
47
+ @io.seek(@offset)
48
+
49
+ # Calling @io.read with more than the number of available bytes will
50
+ # return nil, so we have to calculate how many bytes remain
51
+ @io.read((n <= @size) ? n : @size)
52
+ end
53
+
54
+ # (see AbstractInput#at)
55
+ # @return [String]
56
+ def at(n)
57
+ raise ArgumentError, "n must be positive" unless n >= 0
58
+
59
+ @io.seek(@offset + n)
60
+ @io.read(1)
61
+ end
62
+
63
+ # (see AbstractInput#index)
64
+ def index(value)
65
+ @io.seek(@offset)
66
+ length = value.length
67
+
68
+ # We need to start with value != buffer, and this is a reasonable guess
69
+ buffer = "\377" * length
70
+
71
+ until @io.eof?
72
+ buffer.slice!(0)
73
+ buffer << @io.read(1)
74
+
75
+ if buffer == value
76
+ return @io.tell - @offset - length
77
+ end
78
+ end
79
+ end
80
+
81
+ # @group Advancing the Cursor
82
+ ########################################################################
83
+
84
+ # (see AbstractInput#drop)
85
+ def drop(n)
86
+ raise ArgumentError, "n must be positive" unless n >= 0
87
+
88
+ @io.seek(@offset)
89
+ prefix = @io.read(n)
90
+ suffix = @io
91
+
92
+ length = prefix.length
93
+ count = prefix.count("\n")
94
+
95
+ column = unless count.zero?
96
+ length - prefix.rindex("\n")
97
+ else
98
+ @column + length
99
+ end
100
+
101
+ copy(:offset => @offset + length,
102
+ :line => @line + count,
103
+ :column => column,
104
+ :size => @size - length)
105
+ end
106
+
107
+ # @group Testing the Input
108
+ ########################################################################
109
+
110
+ # (see AbstractInput#defined_at?)
111
+ def defined_at?(n)
112
+ n < @size
113
+ end
114
+
115
+ # (see AbstractInput#empty?)
116
+ def empty?
117
+ @io.eof?
118
+ end
119
+
120
+ # @endgroup
121
+ ########################################################################
122
+
123
+ # @return [void]
124
+ def pretty_print(q)
125
+ q.text("FileInput")
126
+ q.group(2, "(", ")") do
127
+ preview = take(4)
128
+ preview = if preview.empty?
129
+ "EOF"
130
+ elsif preview.length <= 3
131
+ preview.inspect
132
+ else
133
+ (preview.take(3) << "...").inspect
134
+ end
135
+
136
+ q.text preview
137
+ q.text " at line #{@line}, column #{@column}, offset #{@offset}, file #{File.basename(@io.path)}"
138
+ end
139
+ end
140
+
141
+ private
142
+
143
+ # @return [FileInput]
144
+ def copy(changes = {})
145
+ FileInput.new \
146
+ changes.fetch(:io, @io),
147
+ changes.fetch(:offset, @offset),
148
+ changes.fetch(:line, @line),
149
+ changes.fetch(:column, @column),
150
+ changes.fetch(:size, @size)
151
+ end
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,30 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ module Input
5
+ end
6
+
7
+ class << Input
8
+ # @group Constructors
9
+ #########################################################################
10
+
11
+ # @return [Input]
12
+ def build(o, *args)
13
+ case o
14
+ when AbstractInput
15
+ o
16
+ when IO
17
+ FileInput.new(o, *args)
18
+ when String, Array
19
+ DelegatedInput.new(o, *args)
20
+ else
21
+ raise TypeError
22
+ end
23
+ end
24
+
25
+ # @endgroup
26
+ #########################################################################
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,69 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ class Position
5
+ include Inspect
6
+
7
+ # @return [Integer]
8
+ attr_reader :offset
9
+
10
+ # @return [Integer]
11
+ attr_reader :line
12
+
13
+ # @return [Integer]
14
+ attr_reader :column
15
+
16
+ # @return [String, Pathname]
17
+ attr_reader :path
18
+
19
+ def initialize(offset, line, column, path)
20
+ @offset, @line, @column, @path =
21
+ offset, line, column, path
22
+ end
23
+
24
+ def copy(changes = {})
25
+ Position.new \
26
+ changes.fetch(:offset, @offset),
27
+ changes.fetch(:line, @line),
28
+ changes.fetch(:column, @column),
29
+ changes.fetch(:path, @path)
30
+ end
31
+
32
+ # @return [String]
33
+ def inspect
34
+ if @path.present?
35
+ "file #{@path}, line #{@line}, column #{@column}"
36
+ else
37
+ "line #{@line}, column #{@column}"
38
+ end
39
+ end
40
+
41
+ # @return [void]
42
+ def pretty_print(q)
43
+ q.text "Position"
44
+ q.group(2, "(", ")") do
45
+ q.breakable ""
46
+ q.text "line #{@line},"
47
+ q.breakable
48
+ q.text "column #{@column},"
49
+ q.breakable
50
+ q.text "offset #{@offset}"
51
+
52
+ unless @path.nil?
53
+ q.text ","
54
+ q.breakable
55
+ q.text "path #{@path}"
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ class << Position
62
+ def caller(offset = 1)
63
+ path, line, method = Stupidedi.caller(offset + 1)
64
+ new(nil, line, nil, path)
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,168 @@
1
+ module Stupidedi
2
+ module Reader
3
+
4
+ module Result
5
+
6
+ # @return [Position]
7
+ def position
8
+ if @remainder.respond_to?(:position)
9
+ @remainder.position
10
+ end
11
+ end
12
+
13
+ # @return [Integer]
14
+ def offset
15
+ if @remainder.respond_to?(:offset)
16
+ @remainder.offset
17
+ end
18
+ end
19
+
20
+ # @return [Integer]
21
+ def line
22
+ if @remainder.respond_to?(:line)
23
+ @remainder.line
24
+ end
25
+ end
26
+
27
+ # @return [Integer]
28
+ def column
29
+ if @remainder.respond_to?(:column)
30
+ @remainder.column
31
+ end
32
+ end
33
+ end
34
+
35
+ class << Result
36
+ # @group Constructors
37
+ #########################################################################
38
+
39
+ # @return [Result::Success]
40
+ def success(value, remainder)
41
+ Success.new(value, remainder)
42
+ end
43
+
44
+ # @return [Result::Failure]
45
+ def failure(reason, remainder, fatal)
46
+ Failure.new(reason, remainder, fatal)
47
+ end
48
+
49
+ # @endgroup
50
+ #########################################################################
51
+ end
52
+
53
+ class Success < Either::Success
54
+ include Result
55
+
56
+ attr_reader :remainder
57
+
58
+ def initialize(value, remainder)
59
+ @value, @remainder = value, remainder
60
+ end
61
+
62
+ # @return [Success]
63
+ def copy(changes = {})
64
+ Success.new \
65
+ changes.fetch(:value, @value),
66
+ changes.fetch(:remainder, @remainder)
67
+ end
68
+
69
+ def fatal?
70
+ false
71
+ end
72
+
73
+ # @return [Boolean]
74
+ def ==(other)
75
+ if other.is_a?(self.class)
76
+ @value == other.value and @remainder == other.remainder
77
+ else
78
+ @value == other
79
+ end
80
+ end
81
+
82
+ # @return [void]
83
+ def pretty_print(q)
84
+ q.text "Result.success"
85
+ q.group(2, "(", ")") do
86
+ q.breakable ""
87
+ q.pp @value
88
+ q.text ","
89
+ q.breakable
90
+ q.pp @remainder
91
+ end
92
+ end
93
+
94
+ # Override {Enumerable#blank?} since we're not really {Enumerable}
95
+ def blank?
96
+ false
97
+ end
98
+
99
+ private
100
+
101
+ def deconstruct(block)
102
+ block.call(@value, @remainder)
103
+ end
104
+
105
+ def failure(reason)
106
+ Failure.new(reason, @remainder, false)
107
+ end
108
+ end
109
+
110
+ class Failure < Either::Failure
111
+ include Result
112
+
113
+ attr_reader :remainder
114
+
115
+ def initialize(reason, remainder, fatal)
116
+ @reason, @remainder, @fatal =
117
+ reason, remainder, fatal
118
+ end
119
+
120
+ # @return [Failure]
121
+ def copy(changes = {})
122
+ Failure.new \
123
+ changes.fetch(:reason, @reason),
124
+ changes.fetch(:remainder, @remainder),
125
+ changes.fetch(:fatal, @fatal)
126
+ end
127
+
128
+ def fatal?
129
+ @fatal
130
+ end
131
+
132
+ def fatal
133
+ copy(:fatal => true)
134
+ end
135
+
136
+ # @return [Boolean]
137
+ def ==(other)
138
+ if other.is_a?(self.class)
139
+ @reason == other.reason
140
+ else
141
+ @reason == other
142
+ end
143
+ end
144
+
145
+ # @return [void]
146
+ def pretty_print(q)
147
+ q.text "Result.failure"
148
+ q.group(2, "(", ")") do
149
+ q.breakable ""
150
+ q.pp @reason
151
+ q.text ","
152
+ q.breakable
153
+ q.pp @remainder
154
+ q.text ","
155
+ q.breakable
156
+ q.text "#{@fatal ? "" : "non-"}fatal"
157
+ end
158
+ end
159
+
160
+ private
161
+
162
+ def deconstruct(block)
163
+ block.call(@reason, @remainder)
164
+ end
165
+ end
166
+
167
+ end
168
+ end