semver_dialects 2.0.2 → 3.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.
@@ -1,288 +0,0 @@
1
- module IntervalType
2
- UNKNOWN = 0
3
- LEFT_OPEN = 1
4
- LEFT_CLOSED = 2
5
- RIGHT_OPEN = 4
6
- RIGHT_CLOSED = 8
7
- end
8
-
9
- class VersionInterval
10
- attr_accessor :type, :start_cut, :end_cut
11
-
12
- def initialize(type, start_cut, end_cut)
13
- @type = type
14
- @start_cut = start_cut
15
- @end_cut = end_cut
16
- end
17
-
18
- def intersect(other_interval)
19
- return EmptyInterval.new if self.empty?
20
-
21
- # this look odd -- we have to use it here though, because it may be that placeholders are present inside
22
- # the version for which > and < would yield true
23
- return EmptyInterval.new if !(@start_cut <= other_interval.end_cut) || !(other_interval.start_cut <= @end_cut)
24
-
25
- start_cut_new = max(@start_cut, other_interval.start_cut)
26
- end_cut_new = min(@end_cut, other_interval.end_cut)
27
-
28
- # compute the boundaries for the intersection
29
- type = compute_intersection_boundary(self, other_interval, start_cut_new, end_cut_new)
30
- interval = VersionInterval.new(type, start_cut_new, end_cut_new)
31
- half_open = !(interval.bit_set?(IntervalType::RIGHT_CLOSED) && interval.bit_set?(IntervalType::LEFT_CLOSED))
32
-
33
- interval.singleton? && half_open ? EmptyInterval.new : interval
34
- end
35
-
36
- def union(other_interval)
37
- return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
38
-
39
- start_cut_new = min(@start_cut, other_interval.start_cut)
40
- end_cut_new = max(@end_cut, other_interval.end_cut)
41
-
42
- # compute the boundaries for the union
43
- type = compute_union_boundary(self, other_interval, start_cut_new, end_cut_new)
44
- VersionInterval.new(type, start_cut_new, end_cut_new)
45
- end
46
-
47
- def collapse(other_interval)
48
- return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
49
-
50
- frame = [@start_cut, other_interval.start_cut, @end_cut, other_interval.end_cut].reject { |cut| special(cut) }
51
- min_cut = frame.reduce { |smallest, current| smallest < current ? smallest : current }
52
- max_cut = frame.reduce { |biggest, current| biggest > current ? biggest : current }
53
-
54
- # compute the boundaries for the union
55
- type = compute_union_boundary(self, other_interval, min_cut, max_cut)
56
- VersionInterval.new(type, min_cut, max_cut)
57
- end
58
-
59
- def special(cut)
60
- cut.instance_of?(AboveAll) || cut.instance_of?(BelowAll)
61
- end
62
-
63
- def to_s
64
- s = ""
65
- s += bit_set?(IntervalType::LEFT_CLOSED) ? "[" : ""
66
- s += bit_set?(IntervalType::LEFT_OPEN) ? "(" : ""
67
- s += [@start_cut, @end_cut].join(",")
68
- s += bit_set?(IntervalType::RIGHT_CLOSED) ? "]" : ""
69
- s += bit_set?(IntervalType::RIGHT_OPEN) ? ")" : ""
70
- s
71
- end
72
-
73
- # this function returns a human-readable descriptions of the version strings
74
- def to_description_s
75
- s = ""
76
- if self.distinct?
77
- s = "version #{@start_cut.to_s}"
78
- elsif self.universal?
79
- s = "all versions "
80
- else
81
- s = "all versions "
82
- s += start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? "after #{@start_cut.to_s} " : bit_set?(IntervalType::LEFT_CLOSED) ? "starting from #{@start_cut.to_s} " : ""
83
- s += end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "before #{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "up to #{@end_cut.to_s}" : ""
84
- end
85
- s.strip
86
- end
87
-
88
- def to_nuget_s
89
- to_maven_s
90
- end
91
-
92
- def to_maven_s
93
- s = ""
94
- # special case -- distinct version
95
- if self.distinct?
96
- s += "[#{@start_cut.to_s}]"
97
- else
98
- s += start_cut.instance_of?(BelowAll) ? "(," : bit_set?(IntervalType::LEFT_OPEN) ? "[#{@start_cut.to_s}," : bit_set?(IntervalType::LEFT_CLOSED) ? "[#{@start_cut.to_s}," : ""
99
- s += end_cut.instance_of?(AboveAll) ? ")" : bit_set?(IntervalType::RIGHT_OPEN) ? "#{@end_cut.to_s})" : bit_set?(IntervalType::RIGHT_CLOSED) ? "#{@end_cut.to_s}]" : ""
100
- end
101
- s
102
- end
103
-
104
- def distinct?
105
- bit_set?(IntervalType::LEFT_CLOSED) && bit_set?(IntervalType::RIGHT_CLOSED) && @start_cut == @end_cut
106
- end
107
-
108
- def subsumes?(other)
109
- @start_cut <= other.start_cut && @end_cut >= other.end_cut
110
- end
111
-
112
- def universal?
113
- (bit_set?(IntervalType::LEFT_OPEN) && bit_set?(IntervalType::RIGHT_OPEN) && @start_cut.instance_of?(BelowAll) && @end_cut.instance_of?(AboveAll)) || @start_cut.is_initial_version? && @end_cut.instance_of?(AboveAll)
114
- end
115
-
116
- def to_gem_s
117
- get_canoncial_s
118
- end
119
-
120
- def to_ruby_s
121
- get_canoncial_s
122
- end
123
-
124
- def to_npm_s
125
- get_canoncial_s
126
- end
127
-
128
- def to_conan_s
129
- get_canoncial_s
130
- end
131
-
132
- def to_go_s
133
- get_canoncial_s
134
- end
135
-
136
- def to_pypi_s
137
- get_canoncial_s(',', '==')
138
- end
139
-
140
- def to_packagist_s
141
- get_canoncial_s(',')
142
- end
143
-
144
- def empty?
145
- self.instance_of?(EmptyInterval)
146
- end
147
-
148
- def singleton?
149
- @start_cut == @end_cut && @start_cut.value == @end_cut.value
150
- end
151
-
152
- def diff(other_interval, abs = true)
153
- if self.distinct? && other_interval.distinct?
154
- self.start_cut.diff(other_interval.start_cut, abs)
155
- else
156
- EmptyInterval.new()
157
- end
158
- end
159
-
160
- def joinable?(other_interval)
161
- other_interval.start_cut.is_successor_of?(self.end_cut) || universal?
162
- end
163
-
164
- def join(other_interval)
165
- if self.joinable?(other_interval)
166
- _join(self, other_interval)
167
- elsif other_interval.joinable?(self)
168
- _join(other_interval, self)
169
- else
170
- EmptyInterval.new()
171
- end
172
- end
173
-
174
- def cross_total
175
- if distinct?
176
- @start_cut.cross_total
177
- else
178
- @start_cut.cross_total + @end_cut.cross_total
179
- end
180
- end
181
-
182
- def ==(other_interval)
183
- @start_cut == other_interval.start_cut && @end_cut == other_interval.end_cut && @type == other_interval.type
184
- end
185
-
186
- # inverts the given version interval -- note that this function amy return two version intervals
187
- # e.g., (2,10] -> (-inf, 2], (10, +inf)
188
- # left right
189
- def invert
190
- intervals = []
191
- left_type = bit_set?(IntervalType::LEFT_OPEN) ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
192
- left_type = left_type | IntervalType::LEFT_OPEN
193
- right_type = bit_set?(IntervalType::RIGHT_OPEN) ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
194
- right_type = right_type | IntervalType::RIGHT_OPEN
195
-
196
- intervals << VersionInterval.new(left_type, BelowAll.new, @start_cut) unless @start_cut.instance_of?(BelowAll)
197
- intervals << VersionInterval.new(right_type, @end_cut, AboveAll.new) unless @end_cut.instance_of?(AboveAll)
198
- intervals
199
- end
200
-
201
- def bit_set?(interval_type)
202
- @type & interval_type != 0
203
- end
204
-
205
- protected
206
-
207
- # computes the boundary type for union operation
208
- def compute_union_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
209
- compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, IntervalType::LEFT_CLOSED, IntervalType::RIGHT_CLOSED)
210
- end
211
-
212
- def compute_intersection_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
213
- compute_boundary(interval_a, interval_b,start_cut_new, end_cut_new, IntervalType::LEFT_OPEN, IntervalType::RIGHT_OPEN)
214
- end
215
-
216
- def compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, left_check, right_check)
217
- start_cut_a = interval_a.start_cut
218
- end_cut_a = interval_a.end_cut
219
- type_a = interval_a.type
220
-
221
- start_cut_b = interval_b.start_cut
222
- end_cut_b = interval_b.end_cut
223
- type_b = interval_b.type
224
-
225
- left_fill = left_check == IntervalType::LEFT_OPEN ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
226
- right_fill = right_check == IntervalType::RIGHT_OPEN ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
227
-
228
- # compute the boundaries for the union
229
- if start_cut_b == start_cut_a && start_cut_b == start_cut_b
230
- one_left_closed = left_type(type_a) == left_check || left_type(type_b) == left_check
231
- left_type = one_left_closed ? left_check : left_fill
232
- else
233
- left_type = start_cut_new == start_cut_a ? left_type(type_a) : left_type(type_b)
234
- end
235
-
236
- if end_cut_b == end_cut_a && end_cut_b == end_cut_b
237
- one_right_closed = right_type(type_a) == right_check || right_type(type_b) == right_check
238
- right_type = one_right_closed ? right_check : right_fill
239
- else
240
- right_type = end_cut_new == end_cut_a ? right_type(type_a) : right_type(type_b)
241
- end
242
-
243
- left_type | right_type
244
- end
245
-
246
- def _join(first_interval, second_interval)
247
- if first_interval.joinable?(second_interval)
248
- VersionInterval.new(first_interval.type, first_interval.start_cut.dup, second_interval.end_cut.dup)
249
- else
250
- EmptyInterval.new()
251
- end
252
- end
253
-
254
- def get_canoncial_s(delimiter = " ", eq = '=')
255
- if self.distinct?
256
- "#{eq}#{@start_cut.to_s}"
257
- else
258
- first = start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? ">#{@start_cut.to_s}" : bit_set?(IntervalType::LEFT_CLOSED) ? ">=#{@start_cut.to_s}" : ""
259
- second = end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "<#{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "<=#{@end_cut.to_s}" : ""
260
- !first.empty? && !second.empty? ? "#{first}#{delimiter}#{second}" : first + second
261
- end
262
- end
263
-
264
- def max(cut_a, cut_b)
265
- cut_a > cut_b ? cut_a : cut_b
266
- end
267
-
268
- def min(cut_a, cut_b)
269
- cut_a < cut_b ? cut_a : cut_b
270
- end
271
-
272
- def right_type(type)
273
- (IntervalType::RIGHT_OPEN | IntervalType::RIGHT_CLOSED) & type
274
- end
275
-
276
- def left_type(type)
277
- (IntervalType::LEFT_OPEN | IntervalType::LEFT_CLOSED) & type
278
- end
279
- end
280
-
281
- class EmptyInterval < VersionInterval
282
- def initialize()
283
- end
284
-
285
- def to_s
286
- "empty"
287
- end
288
- end
@@ -1,40 +0,0 @@
1
- require_relative "version_cut"
2
- require_relative "version_interval"
3
-
4
- module VersionParser
5
- # A constraint is made of an operator followed by a version string.
6
- CONSTRAINT_REGEXP = Regexp.new("(?<op>[><=]+) *(?<version>#{SemanticVersion::VERSION_PATTERN})").freeze
7
-
8
- def self.parse(versionstring)
9
- if (versionstring == "=*")
10
- # special case = All Versions
11
- return VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
12
- end
13
-
14
- version_items = versionstring.split(" ")
15
- interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
16
- version_items.each do |version_item|
17
- matches = version_item.match CONSTRAINT_REGEXP
18
- raise SemverDialects::InvalidConstraintError, versionstring if matches.nil?
19
- version_string = matches[:version]
20
- case matches[:op]
21
- when ">="
22
- new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
23
- interval = interval.intersect(new_interval)
24
- when "<="
25
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_CLOSED, BelowAll.new(), VersionCut.new(version_string))
26
- interval = interval.intersect(new_interval)
27
- when "<"
28
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), VersionCut.new(version_string))
29
- interval = interval.intersect(new_interval)
30
- when ">"
31
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
32
- interval = interval.intersect(new_interval)
33
- when "=", "=="
34
- new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_CLOSED, VersionCut.new(version_string), VersionCut.new(version_string))
35
- interval = interval.intersect(new_interval)
36
- end
37
- end
38
- interval
39
- end
40
- end
@@ -1,191 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'version_parser'
4
- require 'set'
5
-
6
- # VersionRange is a utility class that helps managing consecutive version ranges automatically
7
- # given that they are added in-order
8
- # Note that join_if_possible should be only activated in case the ranges are added in consecutive order!!
9
- class VersionRange
10
- attr_reader :version_intervals, :join_if_possible
11
-
12
- def initialize(join_if_possible = true)
13
- @version_intervals = []
14
- @version_interval_set = Set.new
15
- @join_if_possible = join_if_possible
16
- end
17
-
18
- def add_all(version_range)
19
- version_range.version_intervals.each { |interval| add(interval) }
20
- end
21
-
22
- def add(version_interval)
23
- return if @version_interval_set.include?(version_interval)
24
-
25
- if @join_if_possible
26
- if @version_intervals.empty?
27
- @version_intervals << version_interval
28
- @version_interval_set.add(version_interval)
29
- else
30
- last = @version_intervals.last
31
- # nothing to do
32
- return if last.end_cut == version_interval.start_cut && last.end_cut.value == version_interval.start_cut.value
33
-
34
- if last.joinable?(version_interval)
35
- @version_intervals[@version_intervals.size - 1] = last.join(version_interval)
36
- else
37
- @version_intervals << version_interval
38
- @version_interval_set.add(version_interval)
39
- end
40
- end
41
- else
42
- @version_intervals << version_interval
43
- @version_interval_set.add(version_interval)
44
- end
45
- end
46
-
47
- def <<(item)
48
- add(item)
49
- end
50
-
51
- def size
52
- @version_intervals.size
53
- end
54
-
55
- def to_s
56
- @version_intervals.map(&:to_s).join(',')
57
- end
58
-
59
- def to_description_s
60
- @version_intervals.map(&:to_description_s).join(', ').capitalize
61
- end
62
-
63
- def to_npm_s
64
- @version_intervals.map(&:to_npm_s).join('||')
65
- end
66
-
67
- def to_conan_s
68
- to_npm_s
69
- end
70
-
71
- def to_nuget_s
72
- to_maven_s
73
- end
74
-
75
- def to_maven_s
76
- @version_intervals.map(&:to_maven_s).join(',')
77
- end
78
-
79
- def to_gem_s
80
- @version_intervals.map(&:to_gem_s).join('||')
81
- end
82
-
83
- def to_pypi_s
84
- @version_intervals.map(&:to_pypi_s).join('||')
85
- end
86
-
87
- def to_go_s
88
- @version_intervals.map(&:to_go_s).join('||')
89
- end
90
-
91
- def to_packagist_s
92
- @version_intervals.map(&:to_packagist_s).join('||')
93
- end
94
-
95
- def to_version_s(package_type)
96
- case package_type
97
- when 'npm'
98
- to_npm_s
99
- when 'nuget'
100
- to_nuget_s
101
- when 'maven'
102
- to_maven_s
103
- when 'gem'
104
- to_gem_s
105
- when 'pypi'
106
- to_pypi_s
107
- when 'packagist'
108
- to_packagist_s
109
- when 'go'
110
- to_go_s
111
- when 'conan'
112
- to_conan_s
113
- else
114
- ''
115
- end
116
- end
117
-
118
- # inverts the given version interval -- note that this function amy return two version intervals
119
- # e.g., (2,10], (12, 13], [15, +inf)
120
- # 1) invert: (-inf, 2], (10, +inf), (-inf, 12], (13, +inf), (15)
121
- # 2) collapse (-inf, 2], (10, 12], (13, 15)
122
- #
123
- # the collapsed inverted ranges can potentially contain fixed versions
124
- def invert
125
- inverted = @version_intervals.map(&:invert).flatten
126
- version_intervals = collapse_intervals(inverted)
127
- version_intervals_to_range(version_intervals)
128
- end
129
-
130
- def collapse
131
- version_intervals = collapse_intervals(@version_intervals)
132
- version_intervals_to_range(version_intervals)
133
- end
134
-
135
- def includes?(version_interval)
136
- @version_interval_set.include?(version_interval)
137
- end
138
-
139
- def overlaps_with?(version_interval)
140
- @version_interval_set.each do |interval|
141
- return true unless interval.intersect(version_interval).instance_of? EmptyInterval
142
- end
143
- false
144
- end
145
-
146
- def first
147
- @version_intervals.first
148
- end
149
-
150
- def empty?
151
- @version_intervals.empty?
152
- end
153
-
154
- def any?
155
- @version_intervals.any?
156
- end
157
-
158
- def universal?
159
- @version_intervals.each do |version_interval|
160
- return true if version_interval.universal?
161
- end
162
- false
163
- end
164
-
165
- private
166
-
167
- def version_intervals_to_range(version_intervals)
168
- ret = VersionRange.new(false)
169
- version_intervals.each do |version_interval|
170
- ret << version_interval
171
- end
172
- ret
173
- end
174
-
175
- def collapse_intervals(version_intervals)
176
- interval_cp = []
177
- interval_cp += version_intervals
178
- ret = [interval_cp.shift]
179
-
180
- interval_cp.each do |item|
181
- last = ret.last
182
- if last.intersect(item).instance_of?(EmptyInterval)
183
- ret << item
184
- else
185
- ret.pop
186
- ret << last.collapse(item)
187
- end
188
- end
189
- ret
190
- end
191
- end
@@ -1,172 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../utils.rb'
4
-
5
- # A prepropcessor -- convert different version strings to something that can be digested by the
6
- # version parser
7
- module VersionTranslator
8
- def self.translate_npm(version_string)
9
- version_string.split('||').map do |item|
10
- add_missing_operator(single_space_after_operator(item.strip.gsub(/&&/, ' ')))
11
- end
12
- end
13
-
14
- def self.translate_conan(version_string)
15
- translate_npm(version_string)
16
- end
17
-
18
- def self.translate_go(version_string)
19
- translate_gem(version_string)
20
- end
21
-
22
- def self.translate_gem(version_string)
23
- version_string.split('||').map do |item|
24
- add_missing_operator(single_space_after_operator(item.strip.gsub(/\s+/, ' ')))
25
- end
26
- end
27
-
28
- def self.translate_packagist(version_string)
29
- translate_pypi(version_string)
30
- end
31
-
32
- def self.translate_pypi(version_string)
33
- version_string.split('||').map do |item|
34
- add_missing_operator(single_space_after_operator(comma_to_space(item)))
35
- end
36
- end
37
-
38
- def self.translate_nuget(version_string)
39
- translate_maven(version_string)
40
- end
41
-
42
- def self.translate_maven(version_string)
43
- lexing_maven_version_string(version_string).map { |item| translate_mvn_version_item(item) }
44
- end
45
-
46
- def self.add_missing_operator(version_string)
47
- starts_with_operator?(version_string) ? version_string : "=#{version_string}"
48
- end
49
-
50
- def self.single_space_after_operator(version_string)
51
- version_string.gsub(/([>=<]+) +/, '\1').gsub(/\s+/, ' ')
52
- end
53
-
54
- def self.starts_with_operator?(version_item)
55
- version_item.match(/^[=><]/) ? true : false
56
- end
57
-
58
- def self.comma_to_space(version_string)
59
- version_string.strip.gsub(/,/, ' ')
60
- end
61
-
62
- def self.lexing_maven_version_string(version_string)
63
- open = false
64
- substring = ''
65
- ret = []
66
- version_string.each_char do |c|
67
- case c
68
- when '(', '['
69
- if open
70
- puts "malformed maven version string #{version_string}"
71
- exit(-1)
72
- else
73
- unless substring.empty?
74
- ret << substring
75
- substring = ''
76
- end
77
- open = true
78
- substring += c
79
- end
80
- when ')', ']'
81
- if !open
82
- puts "malformed maven version string #{version_string}"
83
- exit(-1)
84
- else
85
- open = false
86
- substring += c
87
- ret << substring
88
- substring = ''
89
- end
90
- when ','
91
- substring += c if open
92
- when ' '
93
- # nothing to do
94
- substring += ''
95
- else
96
- substring += c
97
- end
98
- end
99
- if open
100
- puts "malformed maven version string #{version_string}"
101
- exit(-1)
102
- end
103
- ret << substring unless substring.empty?
104
- ret
105
- end
106
-
107
- def self.parenthesized?(version_item)
108
- version_item.match(/^[\(\[]/) && version_item.match(/[\]\)]$/) ? true : false
109
- end
110
-
111
- def self.translate_mvn_version_item(version_item)
112
- content = ''
113
- parens_pattern = ''
114
- if parenthesized?(version_item)
115
- content = version_item[1, version_item.size - 2]
116
- parens_pattern = version_item[0] + version_item[version_item.size - 1]
117
- # special case -- unversal version range
118
- return '=*' if content.strip == ','
119
- else
120
- # according to the doc, if there is a plain version string in maven, it means 'starting from version x'
121
- # https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8903
122
- content = "#{version_item},"
123
- parens_pattern = '[)'
124
- end
125
-
126
- args = content.split(',')
127
- first_non_empty_arg = args.find(&:range_present?)
128
-
129
- if content.start_with?(',')
130
- # {,y}
131
- case parens_pattern
132
- when '[]'
133
- "<=#{first_non_empty_arg}"
134
- when '()'
135
- "<#{first_non_empty_arg}"
136
- when '[)'
137
- "<#{first_non_empty_arg}"
138
- else
139
- # par_pattern == "(]"
140
- "<=#{first_non_empty_arg}"
141
- end
142
- elsif content.end_with?(',')
143
- # {x,}
144
- case parens_pattern
145
- when '[]'
146
- ">=#{first_non_empty_arg}"
147
- when '()'
148
- ">#{first_non_empty_arg}"
149
- when '[)'
150
- ">=#{first_non_empty_arg}"
151
- else
152
- # par_pattern == "(]"
153
- ">#{first_non_empty_arg}"
154
- end
155
- elsif content[','].nil?
156
- # [x,x]
157
- "=#{content}"
158
- else
159
- case parens_pattern
160
- when '[]'
161
- ">=#{args[0]} <=#{args[1]}"
162
- when '()'
163
- ">#{args[0]} <#{args[1]}"
164
- when '[)'
165
- ">=#{args[0]} <#{args[1]}"
166
- else
167
- # par_pattern == "(]"
168
- ">#{args[0]} <=#{args[1]}"
169
- end
170
- end
171
- end
172
- end