Task: Brace expansion






PHP: function getitem($s,$depth=0) {
    $out = [''];
    while ($s) {
        $c = $s[0];
        if ($depth && ($c == ',' || $c == '}')) {
            return [$out, $s];
        }
        if ($c == '{') {
            $x = getgroup(substr($s, 1), $depth + 1);
            if($x) {
                $tmp = [];
                foreach($out as $a) {
                    foreach($x[0] as $b) { 
                        $tmp[] = $a . $b;
                    }
                }
                $out = $tmp;
                $s = $x[1];
                continue;
            }
        }
        if ($c == '\\' && strlen($s) > 1) {
            list($s, $c) = [substr($s, 1), ($c . $s[1])];
        }

        $tmp = [];
        foreach($out as $a) {
            $tmp[] = $a . $c;
        }
        $out = $tmp;
        $s = substr($s, 1);
        
    }
    return [$out, $s];
}
function getgroup($s,$depth) {
    list($out, $comma) = [[], false];
    while ($s) {
        list($g, $s) = getitem($s, $depth);
        if (!$s) {
            break;
        }
        $out = array_merge($out, $g);
        if ($s[0] == '}') {
            if ($comma) {
                return [$out, substr($s, 1)];
            }

            $tmp = [];
            foreach($out as $a) {
                $tmp[] = '{' . $a . '}';
            }
            return [$tmp, substr($s, 1)];
        }
        if ($s[0] == ',') {
            list($comma, $s) = [true, substr($s, 1)];
        }
    }
    return null;
}

$lines = <<< 'END'
~/{Downloads,Pictures}/*.{jpg,gif,png}
It{{em,alic}iz,erat}e{d,}, please.
{,{,gotta have{ ,\, again\, }}more }cowbell!
{}} some }{,{\\{ edge, edge} \,}{ cases, {here} \\\\\}
END;

foreach( explode("\n", $lines) as $line ) {
    printf("\n%s\n", $line);
    foreach( getitem($line)[0] as $expansion ) {
        printf("    %s\n", $expansion);
    }
}



VB: Module Module1

    Function GetGroup(s As String, depth As Integer) As Tuple(Of List(Of String), String)
        Dim out As New List(Of String)
        Dim comma = False
        While Not String.IsNullOrEmpty(s)
            Dim gs = GetItem(s, depth)
            Dim g = gs.Item1
            s = gs.Item2
            If String.IsNullOrEmpty(s) Then
                Exit While
            End If
            out.AddRange(g)

            If s(0) = "}" Then
                If comma Then
                    Return Tuple.Create(out, s.Substring(1))
                End If
                Return Tuple.Create(out.Select(Function(a) "{" + a + "}").ToList(), s.Substring(1))
            End If

            If s(0) = "," Then
                comma = True
                s = s.Substring(1)
            End If
        End While
        Return Nothing
    End Function

    Function GetItem(s As String, Optional depth As Integer = 0) As Tuple(Of List(Of String), String)
        Dim out As New List(Of String) From {""}
        While Not String.IsNullOrEmpty(s)
            Dim c = s(0)
            If depth > 0 AndAlso (c = "," OrElse c = "}") Then
                Return Tuple.Create(out, s)
            End If
            If c = "{" Then
                Dim x = GetGroup(s.Substring(1), depth + 1)
                If Not IsNothing(x) Then
                    Dim tout As New List(Of String)
                    For Each a In out
                        For Each b In x.Item1
                            tout.Add(a + b)
                        Next
                    Next
                    out = tout
                    s = x.Item2
                    Continue While
                End If
            End If
            If c = "\" AndAlso s.Length > 1 Then
                c += s(1)
                s = s.Substring(1)
            End If
            out = out.Select(Function(a) a + c).ToList()
            s = s.Substring(1)
        End While
        Return Tuple.Create(out, s)
    End Function

    Sub Main()
        For Each s In {
            "It{{em,alic}iz,erat}e{d,}, please.",
            "~/{Downloads,Pictures}/*.{jpg,gif,png}",
            "{,{,gotta have{ ,\, again\, }}more }cowbell!",
            "{}} some }{,{\\{ edge, edge} \,}{ cases, {here} \\\\\}"
        }
            Dim fmt = "{0}" + vbNewLine + vbTab + "{1}"
            Dim parts = GetItem(s)
            Dim res = String.Join(vbNewLine + vbTab, parts.Item1)
            Console.WriteLine(fmt, s, res)
        Next
    End Sub

End Module