使用PHP将复杂字符串解析为父/子数组

使用PHP将复杂字符串解析为父/子数组,php,parsing,Php,Parsing,下面是一个字符串示例 a (b, c(d and/or e, f, g), h, i[j, k]), l (m, n(o, p[q, r{s or t,u}, v]), w) 我需要将其解析为如下内容: { -a -b -c -d -and/or -e -f -g -h -i -j -k -l -m -n -o

下面是一个字符串示例

a (b, c(d and/or e, f, g), h, i[j, k]), l (m, n(o, p[q, r{s or t,u}, v]), w)
我需要将其解析为如下内容:

{
-a
    -b
    -c
        -d 
        -and/or
        -e
        -f
        -g
    -h
    -i
        -j
        -k
-l
    -m
    -n
        -o
        -p
            -q
            -r
                -s
                -t
                -or
                -u
            -v
    -w
}
我开始玩一些正则表达式,但很快就变丑了。有什么建议吗


谢谢。

我不知道你的规则,但这段代码基本上可以完成这项工作

<?php
$string = 'a (b, c(d and/or e, f, g), h, i[j, k]), l (m, n(o, p[q, r{s or t,u}, v]), w)';
$indentLevel = 0;
$out = '';
echo '{'."\n";
// Split string into array of characters (AFAIK, that is basically how every parser works out there) and iterate over it
foreach (str_split($string) as $x) {
    // Determine if this character is string terminator or not
    $isTerminator = in_array($x, array(' ', ',', '(', '[', '{', ')', ']', '}'));
    // Output, because of string terminator, but only if output has something in it
    if ($isTerminator && strlen($out) > 0) {
        echo str_repeat("\t", $indentLevel).'-'.$out."\n";
        $out = '';
    }
    // Add to output (multiple character string support), if this is not string terminator
    elseif (!$isTerminator) {
        $out .= $x;
    }
    // Increase indent, because of brackets
    if (in_array($x, array('(', '[', '{'))) {
        $indentLevel++;
    }
    // Decrease indent, because of brackets
    elseif (in_array($x, array(')', ']', '}'))) {
        $indentLevel--;
    }
    // This is how you can tell that there is bracket count mismatch
    if ($indentLevel < 0) {
        die('Syntax error');
    }
}
echo '}'."\n";

没有赢得任何选美比赛,但工作:

<?php
$s = 'a (b, c(d and/or e, f, g), h, i[j, k]), l (m, n(o, p[q, r{s or t,u}, v]), w)';

$chars = str_split($s);

$sep   = array(',', ' ');
$open  = array('(', '[', '{');
$close = array(')', ']', '}');

function parse($s)
{
    global $sep, $open, $close;

    $chars   = str_split($s);
    $arr     = array();
    $collect = '';

    for ($i = 0; $i < count($chars); $i++) {
        $c = $chars[$i];

        if (in_array($c, $open)) {
            $parens = 1;
            $inner  = '';
            do {
                $i++;
                $ch = $chars[$i];
                if (in_array($ch, $open)) {
                    $parens++;
                } elseif (in_array($ch, $close)) {
                    $parens--;
                }
                if ($parens > 0) {
                    $inner .= $ch;
                }
            } while ($parens > 0);

            if ($collect) {
                $arr[] = '-'.$collect;
            }
            $arr[]   = parse($inner);
            $collect = '';
            continue;
        }

        if (in_array($c, $sep)) {
            if ($collect == '') {
                continue;
            }
            $arr[]   = '-'.$collect;
            $collect = '';
        } else {
            $collect .= $c;
        }
    }

    if ($collect) {
        $arr[] = '-'.$collect;
    }

    return $arr;
}

print_r(parse($s));

这不是必然的结果。有时使用(),然后使用{},然后使用[]…;-)除了DOM提到的,要创建解析器,还需要定义解析器应该使用的精确规则。没有这些规则,没有人能正确回答你的问题。现在,我们只能猜测你想要实现的是什么。多姆,我知道它们是不一致的@Deele,我正在将成分列表解析为父/子结构。顶级项可以有嵌套的子项包装在()、[]或{}中。在大多数情况下,结构将是level1(level2[level3{level4}])@user3734597查看答案,不要忘记将适合您的答案标记为最佳答案,这样这个问题就可以结束了。这并不完全是OP要求的,但因为OP问题含糊不清,我不会降低这个答案的分数。输出格式是这之后的另一个步骤。我猜他只想要解析器。