mirror of
https://github.com/urbit/shrub.git
synced 2024-12-21 01:41:37 +03:00
44 lines
1.3 KiB
Ruby
44 lines
1.3 KiB
Ruby
|
def expand_brackets_core(str, depth)
|
||
|
finished_parts = []
|
||
|
active_parts = [+'']
|
||
|
while true
|
||
|
if str.empty?
|
||
|
raise AnticipatedError, "Unmatched opening brace" if depth > 0
|
||
|
break
|
||
|
elsif str.start_with?('}')
|
||
|
str.slice!(0)
|
||
|
raise AnticipatedError, "Unmatched closing brace" if depth == 0
|
||
|
break
|
||
|
elsif str.start_with?('{')
|
||
|
# Recurse, which removes everything up to and
|
||
|
# including the matching closing brace.
|
||
|
str.slice!(0)
|
||
|
options = expand_brackets_core(str, depth + 1)
|
||
|
raise if options.empty?
|
||
|
active_parts = active_parts.flat_map { |p1|
|
||
|
options.map { |p2| p1 + p2 }
|
||
|
}
|
||
|
elsif str.start_with?(',')
|
||
|
raise AnticipatedError, "Comma at top level" if depth == 0
|
||
|
# Remove the comma, mark the parts we are working
|
||
|
# on as finished, and start a new part.
|
||
|
str.slice!(0)
|
||
|
finished_parts += active_parts
|
||
|
active_parts = ['']
|
||
|
else
|
||
|
part_length = str.index(/[{},]|$/)
|
||
|
raise if part_length < 1
|
||
|
part = str.slice!(0, part_length)
|
||
|
active_parts.each do |s|
|
||
|
s.insert(-1, part)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
finished_parts + active_parts
|
||
|
end
|
||
|
|
||
|
# Expands something like "{a,b}{,.x}" to ["a", "a.x", "b", "b.x"]
|
||
|
def expand_brackets(str)
|
||
|
expand_brackets_core(str.dup, 0)
|
||
|
end
|