如何解析代码字符串并基于字符串中的{和}构建分层数组

时间:2011-07-02 18:31:43

标签: algorithm parsing

我有类似代码的字符串,如下所示:

a
{
    bcd
    {
        ef
        {
            gh
            {
                i
            }
            j
        }
    }
    k
    {
        lmn
        {
            op
        }
        qr
        {
            st
        }
        uv
        {
            wx
        }
        y
    }
    z
}

我希望解析这个字符串,以便我可以从这段代码创建一个分层数组,其中每个树都是基于{创建的,而一棵树以}结束。

数组看起来像:

[
    "a",

    "{",

    [

        "bcd",

        "{",

        [
            "ef",

            "{",

            [
                "gh",

                "{",

                [
                    "i"
                ],

                "}",

                "j"
            ],

            "}"
        ],

        "}",

        "k",

        "{",

        [
            "lmn",
            "{",
            [
                "op"
            ],

            "}",
            "qr",

            "{",

            [
                "st"
            ],

            "}",

            "uv",

            "{",
            [
                "wx"
            ],

            "}",
            "y"
        ],

        "}",
        "z"
    ],

"}"
]

任何人都可以帮我解决这个问题吗?

你也可以用Java / C#/ PHP / VB.NET / JavaScript / ActionScript中的任何一种语言传递代码。

2 个答案:

答案 0 :(得分:0)

你对这种语言并不是很挑剔,所以我很好奇你为什么要这样。这里有一些代码应该在C#中做你想要的:

public static object[] ParseSpecial(string s)
{
    string dummy = "";
    Stack<List<object>> result = new Stack<List<object>>();
    result.Push(new List<object>());
    foreach (char character in s)
    {
        switch (character)
        {
            case '{':
                if (dummy.Length > 0)
                    result.Peek().Add(dummy);
                dummy = "";

                result.Peek().Add("{");
                result.Push(new List<object>());
                break;

            case '}':
                if (dummy.Length > 0)
                    result.Peek().Add(dummy);
                dummy = "";

                List<object> temp = result.Pop();
                result.Peek().Add(temp.ToArray());
                result.Peek().Add("}");
                break;

            default:
                dummy += character;
                break;
        }
    }

    if (dummy.Length > 0)
        result.Peek().Add(dummy);

    return result.Peek().ToArray();
}

答案 1 :(得分:0)

如果这就是你想做的全部,你可以这样写(C#):

class Node
{
    public string Name { get; private set; }
    public IEnumerable<Node> Children { get; private set; }

    public Node(string name, IEnumerable<Node> children)
    {
        Name = name;
        Children = children;
    }
}

class Parser
{
    public Node Parse(string s)
    {
        return Parse(s.Split(new char[0], StringSplitOptions.RemoveEmptyEntries));
    }

    public Node Parse(IEnumerable<string> tokens)
    {
        using (var enumerator = tokens.GetEnumerator())
        {
            enumerator.MoveNext(); // move to first token
            return Parse(enumerator);
        }
    }

    Node Parse(IEnumerator<string> enumerator)
    {
        string name = enumerator.Current;
        enumerator.MoveNext();
        var children = new List<Node>();
        if (enumerator.Current == "{")
        {
            enumerator.MoveNext();
            while (enumerator.Current != "}")
            {
                children.Add(Parse(enumerator));
            }
            enumerator.MoveNext();
        }
        return new Node(name, children);
    }
}

此代码不检查MoveNext()的返回值,这意味着它会在无效输入上产生奇怪的结果(包括无限循环的可能性)。

它还要求令牌由空格分隔。因此,像a{b{c}}这样的字符串将被解析为名为a{b{c}}的一个节点。

创建特殊类型Node比使用弱类型数组要好得多(即使您使用的是弱类型语言)。并且不需要在结果中包含大括号。

如果你想做一些更复杂的事情,我建议使用一些解析器库。

如果字符串可能很长并且您正在从文件或网络中读取它,则可能需要使用某种形式的流而不是普通字符串。