tediparse 2.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +319 -0
- data/LICENSE +26 -0
- data/README.md +308 -0
- data/Rakefile +33 -0
- data/bin/tediparse +102 -0
- data/doc/Defining.md +97 -0
- data/doc/Generating-Grammars.md +241 -0
- data/doc/Generating.md +332 -0
- data/doc/Navigating.md +670 -0
- data/doc/Parsing.md +133 -0
- data/doc/README.md +51 -0
- data/doc/Serializing.md +100 -0
- data/doc/Tokenizing.md +136 -0
- data/doc/Validating.md +140 -0
- data/lib/ruby/array.rb +226 -0
- data/lib/ruby/blank.rb +52 -0
- data/lib/ruby/exception.rb +14 -0
- data/lib/ruby/hash.rb +14 -0
- data/lib/ruby/module.rb +60 -0
- data/lib/ruby/object.rb +56 -0
- data/lib/ruby/string.rb +89 -0
- data/lib/ruby/to_d.rb +82 -0
- data/lib/ruby/to_date.rb +26 -0
- data/lib/ruby/to_time.rb +21 -0
- data/lib/ruby/try.rb +46 -0
- data/lib/stupidedi/builder.rb +6 -0
- data/lib/stupidedi/color.rb +94 -0
- data/lib/stupidedi/config/code_list_config.rb +45 -0
- data/lib/stupidedi/config/functional_group_config.rb +72 -0
- data/lib/stupidedi/config/interchange_config.rb +86 -0
- data/lib/stupidedi/config/transaction_set_config.rb +73 -0
- data/lib/stupidedi/config.rb +100 -0
- data/lib/stupidedi/either.rb +286 -0
- data/lib/stupidedi/exceptions/invalid_element_error.rb +7 -0
- data/lib/stupidedi/exceptions/invalid_schema_error.rb +7 -0
- data/lib/stupidedi/exceptions/missing_grammar_error.rb +50 -0
- data/lib/stupidedi/exceptions/output_error.rb +7 -0
- data/lib/stupidedi/exceptions/parse_error.rb +7 -0
- data/lib/stupidedi/exceptions/stupidedi_error.rb +7 -0
- data/lib/stupidedi/exceptions/tokenize_error.rb +7 -0
- data/lib/stupidedi/exceptions/zipper_error.rb +7 -0
- data/lib/stupidedi/exceptions.rb +13 -0
- data/lib/stupidedi/inspect.rb +26 -0
- data/lib/stupidedi/interchanges/element_types/separator_val.rb +79 -0
- data/lib/stupidedi/interchanges/element_types/special_val.rb +48 -0
- data/lib/stupidedi/interchanges/element_types.rb +11 -0
- data/lib/stupidedi/interchanges.rb +21 -0
- data/lib/stupidedi/parser/builder_dsl.rb +292 -0
- data/lib/stupidedi/parser/constraint_table.rb +566 -0
- data/lib/stupidedi/parser/generation.rb +147 -0
- data/lib/stupidedi/parser/identifier_stack.rb +248 -0
- data/lib/stupidedi/parser/instruction.rb +112 -0
- data/lib/stupidedi/parser/instruction_table.rb +222 -0
- data/lib/stupidedi/parser/navigation.rb +786 -0
- data/lib/stupidedi/parser/state_machine.rb +62 -0
- data/lib/stupidedi/parser/states/abstract_state.rb +385 -0
- data/lib/stupidedi/parser/states/failure_state.rb +69 -0
- data/lib/stupidedi/parser/states/functional_group_state.rb +101 -0
- data/lib/stupidedi/parser/states/initial_state.rb +62 -0
- data/lib/stupidedi/parser/states/interchange_state.rb +96 -0
- data/lib/stupidedi/parser/states/loop_state.rb +74 -0
- data/lib/stupidedi/parser/states/table_state.rb +90 -0
- data/lib/stupidedi/parser/states/transaction_set_state.rb +120 -0
- data/lib/stupidedi/parser/states/transmission_state.rb +59 -0
- data/lib/stupidedi/parser/tokenization.rb +195 -0
- data/lib/stupidedi/parser.rb +32 -0
- data/lib/stupidedi/reader/input/abstract_input.rb +137 -0
- data/lib/stupidedi/reader/input/delegated_input.rb +112 -0
- data/lib/stupidedi/reader/input/file_input.rb +157 -0
- data/lib/stupidedi/reader/input.rb +31 -0
- data/lib/stupidedi/reader/position.rb +78 -0
- data/lib/stupidedi/reader/result.rb +172 -0
- data/lib/stupidedi/reader/segment_dict.rb +176 -0
- data/lib/stupidedi/reader/separators.rb +90 -0
- data/lib/stupidedi/reader/stream_reader.rb +173 -0
- data/lib/stupidedi/reader/token_reader.rb +465 -0
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +71 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +85 -0
- data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +76 -0
- data/lib/stupidedi/reader.rb +121 -0
- data/lib/stupidedi/schema/abstract_def.rb +76 -0
- data/lib/stupidedi/schema/abstract_element_def.rb +35 -0
- data/lib/stupidedi/schema/abstract_element_use.rb +47 -0
- data/lib/stupidedi/schema/abstract_use.rb +79 -0
- data/lib/stupidedi/schema/code_list.rb +99 -0
- data/lib/stupidedi/schema/component_element_use.rb +76 -0
- data/lib/stupidedi/schema/composite_element_def.rb +103 -0
- data/lib/stupidedi/schema/composite_element_use.rb +78 -0
- data/lib/stupidedi/schema/element_req.rb +57 -0
- data/lib/stupidedi/schema/functional_group_def.rb +124 -0
- data/lib/stupidedi/schema/generation/definition_generator.rb +139 -0
- data/lib/stupidedi/schema/generation/element_generator.rb +221 -0
- data/lib/stupidedi/schema/generation/flat_file_reader.rb +551 -0
- data/lib/stupidedi/schema/generation/functional_group_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/interchange_generator.rb +145 -0
- data/lib/stupidedi/schema/generation/master_loader_generator.rb +121 -0
- data/lib/stupidedi/schema/generation/models.rb +85 -0
- data/lib/stupidedi/schema/generation/module_loader_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/registration_generator.rb +230 -0
- data/lib/stupidedi/schema/generation/runner.rb +161 -0
- data/lib/stupidedi/schema/generation/segment_generator.rb +130 -0
- data/lib/stupidedi/schema/generation/support.rb +78 -0
- data/lib/stupidedi/schema/generation/support_modules_generator.rb +126 -0
- data/lib/stupidedi/schema/generation/version_modules.rb +35 -0
- data/lib/stupidedi/schema/generation.rb +94 -0
- data/lib/stupidedi/schema/interchange_def.rb +103 -0
- data/lib/stupidedi/schema/loop_def.rb +156 -0
- data/lib/stupidedi/schema/repeat_count.rb +86 -0
- data/lib/stupidedi/schema/segment_def.rb +122 -0
- data/lib/stupidedi/schema/segment_req.rb +46 -0
- data/lib/stupidedi/schema/segment_use.rb +99 -0
- data/lib/stupidedi/schema/simple_element_def.rb +51 -0
- data/lib/stupidedi/schema/simple_element_use.rb +83 -0
- data/lib/stupidedi/schema/syntax_note.rb +52 -0
- data/lib/stupidedi/schema/table_def.rb +178 -0
- data/lib/stupidedi/schema/transaction_set_def.rb +125 -0
- data/lib/stupidedi/schema.rb +30 -0
- data/lib/stupidedi/sets.rb +42 -0
- data/lib/stupidedi/transaction_sets/builder/dsl.rb +192 -0
- data/lib/stupidedi/transaction_sets/builder.rb +188 -0
- data/lib/stupidedi/transaction_sets/common/implementations/element_reqs.rb +37 -0
- data/lib/stupidedi/transaction_sets/common/implementations/segment_reqs.rb +31 -0
- data/lib/stupidedi/transaction_sets/common/implementations.rb +11 -0
- data/lib/stupidedi/transaction_sets/common.rb +8 -0
- data/lib/stupidedi/transaction_sets/validation/ambiguity.rb +395 -0
- data/lib/stupidedi/transaction_sets/validation/implementation.rb +12 -0
- data/lib/stupidedi/transaction_sets/validation.rb +9 -0
- data/lib/stupidedi/transaction_sets.rb +25 -0
- data/lib/stupidedi/values/abstract_element_val.rb +19 -0
- data/lib/stupidedi/values/abstract_val.rb +133 -0
- data/lib/stupidedi/values/composite_element_val.rb +102 -0
- data/lib/stupidedi/values/functional_group_val.rb +105 -0
- data/lib/stupidedi/values/interchange_val.rb +102 -0
- data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
- data/lib/stupidedi/values/invalid_segment_val.rb +89 -0
- data/lib/stupidedi/values/loop_val.rb +73 -0
- data/lib/stupidedi/values/repeated_element_val.rb +113 -0
- data/lib/stupidedi/values/segment_val.rb +105 -0
- data/lib/stupidedi/values/segment_val_group.rb +20 -0
- data/lib/stupidedi/values/simple_element_val.rb +80 -0
- data/lib/stupidedi/values/table_val.rb +69 -0
- data/lib/stupidedi/values/transaction_set_val.rb +69 -0
- data/lib/stupidedi/values/transmission_val.rb +56 -0
- data/lib/stupidedi/values.rb +22 -0
- data/lib/stupidedi/version.rb +4 -0
- data/lib/stupidedi/versions/common/element_reqs.rb +13 -0
- data/lib/stupidedi/versions/common/element_types/an.rb +386 -0
- data/lib/stupidedi/versions/common/element_types/dt.rb +572 -0
- data/lib/stupidedi/versions/common/element_types/id.rb +304 -0
- data/lib/stupidedi/versions/common/element_types/nn.rb +312 -0
- data/lib/stupidedi/versions/common/element_types/operators.rb +128 -0
- data/lib/stupidedi/versions/common/element_types/r.rb +342 -0
- data/lib/stupidedi/versions/common/element_types/simple_element.rb +73 -0
- data/lib/stupidedi/versions/common/element_types/tm.rb +347 -0
- data/lib/stupidedi/versions/common/element_types.rb +29 -0
- data/lib/stupidedi/versions/common/segment_reqs.rb +15 -0
- data/lib/stupidedi/versions/common/syntax_notes.rb +172 -0
- data/lib/stupidedi/versions/common.rb +11 -0
- data/lib/stupidedi/versions.rb +25 -0
- data/lib/stupidedi/writer/claredi.rb +178 -0
- data/lib/stupidedi/writer/default.rb +119 -0
- data/lib/stupidedi/writer.rb +7 -0
- data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
- data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
- data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
- data/lib/stupidedi/zipper/memoized_cursor.rb +133 -0
- data/lib/stupidedi/zipper/path.rb +132 -0
- data/lib/stupidedi/zipper/root_cursor.rb +120 -0
- data/lib/stupidedi/zipper/stack_cursor.rb +107 -0
- data/lib/stupidedi/zipper.rb +45 -0
- data/lib/stupidedi.rb +69 -0
- data/lib/tediparse.rb +1 -0
- metadata +249 -0
data/lib/ruby/array.rb
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Array do
|
|
5
|
+
def blank?
|
|
6
|
+
empty?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def present?
|
|
10
|
+
not empty?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Return the first item. Raises an `IndexError` if the Array is `empty?`.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# [1, 2, 3].head #=> 1
|
|
17
|
+
#
|
|
18
|
+
def head
|
|
19
|
+
raise IndexError, "head of empty array" if empty?
|
|
20
|
+
x, = self
|
|
21
|
+
x
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# True if `#at` is defined for the given `n`
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# [1, 2, 3].defined_at?(0) #=> true
|
|
28
|
+
# [].defined_at?(0) #=> false
|
|
29
|
+
#
|
|
30
|
+
def defined_at?(n)
|
|
31
|
+
n < length and -n <= length
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @group Selection
|
|
35
|
+
#############################################################################
|
|
36
|
+
|
|
37
|
+
# Selects all elements except the first.
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# [1, 2, 3].tail #=> [2, 3]
|
|
41
|
+
# [1].tail #=> []
|
|
42
|
+
# [].tail #=> []
|
|
43
|
+
#
|
|
44
|
+
# @return [Array]
|
|
45
|
+
def tail
|
|
46
|
+
_, *xs = self
|
|
47
|
+
xs
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Selects all elements except the last `n` ones.
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# [1, 2, 3].init #=> [1, 2]
|
|
54
|
+
# [1, 2, 3].init(2) #=> [1]
|
|
55
|
+
# [].tail #=> []
|
|
56
|
+
#
|
|
57
|
+
# @return [Array]
|
|
58
|
+
def init(n = 1)
|
|
59
|
+
raise ArgumentError, "n cannot be negative" if n < 0
|
|
60
|
+
slice(0..-(n + 1)) or []
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Select all elements except the first `n` ones.
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
# [1, 2, 3].drop(1) #=> [2, 3]
|
|
67
|
+
# [1, 3, 3].drop(2) #=> [3]
|
|
68
|
+
# [].drop(10) #=> []
|
|
69
|
+
#
|
|
70
|
+
# @return [Array]
|
|
71
|
+
def drop(n)
|
|
72
|
+
raise ArgumentError, "n cannot be negative" if n < 0
|
|
73
|
+
slice(n..-1) or []
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Select the first `n` elements.
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# [1, 2, 3].take(2) #=> [1, 2]
|
|
80
|
+
# [1, 2, 3].take(0) #=> []
|
|
81
|
+
#
|
|
82
|
+
# @return [Array]
|
|
83
|
+
def take(n)
|
|
84
|
+
raise ArgumentError, "n cannot be negative" if n < 0
|
|
85
|
+
slice(0, n) or []
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Split the array in two at the given position.
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# [1, 2, 3].split_at(2) #=> [[1,2], [3]]
|
|
92
|
+
# [1, 2, 3].split_at(0) #=> [[], [1,2,3]]
|
|
93
|
+
#
|
|
94
|
+
# @return [(Array, Array)]
|
|
95
|
+
def split_at(n)
|
|
96
|
+
n = length + n if n < 0
|
|
97
|
+
return take(n), drop(n)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @endgroup
|
|
101
|
+
#############################################################################
|
|
102
|
+
|
|
103
|
+
# @group Filtering
|
|
104
|
+
#############################################################################
|
|
105
|
+
|
|
106
|
+
# Drops the longest prefix of elements that satisfy the predicate.
|
|
107
|
+
#
|
|
108
|
+
# @return [Array]
|
|
109
|
+
def drop_while(&block)
|
|
110
|
+
# This is in tail call form
|
|
111
|
+
if not empty? and yield(head)
|
|
112
|
+
tail.drop_while(&block)
|
|
113
|
+
else
|
|
114
|
+
self
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Drops the longest prefix of elements that do not satisfy the predicate.
|
|
119
|
+
#
|
|
120
|
+
# @return [Array]
|
|
121
|
+
def drop_until(&block)
|
|
122
|
+
# This is in tail call form
|
|
123
|
+
unless empty? or yield(head)
|
|
124
|
+
tail.drop_until(&block)
|
|
125
|
+
else
|
|
126
|
+
self
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Takes the longest prefix of elements that satisfy the predicate.
|
|
131
|
+
#
|
|
132
|
+
# @return [Array]
|
|
133
|
+
def take_while(accumulator = [], &block)
|
|
134
|
+
# This is in tail call form
|
|
135
|
+
if not empty? and yield(head)
|
|
136
|
+
tail.take_while(head.snoc(accumulator), &block)
|
|
137
|
+
else
|
|
138
|
+
accumulator
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Takes the longest prefix of elements that do not satisfy the predicate.
|
|
143
|
+
#
|
|
144
|
+
# @return [Array]
|
|
145
|
+
def take_until(accumulator = [], &block)
|
|
146
|
+
# This is in tail call form
|
|
147
|
+
unless empty? or yield(head)
|
|
148
|
+
tail.take_until(head.snoc(accumulator), &block)
|
|
149
|
+
else
|
|
150
|
+
accumulator
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Splits the array into prefix/suffix pair according to the predicate.
|
|
155
|
+
#
|
|
156
|
+
# @return [(Array, Array)]
|
|
157
|
+
def split_until(&block)
|
|
158
|
+
prefix = take_while(&block)
|
|
159
|
+
suffix = drop(prefix.length)
|
|
160
|
+
return prefix, suffix
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Splits the array into prefix/suffix pair according to the predicate.
|
|
164
|
+
#
|
|
165
|
+
# @return [(Array, Array)]
|
|
166
|
+
def split_when(&block)
|
|
167
|
+
prefix = take_until(&block)
|
|
168
|
+
suffix = drop(prefix.length)
|
|
169
|
+
return prefix, suffix
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Returns a list of sublists, where each sublist contains only equal
|
|
173
|
+
# elements. Equality is determined by a two-argument block parameter.
|
|
174
|
+
# The concatenation of the result is equal to the original argument.
|
|
175
|
+
#
|
|
176
|
+
# @example
|
|
177
|
+
# "abba".split(//).group_seq(&:==) #=> [["y"], ["a"], ["b", "b"], ["a"]]
|
|
178
|
+
#
|
|
179
|
+
# @return [[Array]]
|
|
180
|
+
def runs(&block)
|
|
181
|
+
unless empty?
|
|
182
|
+
as, bs = tail.split_until{|x| block.call(head, x) }
|
|
183
|
+
head.cons(as).cons(bs.runs(&block))
|
|
184
|
+
else
|
|
185
|
+
[]
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# @endgroup
|
|
190
|
+
#############################################################################
|
|
191
|
+
|
|
192
|
+
# Accumulate elements using the `+` method, optionally
|
|
193
|
+
# transforming them first using a block
|
|
194
|
+
#
|
|
195
|
+
# @example
|
|
196
|
+
# ["a", "b", "cd"].sum #=> "abcd"
|
|
197
|
+
# ["a", "b", "cd"].sum(&:length) #=> 4
|
|
198
|
+
#
|
|
199
|
+
def sum(&block)
|
|
200
|
+
if block_given?
|
|
201
|
+
tail.inject(yield(head)){|sum,e| sum + yield(e) }
|
|
202
|
+
else
|
|
203
|
+
tail.inject(head){|sum,e| sum + e }
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Count the number of elements that satisfy the predicate
|
|
208
|
+
#
|
|
209
|
+
# @example
|
|
210
|
+
# ["abc", "de", "fg", "hi"].count{|s| s.length == 2 } #=> 3
|
|
211
|
+
# ["a", "b", "a", "c", "a"].count("a") #=> 3
|
|
212
|
+
# [1, 3, 5, 9, 0].count #=> 5
|
|
213
|
+
#
|
|
214
|
+
# @return [Integer]
|
|
215
|
+
def count(*args)
|
|
216
|
+
if block_given?
|
|
217
|
+
inject(0){|n, e| yield(e) ? n + 1 : n }
|
|
218
|
+
elsif args.empty?
|
|
219
|
+
size
|
|
220
|
+
else
|
|
221
|
+
inject(0){|n, e| e == args.first ? n + 1 : n }
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
data/lib/ruby/blank.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine String do
|
|
5
|
+
# True if the string is `empty?` or contains all whitespace
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# "abc".blank? #=> false
|
|
9
|
+
# " ".blank? #=> true
|
|
10
|
+
# "".blank? #=> true
|
|
11
|
+
#
|
|
12
|
+
def blank?
|
|
13
|
+
self !~ /\S/
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def present?
|
|
17
|
+
self =~ /\S/
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
refine NilClass do
|
|
22
|
+
# Always `true`. Note this overrides {Object#blank?} which returns false.
|
|
23
|
+
#
|
|
24
|
+
# @example
|
|
25
|
+
# nil.blank? #=> true
|
|
26
|
+
#
|
|
27
|
+
def blank?
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def present?
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
refine Object do
|
|
37
|
+
# Always `false`. Note that {NilClass#blank?} is overridden to return `true`
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# false.blank? #=> false
|
|
41
|
+
# 100.blank? #=> false
|
|
42
|
+
#
|
|
43
|
+
def blank?
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def present?
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Exception do
|
|
5
|
+
def print(name: nil, io: $stderr)
|
|
6
|
+
ansi = Stupidedi::Color.ansi
|
|
7
|
+
io.puts "warning: #{ansi.red("#{self.class} #{message}")}"
|
|
8
|
+
io.puts " module: #{name}" unless name.nil?
|
|
9
|
+
io.puts backtrace.map{|x| " " + x}.join("\n")
|
|
10
|
+
io.puts
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/ruby/hash.rb
ADDED
data/lib/ruby/module.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Module do
|
|
5
|
+
# Creates an abstract method
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# class Collection
|
|
9
|
+
# abstract :size
|
|
10
|
+
# abstract :add, :args => %w(item)
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# @return [void]
|
|
14
|
+
def abstract(name, *params)
|
|
15
|
+
if params.last.is_a?(Hash)
|
|
16
|
+
# abstract :method, :args => %w(a b c)
|
|
17
|
+
params = params.last[:args]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
file, line, = Stupidedi.caller
|
|
21
|
+
|
|
22
|
+
if params.empty?
|
|
23
|
+
class_eval(<<-RUBY, file, line.to_i - 1)
|
|
24
|
+
def #{name}(*args)
|
|
25
|
+
raise NoMethodError,
|
|
26
|
+
"method \#{self.class.name}.#{name} is abstract"
|
|
27
|
+
end
|
|
28
|
+
RUBY
|
|
29
|
+
else
|
|
30
|
+
class_eval(<<-RUBY, file, line.to_i - 1)
|
|
31
|
+
def #{name}(*args)
|
|
32
|
+
raise NoMethodError,
|
|
33
|
+
"method \#{self.class.name}.#{name}(#{params.join(", ")}) is abstract"
|
|
34
|
+
end
|
|
35
|
+
RUBY
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def def_delegators(target, *methods)
|
|
40
|
+
file, line, = Stupidedi.caller
|
|
41
|
+
|
|
42
|
+
for m in methods
|
|
43
|
+
if m.to_s =~ /=$/
|
|
44
|
+
class_eval(<<-RUBY, file, line.to_i - 1)
|
|
45
|
+
def #{m}(value)
|
|
46
|
+
#{target}.#{m}(value)
|
|
47
|
+
end
|
|
48
|
+
RUBY
|
|
49
|
+
else
|
|
50
|
+
class_eval(<<-RUBY, file, line.to_i - 1)
|
|
51
|
+
def #{m}(*args, &block)
|
|
52
|
+
#{target}.#{m}(*args, &block)
|
|
53
|
+
end
|
|
54
|
+
RUBY
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/ruby/object.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Object do
|
|
5
|
+
# @group List Constructors
|
|
6
|
+
#############################################################################
|
|
7
|
+
|
|
8
|
+
# Prepend the item to the front of a new list
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# 1.cons #=> [1]
|
|
12
|
+
# 1.cons(2.cons) #=> [1, 2]
|
|
13
|
+
# 1.cons([0, 0, 0]) #=> [1, 0, 0, 0]
|
|
14
|
+
#
|
|
15
|
+
# @return [Array]
|
|
16
|
+
def cons(array = [])
|
|
17
|
+
[self] + array
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Append the item to rear of a new list
|
|
21
|
+
#
|
|
22
|
+
# @example
|
|
23
|
+
# 1.snoc #=> [1]
|
|
24
|
+
# 1.snoc(2.snoc) #=> [2, 1]
|
|
25
|
+
# 1.snoc([0, 0, 0]) #=> [0, 0, 0, 1]
|
|
26
|
+
#
|
|
27
|
+
# @return [Array]
|
|
28
|
+
def snoc(array = [])
|
|
29
|
+
array + [self]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @group Combinators
|
|
33
|
+
#############################################################################
|
|
34
|
+
|
|
35
|
+
# Yields `self` to a block argument
|
|
36
|
+
#
|
|
37
|
+
# @example
|
|
38
|
+
# nil.bind{|a| a.nil? } #=> true
|
|
39
|
+
# 100.bind{|a| a.nil? } #=> false
|
|
40
|
+
#
|
|
41
|
+
def bind
|
|
42
|
+
yield self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @endgroup
|
|
46
|
+
#############################################################################
|
|
47
|
+
|
|
48
|
+
# Return the "eigenclass" where singleton methods reside
|
|
49
|
+
#
|
|
50
|
+
# @return [Class]
|
|
51
|
+
def eigenclass
|
|
52
|
+
class << self; self; end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/ruby/string.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine String do
|
|
5
|
+
# Return the one-character string at the given index
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# "abc".at(0) #=> "a"
|
|
9
|
+
# "abc".at(2) #=> "c"
|
|
10
|
+
#
|
|
11
|
+
# @param [Integer] n zero-based index of the character to read
|
|
12
|
+
#
|
|
13
|
+
# @return [String]
|
|
14
|
+
def at(n)
|
|
15
|
+
raise ArgumentError, "n must be positive" if n < 0
|
|
16
|
+
self[n, 1] unless n >= length
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Return the string with `n` characters removed from the front
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# "abc".drop(0) #=> "abc"
|
|
23
|
+
# "abc".drop(2) #=> "c"
|
|
24
|
+
#
|
|
25
|
+
# @param [Integer] n number of characters to drop (`n > 0`)
|
|
26
|
+
#
|
|
27
|
+
# @return [String]
|
|
28
|
+
def drop(n)
|
|
29
|
+
raise ArgumentError, "n must be positive" if n < 0
|
|
30
|
+
(length >= n) ? self[n..-1] : ""
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Return the first `n` characters from the front
|
|
34
|
+
#
|
|
35
|
+
# @example
|
|
36
|
+
# "abc".take(0) #=> ""
|
|
37
|
+
# "abc".take(2) #=> "ab"
|
|
38
|
+
#
|
|
39
|
+
# @param [Integer] n number of characters to select (`n > 0`)
|
|
40
|
+
#
|
|
41
|
+
# @return [String]
|
|
42
|
+
def take(n)
|
|
43
|
+
raise ArgumentError, "n must be positive" if n < 0
|
|
44
|
+
self[0, n]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Split the string in two at the given position
|
|
48
|
+
#
|
|
49
|
+
# @example
|
|
50
|
+
# "abc".split_at(0) #=> ["", "abc"]
|
|
51
|
+
# "abc".split_at(2) #=> ["ab", "c"]
|
|
52
|
+
#
|
|
53
|
+
# @param [Integer] n number of characters at which to split (`n > 0`)
|
|
54
|
+
#
|
|
55
|
+
# @return [Array(String, String)]
|
|
56
|
+
def split_at(n)
|
|
57
|
+
[take(n), drop(n)]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# True if the string is long enough such that {#at} is defined for the
|
|
61
|
+
# given `n`
|
|
62
|
+
#
|
|
63
|
+
# @example
|
|
64
|
+
# "abc".defined_at?(0) #=> true
|
|
65
|
+
# "abc".defined_at?(3) #=> false
|
|
66
|
+
def defined_at?(n)
|
|
67
|
+
n < length
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# To make String compatible with the {Stupidedi::Reader::Input} interface,
|
|
71
|
+
# we have to define `#position`... shameful!
|
|
72
|
+
def position
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Join multi-line string into a single line, removing leading whitespace
|
|
77
|
+
# from the beginning of each line
|
|
78
|
+
#
|
|
79
|
+
# @example
|
|
80
|
+
# "this is a
|
|
81
|
+
# multiline string".join #=> "this is a multiline string"
|
|
82
|
+
#
|
|
83
|
+
# @return [String]
|
|
84
|
+
def join
|
|
85
|
+
gsub(/\n[ \t]+/, " ")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/ruby/to_d.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "bigdecimal"
|
|
3
|
+
require "rational"
|
|
4
|
+
|
|
5
|
+
module Stupidedi
|
|
6
|
+
module Refinements
|
|
7
|
+
refine BigDecimal do
|
|
8
|
+
# @return [BigDecimal] self
|
|
9
|
+
def to_d
|
|
10
|
+
self
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
BIGDECIMAL = /\A[+-]? (?# optional leading sign )
|
|
15
|
+
(?:
|
|
16
|
+
(?:\d+\.?\d*) | (?# whole with optional decimal or ..)
|
|
17
|
+
(?:\d*?\.?\d+) ) (?# optional whole with decimal )
|
|
18
|
+
(?:E[+-]?\d+)? (?# optional exponent )
|
|
19
|
+
\Z/ix
|
|
20
|
+
|
|
21
|
+
refine String do
|
|
22
|
+
# Converts the string to a BigDecimal after validating the format. If the
|
|
23
|
+
# string does not match the pattern for a valid number, an `ArgumentError`
|
|
24
|
+
# is raised.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# "1.0".to_d #=> BigDecimal("1.0")
|
|
28
|
+
#
|
|
29
|
+
# @return [BigDecimal]
|
|
30
|
+
def to_d
|
|
31
|
+
if BIGDECIMAL =~ self
|
|
32
|
+
BigDecimal(to_s)
|
|
33
|
+
else
|
|
34
|
+
raise ArgumentError, "#{inspect} is not a valid number"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
refine Integer do
|
|
40
|
+
# Converts the integer to a BigDecimal
|
|
41
|
+
#
|
|
42
|
+
# @example
|
|
43
|
+
# 10.to_d #=> BigDecimal("10")
|
|
44
|
+
#
|
|
45
|
+
# @return [BigDecimal]
|
|
46
|
+
def to_d
|
|
47
|
+
BigDecimal(to_s)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
refine Rational do
|
|
52
|
+
# Converts the rational to a BigDecimal
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# Rational(3, 4).to_d #=> BigDecimal("3") / BigDecimal("4")
|
|
56
|
+
#
|
|
57
|
+
# @return [BigDecimal]
|
|
58
|
+
def to_d
|
|
59
|
+
numerator.to_d / denominator.to_d
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
refine Float do
|
|
64
|
+
# Raises a `TypeError` exception. The reason this method is defined at
|
|
65
|
+
# all is to produce a more meaningful error than `NoSuchMethod`.
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
def to_d
|
|
69
|
+
# The problem is there isn't a way to know the correct precision,
|
|
70
|
+
# since there are (many) values that cannot be represented exactly
|
|
71
|
+
# using Floats. For instance, we can't assume which value is correct
|
|
72
|
+
#
|
|
73
|
+
# "%0.10f" % 1.8 #=> "1.8000000000"
|
|
74
|
+
# "%0.20f" % 1.8 #=> "1.80000000000000004441"
|
|
75
|
+
#
|
|
76
|
+
# The programmer should convert the Float to a String using whatever
|
|
77
|
+
# precision he chooses, and call #to_d on the String.
|
|
78
|
+
raise TypeError, "cannot convert Float to BigDecimal"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/ruby/to_date.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Time do
|
|
5
|
+
def to_date
|
|
6
|
+
Date.civil(year, month, day)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
refine String do
|
|
11
|
+
def to_date
|
|
12
|
+
Date.parse(self)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
refine Date do
|
|
17
|
+
def to_date
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << Date
|
|
23
|
+
public :parse
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/ruby/to_time.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Time do
|
|
5
|
+
# @return [Time]
|
|
6
|
+
def to_time
|
|
7
|
+
self
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class << Time
|
|
12
|
+
public :parse
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
refine String do
|
|
16
|
+
def to_time
|
|
17
|
+
Time.parse(self)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/ruby/try.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Refinements
|
|
4
|
+
refine Object do
|
|
5
|
+
# @group Combinators
|
|
6
|
+
#############################################################################
|
|
7
|
+
|
|
8
|
+
# Sends the arguments to `self` or yields `self` (when `self` is non-`nil`).
|
|
9
|
+
# This is overridden by {NilClass#try}, which always returns `nil`.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# "non-nil".try(&:length) #=> 7
|
|
13
|
+
# nil.try(&:length) #=> nil
|
|
14
|
+
#
|
|
15
|
+
# "non-nil".try(:slice, 0, 3) #=> "non"
|
|
16
|
+
# nil.try(:slice, 0, 3) #=> nil
|
|
17
|
+
#
|
|
18
|
+
def try(*args, &block)
|
|
19
|
+
if args.empty?
|
|
20
|
+
yield self
|
|
21
|
+
else
|
|
22
|
+
__send__(*args, &block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
refine NilClass do
|
|
28
|
+
# @group Combinators
|
|
29
|
+
#############################################################################
|
|
30
|
+
|
|
31
|
+
# Returns `nil` (when `self` is `nil`). This overrides {Object#try}
|
|
32
|
+
#
|
|
33
|
+
# @example
|
|
34
|
+
# "non-nil".try(&:length) #=> 7
|
|
35
|
+
# nil.try(&:length) #=> nil
|
|
36
|
+
#
|
|
37
|
+
# "non-nil".try(:slice, 0, 3) #=> "non"
|
|
38
|
+
# nil.try(:slice, 0, 3) #=> nil
|
|
39
|
+
#
|
|
40
|
+
# @return nil
|
|
41
|
+
def try(*args)
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|