PHP recursive function nesting level reached

Good day. I have a parcer function that taker an array of string like this:

['str','str2','str2','*str','*str2','**str2','str','str2','str2']

And recursivelly elevates a level those starting with asterix to get this

['str','str2','str2',['str','str2',['str2']],'str','str2','str2']

And the function is:

function recursive_array_parser($ARRAY) {
    do {

        $i = 0;
        $s = null;
        $e = null;
        $err = false;

        foreach ($ARRAY as $item) {

            if (!is_array($item)) { //if element is not array
                $item = trim($item);
                if ($item[0] === '*' && $s == null && $e == null) { //we get it's start and end if it has asterix
                    $s = $i;
                    $e = $i;
                } elseif ($item[0] === '*' && $e != null)
                    $e = $i;
                elseif (!isset($ARRAY[$i + 1]) || $s != null && $e != null) { //if there are no elements or asterix element ended we elevate it
                    $e = $e == NULL ? $i : $e;
                    $head = array_slice($ARRAY, 0, $s);
                    $_x = [];
                    $inner = array_slice($ARRAY, $s, $e - $s + 1);
                    foreach ($inner as $_i)
                        $_x[] = substr($_i, 1);

                    $inner = [$_x];
                    $tail = array_slice($ARRAY, $e + 1, 999) or [];
                    $X = array_merge($head, $inner);
                    $ARRAY = array_merge($X, $tail);

                    $s = null;
                    $e = null;
                    $err = true;
                }
            } else {
                $ARRAY[$i] = recursive_array_parser($ARRAY[$i]); //if the item is array of items we recur.
            }
            $i++;

            if ($err == true) {
                break 1;
            }
        }
    } while ($err);
    return $ARRAY;
}

When this function runs, i get "Fatal error: Maximum function nesting level of '200' reached, aborting!" error.

I know it has something to do with infinite recursion, but i can't track the particular place where it occurs, and this is strange.

Upvotes: 0

Views: 417

Answers (2)

desimusxvii
desimusxvii

Reputation: 1094

Here's my solution. No nested loops.

function recursive_array_parser($arr) {
    $out = array();
    $sub = null;
    foreach($arr as $item) {
        if($item[0] == '*') { // We've hit a special item!
            if(!is_array($sub)) { // We're not currently accumulating a sub-array, let's make one!
                $sub = array();
            }
            $sub[] = substr($item, 1); // Add it to the sub-array without the '*'
        } else {
            if(is_array($sub)) { 
                // Whoops, we have an active subarray, but this thing didn't start with '*'. End that sub-array
                $out[] = recursive_array_parser($sub);
                $sub = null;
            }
            // Take the item
            $out[] = $item;
        }
    }

    if(is_array($sub)) { // We ended in an active sub-array. Add it.
        $out[] = recursive_array_parser($sub);
        $sub = null;
    }

    return $out;
}

Upvotes: 1

kainaw
kainaw

Reputation: 4334

I don't normally rewrite code, but your code can be reduced and simplified while, from what I can see, getting the desired result. See if this works for you:

$a = array('a','b','c','*d','*e','**f','g','*h');
print_r($a);
$a = recursive_array_parser($a);
print_r($a);
function recursive_array_parser($array)
{
    $ret = array();
    for($i=0; $i<sizeof($array); $i++)
    {
        if($array[$i]{0}!='*') $ret[] = $array[$i];
        else
        {
            $tmp = array();
            for($j=$i; $j<sizeof($array) && $array[$j]{0}=='*'; $j++)
            {
                $tmp[] = substr($array[$j],1);
            }
            $ret[] = recursive_array_parser($tmp);
            $i = $j-1;
        }
    }
    return $ret;
}

Note that it isn't possible for $array[$i] to be an array, so that check is removed. The recursion takes place on the temp array created when a * is found. The $i is closer tied to $array to reset it properly after parsing the series of * elements.

Upvotes: 2

Related Questions