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,399 @@
1
+ require "support/quickcheck"
2
+
3
+ class QuickCheck
4
+
5
+ #
6
+ #
7
+ #
8
+ class SerializedEdi < ::QuickCheck
9
+
10
+ #
11
+ #
12
+ #
13
+ module Macro
14
+ def self.included(base)
15
+ base.extend(ClassMethods)
16
+ end
17
+
18
+ module ClassMethods
19
+ def property(*args, &setup)
20
+ QuickCheck.property(self, *args, &setup)
21
+ end
22
+ end
23
+ end
24
+
25
+ has_parameter :separators,
26
+ Stupidedi::Reader::Separators.new(":", "^", "*", "~")
27
+
28
+ def is_delimiter?(c)
29
+ separators.segment == c or
30
+ separators.element == c or
31
+ separators.component == c or
32
+ separators.repetition == c
33
+ end
34
+
35
+ # @return [Delegators::Char]
36
+ def char
37
+ Delegators::Char.new(self)
38
+ end
39
+
40
+ # @return [Delegators::Stream]
41
+ def stream
42
+ Delegators::Stream.new(self)
43
+ end
44
+
45
+ # @return [Delegators::SimpleElement]
46
+ # @return [String]
47
+ def element(element_def = nil)
48
+ delegator = Delegators::SimpleElement.new(self)
49
+
50
+ if element_def.respond_to?(:min_length)
51
+ min = element_def.min_length
52
+ max = element_def.max_length
53
+ end
54
+
55
+ case element_def
56
+ when nil
57
+ delegator
58
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::Nn
59
+ with(:size, choose([min, max])) { delegator.nn }
60
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::R
61
+ with(:size, choose([min, max])) { delegator.r }
62
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::ID
63
+ with(:size, choose([min, max])) { delegator.id }
64
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::AN
65
+ with(:size, choose([min, max])) { delegator.an }
66
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::DT
67
+ with(:size, choose([min, max])) { delegator.dt }
68
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::TM
69
+ with(:size, choose([min, max])) { delegator.tm }
70
+ when Stupidedi::FiftyTen::Definitions::ElementTypes::CompositeElementDef
71
+ composite(element_def)
72
+ else
73
+ raise ArgumentError
74
+ end
75
+ end
76
+
77
+ # @return [Delegators::CompositeElement]
78
+ # @return [String]
79
+ def composite(element_def = nil)
80
+ case element_def
81
+ when nil
82
+ Delegators::CompositeElement.new(self)
83
+ when Stupidedi::Schema::CompositeElementDef
84
+ # Generate each component element
85
+ elements = element_def.component_element_uses.map do |use|
86
+ if use.required?
87
+ value { element(use.definition) }
88
+ else
89
+ value { choose([element(use.definition), element.blank]) }
90
+ end
91
+ end
92
+
93
+ # Collapse the suffix of blank elements
94
+ suffix, elements = elements.reverse.split_until(&:empty?)
95
+ elements.reverse.join(separators.component)
96
+ else
97
+ raise ArgumentError
98
+ end
99
+ end
100
+
101
+ # @return [Delegators::Segment]
102
+ def segment
103
+ Delegators::Segment.new(self)
104
+ end
105
+
106
+ # @return [Delegators::Document]
107
+ def document
108
+ Delegators::Document.new(self)
109
+ end
110
+
111
+ # @return [Delegators::Current]
112
+ def current
113
+ Delegators::Current.new(self)
114
+ end
115
+
116
+ #
117
+ #
118
+ #
119
+ class Delegator < Stupidedi::BlankSlate
120
+ def initialize(quickcheck)
121
+ @quickcheck = quickcheck
122
+ end
123
+
124
+ private
125
+
126
+ def method_missing(name, *args, &block)
127
+ @quickcheck.__send__(name, *args, &block)
128
+ end
129
+ end
130
+
131
+ #
132
+ #
133
+ #
134
+ module Delegators
135
+
136
+ #
137
+ #
138
+ #
139
+ class Char < Delegator
140
+
141
+ # Generate a single basic character
142
+ #
143
+ # @return [Character]
144
+ def basic
145
+ choose(Stupidedi::Reader.basic_characters).tap{|c| guard(!is_delimiter?(c)) }
146
+ end
147
+
148
+ # Generate a single control character
149
+ #
150
+ # @return [Character]
151
+ def control
152
+ choose(Stupidedi::Reader.control_characters).tap{|c| guard(!is_delimiter?(c)) }
153
+ end
154
+
155
+ # Generate a single extended character
156
+ #
157
+ # @return [Character]
158
+ def extended
159
+ choose(Stupidedi::Reader.extended_characters).tap{|c| guard(!is_delimiter?(c)) }
160
+ end
161
+
162
+ # Generate a single delimiter character
163
+ #
164
+ # @return [Character]
165
+ def delimiter
166
+ choose [separators.segment,
167
+ separators.element,
168
+ separators.component,
169
+ separators.repetition]
170
+ end
171
+ end
172
+
173
+ #
174
+ #
175
+ #
176
+ class Stream < Delegator
177
+
178
+ # Generate a sized string of control characters
179
+ #
180
+ # @return [String]
181
+ def control
182
+ (1..size).inject(""){|s,_| s << char.control }
183
+ end
184
+
185
+ # Generate a sized string of basic characters
186
+ #
187
+ # @return [String]
188
+ def basic
189
+ (1..size).inject(""){|s,_| s << char.basic }
190
+ end
191
+
192
+ # Generate a sized string of extended characters
193
+ #
194
+ # @return [String]
195
+ def extended
196
+ (1..size).inject(""){|s,_| s << char.extended }
197
+ end
198
+
199
+ # Generate a sized string of spaces
200
+ #
201
+ # @return [String]
202
+ def space(length = size)
203
+ " " * length
204
+ end
205
+
206
+ # Randomly insert control characters into the string
207
+ #
208
+ # @return [String]
209
+ def agitate(string)
210
+ cs = string.split(//)
211
+
212
+ # Generate `cs.length + 1` control characters
213
+ xs = (0..cs.length).inject([]){|s,_| s << choose(["", char.control]) }
214
+
215
+ agitated = ""
216
+ xs.zip(cs){|pad, c| agitated << pad << c.to_s }
217
+
218
+ agitated
219
+ end
220
+
221
+ # Pad the ends of the string with sized random spaces. The combined
222
+ # length of the left and right padding is `sized`
223
+ #
224
+ # @return [String]
225
+ def pad(string)
226
+ left = space(between(0, size))
227
+ right = space(between(0, size - left.length))
228
+ left << string << right
229
+ end
230
+ end
231
+
232
+ #
233
+ #
234
+ #
235
+ class SimpleElement < Delegator
236
+
237
+ # Generate a string representing a blank element
238
+ #
239
+ # @return [String]
240
+ def blank
241
+ ""
242
+ end
243
+
244
+ # Generate a sized string representing a non-empty numeric element (Nn).
245
+ # The leading sign character is not counted against `size`
246
+ #
247
+ # @return [String]
248
+ def nn
249
+ choose(["", "+", "-"]) << string(:digit)
250
+ end
251
+
252
+ # Generate a sized string representing a non-empty decimal element (R).
253
+ # The leading sign character, optional exponent (E) indicator and its
254
+ # sign character are not counted against `size`
255
+ #
256
+ # @return [String]
257
+ def r(length = size)
258
+ decimal = with(:size, between(0, length)) { string(:digit) }
259
+ exponent = with(:size, between(0, decimal.length)) { string(:digit) }
260
+ whole = with(:size, length - decimal.length - exponent.length) { string(:digit) }
261
+
262
+ decimal =
263
+ if decimal.empty?
264
+ choose(["", "."])
265
+ else
266
+ ".#{decimal}"
267
+ end
268
+
269
+ unless exponent.empty?
270
+ exponent = "E#{choose(["", "-", "+"])}#{exponent}"
271
+ end
272
+
273
+ whole = "#{choose(["", "-", "+"])}#{whole}"
274
+
275
+ "#{whole}#{decimal}#{exponent}"
276
+ end
277
+
278
+ # Generate a sized string representing an identifier element (ID)
279
+ #
280
+ # @return [String]
281
+ def id
282
+ (1..size).inject("") do |s,_|
283
+ s << choose([char.basic, char.extended])
284
+ end.tap{|s| guard(!s.blank?) }
285
+ end
286
+
287
+ # Generate a sized string representing a string element (AN)
288
+ #
289
+ # @return [String]
290
+ def an
291
+ (1..size).inject("") do |s,_|
292
+ s << choose([char.basic, char.extended])
293
+ end.tap{|s| guard(!s.blank?) }
294
+ end
295
+
296
+ # Generate a sized string representing a date (DT)
297
+ #
298
+ # @return [String]
299
+ def dt
300
+ year = between(0, 9999)
301
+ month = between(1, 12)
302
+ day = between(1, 31)
303
+
304
+ # Ensure this is a valid date
305
+ guard(begin Date.civil(year, month, day); rescue ArgumentError; false end)
306
+
307
+ case size
308
+ when 6 then "%02d%02d%02d" % [year.modulo(100), month, day]
309
+ when 8 then "%04d%02d%02d" % [year, month, day]
310
+ else raise "Size must be 6 or 8, but it is #{size}"
311
+ end
312
+ end
313
+
314
+ # Generate a sized string representing a time (TM)
315
+ #
316
+ # @return [String]
317
+ def tm
318
+ case size
319
+ when 2 then "%02d" % between(0, 23)
320
+ when 4 then "%02d%02d" % [between(0, 23).abs, between(0, 59).abs]
321
+ else
322
+ raise "Size must be 2, 4, 6, or greater than 6, but it is #{size}" if size < 6
323
+ hour = between(0, 23)
324
+ minute = between(0, 59)
325
+ second = between(0, 59)
326
+ fract = with(:size, size - 6) { string(:digit) }
327
+ "%02d%02d%02d%s" % [hour, minute, second, fract]
328
+ end
329
+ end
330
+ end
331
+
332
+ #
333
+ #
334
+ #
335
+ class CompositeElement < Delegator
336
+ # @todo
337
+ end
338
+
339
+ #
340
+ #
341
+ #
342
+ class Segment < Delegator
343
+
344
+ # @private
345
+ SEGMENT_ID = /^[A-Z][A-Z0-9]{1,2}$/
346
+
347
+ def generate(name, *elements)
348
+ # @todo
349
+ end
350
+
351
+ private
352
+
353
+ def method_missing(name, *arguments, &block)
354
+ if SEGMENT_ID =~ name.to_s
355
+ generate(name)
356
+ else
357
+ super
358
+ end
359
+ end
360
+ end
361
+
362
+ #
363
+ #
364
+ #
365
+ class Document < Delegator
366
+
367
+ # Generate four random delimiters with the restriction that they cannot
368
+ # be control characters, spaces, tabs, numbers, letters, underscores, or
369
+ # numerical symbols, and each delimiter must be unique.
370
+ #
371
+ # @return [Reader::Separators]
372
+ def delimiters
373
+ possible = Stupidedi::Reader.basic_characters
374
+ possible << Stupidedi::Reader.extended_characters
375
+ possible -= QuickCheck::Characters.of(/[ \t0-9a-z_.+-]/i)
376
+
377
+ delimiters = []
378
+
379
+ 4.times do
380
+ delimiters << value do
381
+ choose(possible).tap{|x| guard(!delimiters.include?(x)) }
382
+ end
383
+ end
384
+
385
+ Stupidedi::Reader::Sepatarors.new(*delimiters)
386
+ end
387
+ end
388
+
389
+ #
390
+ #
391
+ #
392
+ class Current < Delegator
393
+ # @todo
394
+ end
395
+
396
+ end
397
+
398
+ end
399
+ end
@@ -0,0 +1,302 @@
1
+ #
2
+ # This class is designed to be subclassed, to avoid polluting the minimal
3
+ # base class. Subclasses can add parameters with the macro "has_parameter",
4
+ # and parameters are inherited when subclassing.
5
+ #
6
+ # @see https://github.com/hayeah/rantly
7
+ #
8
+ class QuickCheck
9
+ autoload :Characters, "support/quickcheck/characters"
10
+ autoload :Property, "support/quickcheck/property"
11
+
12
+ def initialize
13
+ @bindings = []
14
+ end
15
+ end
16
+
17
+ class << QuickCheck
18
+ def property(base, *args, &setup)
19
+ QuickCheck::Property.new(base, new, *args, &setup)
20
+ end
21
+
22
+ # Generate `count` values, returning nil
23
+ def each(count, limit = 10, &block)
24
+ new.each(count, limit, &block)
25
+ end
26
+
27
+ # Generate an array of `count` values
28
+ def map(count, limit = 10, &block)
29
+ new.map(count, limit, &block)
30
+ end
31
+
32
+ # Generate a single value
33
+ def value(limit = 10, &block)
34
+ new.value(limit, &block)
35
+ end
36
+
37
+ def generate(count, limit, setup, &block)
38
+ new.generate(count, limit, setup, &block)
39
+ end
40
+
41
+ # @return [Class]
42
+ def default
43
+ @default ||= (superclass == Object) ?
44
+ Class.new.new :
45
+ Class.new(superclass).new
46
+ end
47
+
48
+ # @return [void]
49
+ def has_parameter(name, value)
50
+ scope = self
51
+ define_method(name) { instance_variable_get("@_parameter_#{name}") || scope.default.send(name) }
52
+ default.class.send(:define_method, name) { value }
53
+ end
54
+ end
55
+
56
+ class QuickCheck
57
+ module Macro
58
+ def self.included(base)
59
+ base.extend(ClassMethods)
60
+ end
61
+
62
+ module ClassMethods
63
+ def property(*args, &setup)
64
+ QuickCheck.property(self, *args, &setup)
65
+ end
66
+ end
67
+ end
68
+
69
+ class GuardFailure < StandardError; end
70
+
71
+ class NoMoreTries < StandardError
72
+
73
+ # @return [Integer]
74
+ attr_reader :limit
75
+
76
+ # @return [Integer]
77
+ attr_reader :tries
78
+
79
+ def initialize(limit, tries)
80
+ @limit, @tries = limit, tries
81
+ end
82
+
83
+ # @return [String]
84
+ def to_s
85
+ "Exceeded limit #{limit}: #{tries} failed guards"
86
+ end
87
+ end
88
+
89
+ # Controls the size of sized generators: array, string
90
+ has_parameter :size, 6
91
+
92
+ # Generate `count` values, returning nil
93
+ def each(count, limit = 10, &setup)
94
+ generate(count, limit, setup)
95
+ end
96
+
97
+ # Generate an array of `count` values
98
+ def map(count, limit = 10, &setup)
99
+ acc = []; generate(count, limit, setup) {|x| acc << x }; acc
100
+ end
101
+
102
+ # Generate a single value
103
+ def value(limit = 10, &setup)
104
+ generate(1, limit, setup) {|x| return x }
105
+ end
106
+
107
+ def generate(count, limit, setup, &block)
108
+ retries = count * limit
109
+ failures = successes = 0
110
+
111
+ @bindings.push(eval("self", block.binding))
112
+
113
+ while successes < count
114
+ raise NoMoreTries.new(count * limit, failures) if retries < 0
115
+
116
+ begin
117
+ retries -= 1
118
+ value = instance_eval(&setup)
119
+ rescue GuardFailure
120
+ failures += 1
121
+ else
122
+ successes += 1
123
+ yield(value) if block_given?
124
+ end
125
+ end
126
+
127
+ @bindings.pop
128
+ end
129
+
130
+ def guard(condition)
131
+ raise GuardFailure unless condition
132
+ end
133
+
134
+ # Called with a block, sets `parameters` temporarily while evaluating the
135
+ # block, and returns the value of the block. Without a block, this permanently
136
+ # sets `parameters`
137
+ def with(*parameters)
138
+ parameters = Hash[*parameters]
139
+
140
+ if block_given?
141
+ # Copy current parameters to a safe place
142
+ prev = instance_variables.grep(/@_parameter/).inject({}) do |hash, name|
143
+ hash.update(name => instance_variable_get(name))
144
+ end
145
+
146
+ # Update the given parameters
147
+ parameters.each{|name, value| instance_variable_set("@_parameter_#{name}", value) }
148
+
149
+ begin
150
+ yield
151
+ ensure
152
+ # Remove all the parameters
153
+ instance_variables.each do |name|
154
+ next unless /^@_parameter_/ =~ name
155
+ remove_instance_variable(name)
156
+ end
157
+
158
+ # Restore previous parameters from the copy
159
+ prev.each{|name, value| instance_variable_set(name, value) }
160
+ end
161
+ else
162
+ parameters.each{|name, value| instance_variable_set("@_parameter_#{name}", value) }
163
+ end
164
+ end
165
+
166
+ INTMIN = 2 ** (0.size * 8 - 2) - 1
167
+ INTMAX = -INTMIN + 1
168
+
169
+ # Returns the given parameter
170
+ def literal(x); x end
171
+
172
+ # Generates an integer
173
+ def integer(magnitude = nil)
174
+ case magnitude
175
+ when Range then between(magnitude.end, magnitude.begin)
176
+ when Integer then between(magnitude, -magnitude)
177
+ else between(INTMAX, INTMIN) end
178
+ end
179
+
180
+ # Generates a float
181
+ alias float rand
182
+
183
+ # Generates a value between the given range
184
+ def between(lo, hi = nil)
185
+ case lo
186
+ when Numeric
187
+ rand(hi + 1 - lo) + lo
188
+ when Range
189
+ # @todo: #to_a is wasteful for large Ranges
190
+ lo.to_a.bind{|a| a[between(0, a.length - 1)] }
191
+ end
192
+ end
193
+
194
+ # Generates true or false
195
+ def boolean
196
+ rand(2) == 0
197
+ end
198
+
199
+ # Generates a sized array by iteratively evaluating `block`
200
+ def array(&block)
201
+ @bindings.push(eval("self", block.binding))
202
+
203
+ (1..size).inject([]) {|a,_| a << instance_eval(&block) }.tap do
204
+ @bindings.pop
205
+ end
206
+ end
207
+
208
+ # Generates a character the given character class
209
+ def character(type = :print)
210
+ chars = case type
211
+ when Regexp then Characters.of(type)
212
+ when Symbol then Characters::CLASSES[type] end
213
+
214
+ raise ArgumentError, "unrecognized character type #{type.inspect}" unless chars
215
+ choose(chars)
216
+ end
217
+
218
+ # Generates a sized string of the given character class
219
+ def string(type = :print)
220
+ chars = case type
221
+ when Regexp then Characters.of(type)
222
+ when Symbol then Characters::CLASSES[type] end
223
+
224
+ raise ArgumentError, "unrecognized character type #{type.inspect}" unless chars
225
+ acc = ""; size.times { acc << choose(chars) }; acc
226
+ end
227
+
228
+ # Generate a weighted value by calling the tail of each element
229
+ #
230
+ # @example
231
+ # freq [1, :literal, "one"],
232
+ # [2, :string],
233
+ # [3, :string, :alpha],
234
+ # [4, [:string, :alpha]],
235
+ # [5, lambda{ with(:size, 2) { string }}],
236
+ # [6, lambda{|x| with(:size, x) { string }}, 2]
237
+ def freq(*pairs)
238
+ total = 0
239
+ pairs = pairs.map do |p|
240
+ case p
241
+ when Symbol, String, Proc
242
+ total += 1; [1, p]
243
+ when Array
244
+ total += p.head; p
245
+ end
246
+ end
247
+
248
+ index = between(1, total)
249
+ pairs.each do |p|
250
+ weight, generator, *args = p
251
+ if index <= weight
252
+ return call(generator, *args)
253
+ else
254
+ index -= weight
255
+ end
256
+ end
257
+ end
258
+
259
+ # Generates an element from the given array of values
260
+ def choose(values)
261
+ values[between(0, values.length - 1)]
262
+ end
263
+
264
+ # Executes `call` on a random element from the given array of values
265
+ def branch(generators)
266
+ call(choose(generators))
267
+ end
268
+
269
+ # Executes the given generator
270
+ #
271
+ # @example
272
+ # call(:integer)
273
+ # call(:choose, [1,2,3])
274
+ # call([:choose, [1,2,3]])
275
+ # call(lambda { choose([1,2,3]) }
276
+ def call(generator, *args)
277
+ case generator
278
+ when Symbol, String
279
+ send(generator, *args)
280
+ when Array
281
+ send(generator.head, *generator.tail)
282
+ when Proc
283
+ @bindings.push(eval("self", generate.binding))
284
+
285
+ instance_eval { generator.call(*args) }.tap do
286
+ @bindings.pop
287
+ end
288
+ else
289
+ raise ArgumentError, "unrecognized generator type #{generator.inspect}"
290
+ end
291
+ end
292
+
293
+ private
294
+
295
+ def method_missing(name, *args, &block)
296
+ unless @bindings.empty?
297
+ @bindings.last.__send__(name, *args, &block)
298
+ else
299
+ super
300
+ end
301
+ end
302
+ end