Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/470.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript解析带参数的嵌套字符串函数_Javascript_Regex_String_Parsing - Fatal编程技术网

Javascript解析带参数的嵌套字符串函数

Javascript解析带参数的嵌套字符串函数,javascript,regex,string,parsing,Javascript,Regex,String,Parsing,我试图将此字符串解析为一组有组织的函数: var str = "a(b, c(e, f(h,i,j), g(k,l,m(o,p,q)) ), d(r,s,t))" 理想情况下,我想把它变成这样一个对象: var obj = { func:'a', params:[ {p:'b'}, {p: { func:'c', params:[ {

我试图将此字符串解析为一组有组织的函数:

var str = "a(b, c(e, f(h,i,j), g(k,l,m(o,p,q)) ), d(r,s,t))"
理想情况下,我想把它变成这样一个对象:

var obj = {
    func:'a',
    params:[
        {p:'b'},
        {p: {
            func:'c',
            params:[
                {
                    p:'e',
                    p:{
                        func:'f',
                        params:[
                            {p:'h'},
                            {p:'i'},
                            {p:'j'}
                        ]
                    },
                    p:'g',
                    params:[
                        {p:'k'},
                        {p:'l'},
                        {p:{
                            func:'m',
                            params:[
                                {p:'o'},
                                {p:'p'},
                                {p:'q'}
                            ]
                        }}
                    ]
                }
            ]
        }},
        {
            p:'d',
            params:[
                {p:'r'},
                {p:'s'},
                {p:'t'}
            ]
        }
    ]
}
我尝试了大约8个小时的str.replace()str.substring()和str.indexOf()混合,但没有任何运气

任何关于如何实现我的目标的帮助都将受到欢迎

注意:函数可以采用任意数量的参数,且未设置为3

更新--我停止尝试进行字符串操作,并逐个字符地处理它。要创建所需的输出:

var str = "a(b, c(e, f(h,i,j), g(k,l,m(o,p,q)) ), d(r,s,t))";
str = str.replace('/ /g,""');
var strArr = str.split('');
var firstPass = "";
var final;
var buildObj = function(){
for(var i = 0; i < strArr.length; i++){
    var letters = /^[0-9a-zA-Z]+$/;

    if(strArr[i].match(letters)){
        if(strArr[i + 1] == '('){
            firstPass += '},{"func":' + '"' + strArr[i] + '"';
        } else {
            firstPass += '"' + strArr[i] + '"';
        }

    }
    if(strArr[i] == '('){
        firstPass += ',"params":[{"p":';
    }
    if(strArr[i] == ')'){
        firstPass += '}],';
    }
    if(strArr[i] == ','){
        firstPass += '},{"p":';
    }

    //console.log(job + '}')
}

var secondPass = firstPass;
secondPass += '}'
secondPass = secondPass.replace(/,{"p":}/g,'');
secondPass = secondPass.replace('},','');
secondPass = secondPass.replace(/],}/g,']}');
final = secondPass
console.log(final)
console.log(JSON.parse(final))
var str=“a(b,c(e,f(h,i,j),g(k,l,m(o,p,q))),d(r,s,t))”;
str=str.replace('//g,“”);
var strArr=str.split(“”);
var firstPass=“”;
var最终;
var buildObj=函数(){
对于(变量i=0;i

};

正则表达式和字符串黑客是行不通的;正则表达式不能(直接)处理任何嵌套结构的文本(人们一直在学习这个…)。切换到单个字符并不能改善任何事情

通常,您需要的是一个生成标记(语言元素)的lexer和一个解析器(检查元素是否正确组织)


作为一个实际问题,您可以将这些内容组合成一个简单语言的连贯结构,就像OP感兴趣的语言一样。请轻松查看;按照这个答案回答如何构建树(本质上,如何构建您想要的结果结构).

我看到了这个问题,并认为尝试一下可能会很有趣。我将详细介绍我的思考过程,希望能对您有所帮助

我生成的对象并不完全映射到您的对象,但可以很容易地映射到您的对象。不需要额外的工作就可以得到我生成的对象,而不会被诸如将对象放入数组之类的“无关”细节分散注意力

1.)我假设空白是无用的。第一步是用零替换所有空白

function processStatement(statement) {
    return statement.replace(/[ ]/g, '');
}
// Output: a(b,c(e,f(h,i,j),g(k,l,m(o,p,q))),d(r,s,t))
2.)我的目标是创建一个树状对象,其参数不会导致更多函数成为死胡同。我需要一种解析“根”的方法,代码应该解释更多:

function produceNodeFromStatement(statement) {
    var regex = new RegExp('([a-zA-Z])\\((.+)\\)', 'g');
    var results = regex.exec(statement);
    // This regex matches for the widest pattern: identifier(stuff-inside)
    // Running the previous output would result in matching groups of:
    // identifier: a
    // stuff-inside: b,c(e,f(h,i,j),g(k,l,m(o,p,q))),d(r,s,t)

    var root = {}
    // We need a way to split the stuff-inside by commas that are not enclosed in parenthesis.
    // We want to turn stuff-inside into the following array:
    // [ 'b', 'c(e,f(h,i,j),g(k,l,m(o,p,q)))', 'd(r,s,t)' ]
    // Since my regex-fu is bad, I wrote a function to do this, explained in the next step.
    var parameters = splitStatementByExternalCommas(results[2]);

    var node = {};
    parameters.forEach(function (parameter) {
        if (parameter.indexOf('(') == -1) {
            node[parameter] = null;
        } else {
            // Recursion. This function produces an anonymous wrapper object around a node.
            // I will need to unwrap my result.
            var wrappedNode = deconstructStatement(parameter);
            var key;
            for (key in wrappedNode) {
                node[key] = wrappedNode[key];
            }
        }
    });

    // Assign node to the node's identifier
    root[results[1]] = node;
    return root;
}
3.)公式中唯一缺少的部分是只使用外部逗号分割字符串的函数-因为我无法理解正则表达式,下面是
splitStatementByExternalCommas

function splitStatementByExternalCommas(statement) {
    statement += ','; // so I don't have to handle the "last, leftover parameter"
    var results = [];
    var chars = statement.split('');
    var level = 0; // levels of parenthesis, used to track how deep I am in ().
    var index = 0; // determines which parameter am I currently on.
    var temp = '';

    // this is somewhat like your implementation in the edits, I walk through the characters one by one, and do something extra if it's a special character.
    chars.forEach(function (char) {
        switch (char) {
            case '(':
                temp += char;
                level++;
                break;
            case ')':
                temp += char;
                level--;
                break;
            case ',':
                // if the comma is between a set of parenthesis, ignore.
                if (level !== 0) { temp += char; }
                // if the comma is external, split the string.
                else { results[index] = temp; temp = ''; index++; }
                break;
            default:
                temp += char;
                break;
        }
    });
    return results;
}
4.)将所有内容放在一起,将字符串语句转换为中间对象:

var str = "a(b, c(e, f(h,i,j), g(k,l,m(o,p,q)) ), d(r,s,t))";
str = processStatement(str);
var root = produceNodeFromStatement(str);
// Output is something like:

{ 
  a: { 
       b: null,
       c: {
          e: null,
          f: { h: null, i: null, j: null },
          g: {
              k: null, l: null,
              m: { o: null, p: null, q: null }
          }
       },
       d: { r: null, s: null, t: null }
  }
}

5.)我假设从现在开始,将这个中间对象映射到您的预期目标是很简单的?

您不能对3个值使用相同的属性名称,因此您不能这样做

        func:'c',
        params:[
            {
                p:'e',
                p:{
                    func:'f',
                    params:[
                        {p:'h'},
                        {p:'i'},
                        {p:'j'}
                    ]
                },
                p:'g',
如果我们删除此部分并修复示例中其他不一致的部分(至少尝试编写一个本身不是失败的示例),那么使用eval将代码转换为javascript就相对容易:

解析器:

var parse = function (str) {

    var compiled = str.replace(/(\w+)\s*(\W)/g, function (match, name, token) {
        if (token == "(")
            return "q(\"" + name + "\",";
        else
            return "p(\"" + name + "\")" + token;
    }).replace(/,\s*\)/g, ")");

    function q(name) {
        return {
            p: {
                func: name,
                params: Array.prototype.slice.call(arguments, 1)
            }
        };
    }

    function p(name) {
        return {
            p: name
        };
    }

    var f = eval("(function (){return " + compiled + ";})");

    return f().p;
};
测试:

注:


我同意Ira Baxter的观点,您必须阅读更多关于如何进行此操作的一般信息。

您必须编写一个更复杂的解析器来解析它。通过常规语法,它不是很容易理解的。计算括号嵌套是主要问题。是的,这是我遇到的主要问题。因为要处理数量未知的参数,这就更加困难了。如果有什么想法出现在我脑海中,我洗耳恭听。解析是一个很大的话题,就像,它实际上是一门或多门你在高级计算机科学中学习的课程。这不是非常复杂,但涉及的东西很多。你考虑过吗?这会简单得多。假设字符串是有效的。如果不是,所有的赌注都没有了。
describe("x", function () {

    it("y", function () {

        var str = "a(b, c(e), d(r,s,t))";


        var obj = {
            func: 'a',
            params: [
                {p: "b"},
                {
                    p: {
                        func: 'c',
                        params: [
                            {
                                p: 'e'
                            }
                        ]
                    }
                },
                {
                    p: {
                        func: 'd',
                        params: [
                            {p: 'r'},
                            {p: 's'},
                            {p: 't'}
                        ]
                    }
                }
            ]
        };

        expect(parse(str)).toEqual(obj);

    });

});