func brace_expand (input) {
var current = ['']
var stack = [[current]]
loop {
var t = input.match(
/\G ((?:[^\\{,}]++ | \\(?:.|\z))++ | . )/gx
)[0] \\ break
if (t == '{') {
stack << [current = ['']]
}
elsif ((t == ',') && (stack.len > 1)) {
stack[-1] << (current = [''])
}
elsif ((t == '}') && (stack.len > 1)) {
var group = stack.pop
current = stack[-1][-1]
group[0][] = group[0].map{ '{'+_+'}' }... if (group.len == 1)
current[] = current.map { |c|
group.map { .map { c + _ }... }...
}...
}
else {
current[] = current.map { _ + t }...
}
}
while (stack.len > 1) {
var right = stack[-1].pop
var sep = ','
if (stack[-1].is_empty) {
sep = '{'
stack.pop
}
current = stack[-1][-1]
current[] = current.map { |c|
right.map { c + sep + _ }...
}...
}
return current
}
DATA.each { |line|
say line
brace_expand(line).each { "\t#{_}".say }
say ''
}
__DATA__
~/{Downloads,Pictures}/*.{jpg,gif,png}
It{{em,alic}iz,erat}e{d,}, please.
{,{,gotta have{ ,\, again\, }}more }cowbell!
{}} some }{,{\\{ edge, edge} \,}{ cases, {here} \\\\\}
Output:
~/{Downloads,Pictures}/*.{jpg,gif,png}
~/Downloads/*.jpg
~/Downloads/*.gif
~/Downloads/*.png
~/Pictures/*.jpg
~/Pictures/*.gif
~/Pictures/*.png
It{{em,alic}iz,erat}e{d,}, please.
Itemized, please.
Itemize, please.
Italicized, please.
Italicize, please.
Iterated, please.
Iterate, please.
{,{,gotta have{ ,\, again\, }}more }cowbell!
cowbell!
more cowbell!
gotta have more cowbell!
gotta have\, again\, more cowbell!
{}} some }{,{\\{ edge, edge} \,}{ cases, {here} \\\\\}
{}} some }{,{\\ edge \,}{ cases, {here} \\\\\}
{}} some }{,{\\ edge \,}{ cases, {here} \\\\\}