I have a string composed by many letters, at some point, one letter from a group can be used and this is represented by letters enclosed in []. I need to expand these letters into its actual strings.
From this:
$str = 'ABCCDF[GH]IJJ[KLM]'
To this:
$sub[0] = 'ABCCDFGIJJK';
$sub[1] = 'ABCCDFHIJJK';
$sub[2] = 'ABCCDFGIJJL';
$sub[3] = 'ABCCDFHIJJL';
$sub[4] = 'ABCCDFGIJJM';
$sub[5] = 'ABCCDFHIJJM';
UPDATE:
Thanks to @Barmar for the very valuable suggestions.
My final solution is:
$str = '[GH]DF[IK]TF[ADF]';
function parseString(string $str) : array
{
    $i = 0;
    $is_group = false;
    $sub = array();
    $chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
    foreach ($chars as $key => $value)
    {
        if(ctype_alpha($value))
        {
            if($is_group){
                $sub[$i][] = $value;
            } else {
                if(!isset($sub[$i][0])){
                    $sub[$i][0] = $value;
                } else {
                    $sub[$i][0] .= $value;
                }
            }
        } else {
            $is_group = !$is_group;
            ++$i;
        }
    }
    return $sub;
}
The recommended function for combinations is (check the related post):
function array_cartesian_product($arrays)
{
    $result = array();
    $arrays = array_values($arrays);
    $sizeIn = sizeof($arrays);
    $size = $sizeIn > 0 ? 1 : 0;
    foreach ($arrays as $array)
        $size = $size * sizeof($array);
    for ($i = 0; $i < $size; $i++) {
        $result[$i] = array();
        for ($j = 0; $j < $sizeIn; $j++)
            array_push($result[$i], current($arrays[$j]));
        for ($j = ($sizeIn - 1); $j >= 0; $j--) {
            if (next($arrays[$j]))
                break;
            elseif (isset($arrays[$j]))
                reset($arrays[$j]);
        }
    }
    return $result;
}
Check the solution with:
$combinations = array_cartesian_product(parseString($str));
$sub = array_map('implode', $combinations);
var_dump($sub);