Roey Zada
Roey Zada

Reputation: 683

javascript - regex - match "parent child" relationship of repetitive tags

I have this text

parent( child( child_of_child(value)  ) )

and this regex pattern to math with

([a-z]+\(.*\))

Javascript code I use

'parent( child( child_of_child(value)  ) )'.match(/([a-z]+\(.*\))/g)

current result:

["parent( child( child_of_child(value)  ) )"]

expected result:

parent: {
     m: 'parent( child( child_of_child(value)  ) )',
     child: {
        m: 'child( child_of_child(value)  )',
        child: {
            m: 'child_of_child(value)'
        }
     }
}

Any help of direction will be very welcome

Upvotes: 1

Views: 919

Answers (3)

The fourth bird
The fourth bird

Reputation: 163477

You might use a recursive function and a pattern with 4 capturing groups where you would match from an opening till a closing parenthesis.

Then check in the next iteration check if the pattern still matches. In the next call use the groups to construct the object with the key and the values.

([^()]+)(\()(.*)(\))
  • ([^()]+) Group 1, capture 1+ times not ( or )
  • (\() Group 2, capture (
  • (.*) Group 3, capture any char 0+ times except a newline
  • (\)) Group 4, capture )

Regex demo

let pattern = /([^()]+)(\()(.*)(\))/;
let string = "parent( child( child_of_child(value)  ) )";

function parse(str, obj) {
  if (pattern.test(str)) {
    let res = str.match(pattern);
    res.shift();
    parse(res[2], obj[res[0]] = {
      'm': res.join('')
    });
  }
  return obj;
}

console.log(JSON.stringify(parse(string, {}), null, 2));

Upvotes: 1

Roey Zada
Roey Zada

Reputation: 683

Thanks to farvilain direction, I came up with the solution for this.

the regex changed to:

/([a-z\_]+)\((.*)\)/

and istead of "match" I used "replace"

and here it goes:

var explore_parent_child = (val, reg) => {
var v = val.replace(reg, (a, b, c) => {

    var res = {};
    var exp = explore_parent_child(c, reg);
    if(typeof(exp) == 'object') {
        exp.m = a;
        res[b] = exp;
    } else{
        res[b] = {
            m: a,
            child: exp
        };
    }

    return JSON.stringify(res);
})

try { return JSON.parse(v) } catch { return v };}

example run:

explore_parent_child("parent( child( child_of_child(value)  ) )", /([a-z\_]+)\((.*)\)/)

result:

parent: {
 m: 'parent( child( child_of_child(value)  ) )',
 child: {
    m: 'child( child_of_child(value)  )',
    child_of_child: {
        m: 'child_of_child(value)',
        value: 'value'
    }
 } }

Upvotes: 0

farvilain
farvilain

Reputation: 2562

Try to use this regexp instead

let regexp = /([a-z]+)(\(.*\))/;
let text = 'parent( child( child_of_child(value)  ) )';
let match = text.match(regex);

Will produce

0: "parent( child( child_of_child(value)  ) )"
1: "parent"
2: "( child( child_of_child(value)  ) )"

The difference between our regexps are the parentheses used for capture group.

This is not exactly the output you want but the transformation will be really easy.

Upvotes: 1

Related Questions