我有以下示例查询,它们表示复杂程度不同的对象:

abc,def,ghi

abc,\def,ghi

abc,\def{ghi,jkl},mno

abc,\def{ghi,\jkl},mno

abc,\def{ghi,\jkl{mno,pqr,\stu},vwx


在上面的示例中,我仅使用3个字母来表示一个单词。这个词可以是任何长度。

有两种不同类型的单词。如果单词以反斜杠开头,则称为边。如果不是,则称为字段。

场和边可以属于边。这些在edge {}中定义。这是无限递归的,因此单词可以属于边,而边又属于边等。

我想解析此字符串以将其转换为JavaScript对象。

很难解释,所以一个例子可能更好。

例如1,它将转换为:

[
    {
        type: "field",
        val: "abc"
    },
    {
        type: "field",
        val: "def"
    },
    {
        type: "field",
        val: "ghi"
    },
]


例如2,它将转换为:

[
    {
        type: "field",
        val: "abc"
    },
    {
        type: "edge",
        val: "def",
        children: []
    },
    {
        type: "field",
        val: "ghi"
    }
]


例如5,它将转换为:

[
    {
        type: "field",
        val: "abc"
    },
    {
        type: "edge",
        val: "def",
        children: [
            {
                type: "field",
                val: "ghi"
            },
            {
                type: "edge",
                val: "jkl",
                children: [
                    {
                        type: "field",
                        val: "mno"
                    },
                    {
                        type: "field",
                        val: "pqr"
                    },
                    {
                        type: "edge",
                        val: "stu",
                        children: []
                    }
                ]
            }
        ]
    },
    {
        type: "field",
        val: "vwx"
    }
]


为此,我想它必须逐个字符地对字符串进行爬网,计算出当前正在查看的内容,并随对象进行构建/遍历。也许我可以使用某种递归正则表达式?

关于如何最好地做到这一点的任何想法?任何想法,概念等将不胜感激。

最佳答案

我建议编写语法并实现recursive descent parser。它们非常简单。

var parse = function(s){

    var i = 0;

    var peek = function(c){
        return s[i] === c;
    };

    var next = function(c){
        var found = s[i];
        if(c && s[i] !== c){
            throw 'expected ' + c + ' at char ' + i + ': ' + s.slice(i,20);
        }
        i += 1;
        return found;
    };

    var word = function(){
        var w = '';
        if(!/[a-z]/.test(s[i])){
            throw 'expected a word at char ' + i + ': ' + s.slice(i,20);
        }
        while(s[i] && /[a-z]/.test(s[i])){
            w += s[i];
            i += 1;
        }
        return w;
    };

    var edge = function(){
        next('\\');
        var val = word();
        var e = {
            type: 'edge',
            val: val
        };
        if(peek('{')){
            next('{');
            e.children = fields_or_edges();
            next('}');
        }
        return e;
    };

    var field = function(){
        return {
            type: 'field',
            val: word()
        };
    };

    var fields_or_edges = function(){
        var stuff = [];
        var thing;
        do {
            if(peek('\\')){
                thing = edge();
            }else{
                thing = field();
            }
            stuff.push(thing);
        }while(peek(',') && next());
        return stuff;
    };

    return fields_or_edges();
};


让我们测试一下。

[
    'abc,def,ghi',
    'abc,\\def,ghi',
    'abc,\\def{ghi,jkl},mno',
    'abc,\\def{ghi,\\jkl},mno',
    'abc,\\def{ghi,\\jkl{mno,pqr,\\stu},vwx' // uncaught exception: expected } at char 35:
].forEach(function(s){
    console.log(JSON.stringify(parse(s), null, 4));
});


请注意,如果运行此命令,则解析器将在最终测试字符串的char 35处收到一个错误:不关闭'}'。

关于javascript - 将字符串解析为对象(自定义格式),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31564047/

10-11 10:35