Correct way to split nested brackets in PHP, e.g. "root[one[a,b,c],two[d,e,f]]" into array? -
like title says i'm looking robust way parse expression array (example in code).
<?php $str = 'root[one[a,b,c],two[d,e,f]]' $decoded = decode($str);
output:
$decoded = ['root' => ['one' => ['a', 'b', 'c'], 'two' => ['d', 'e', 'f']]
i'm trying via regex since brackets , commas nested it's not yielding correct results. how can this?
a simple parser below should job. did not test - successful route, , few obvious edge cases based on fair assumptions.
var_dump(parse('root[one[a,b,c],two[d,e,f]]')); function parse($str, $level = 0) { if ($level === 0) { // strip spaces once simplicity $str = str_replace([" ", "\t"], '', $str); } $result = []; while(true) { $rest = strpbrk($str, '[],'); if (!$rest) { if (strlen($str) > 0) { throw new expectedendofstringexception($str); } return $result; } $term = substr($rest, 0, 1); $rest = substr($rest, 1); $val = substr($str, 0, strpos($str, $term)); switch ($term) { case '[': if (!$val) { $val = 0; } elseif (isset($result[$val])) { throw new nonuniquekeyexception($val); } list($a, $str) = parse($rest, $level+1); if (is_null($a) && is_null($str)) { throw new bracketsmismatchexception($rest); } $result = array_merge($result, [$val => $a]); break; case ']': if ($val) { $result[] = $val; } if($level < 1) { throw new bracketsmismatchexception($rest); } if (strlen($rest) > 0 && !in_array(substr($rest, 0, 1), [',', ']'])) { throw new malformedstringexception($val.$term.$rest); } return [$result, ltrim($rest, ',')]; case ',': if (!$val) { throw new unexpectedcomaexception($term.$rest); } $result[] = $val; $str = $rest; break; default: throw new logicexception(); } } }
http://sandbox.onlinephpfunctions.com/code/d1e74494226d530d1ed5b3c2d0fd7d545acb2d9e
you need implement exception classes, should trivial. otherwise replace them generic \exception();
Comments
Post a Comment