coder9
coder9

Reputation: 1549

Parsing using regex in recursive functions in Javascript

I want to parse a string which contains shortcodes and push each extracted node into an array. However the recursive function I have written for this never terminates. What am I doing wrong here?

var i = 0;
var nodes = [];
var pattern = /(\[sc_(\w+)[\s\w="_-]*\])(.*)(\[\/sc_\2\])/gi;

var extractNodes = function(str, parent) {
    var m;

    if (str.indexOf('[sc_') === -1) return;

    while ((m = pattern.exec(str)) !== null) {
        nodes.push({
            id: i,
            tag: m[2],
            children: m[3],
            parentId: parent
        });
        extractNodes(m[3], i++);
    }
}

extractNodes("[sc_div][sc_span][sc_strong]Foo[/sc_strong][/sc_span][/sc_div]", -1); 

Upvotes: 1

Views: 162

Answers (1)

ak_
ak_

Reputation: 2815

You've got a conflict between your while loop and the global (g flag) RegEx.

Each iteration of the function is sending the same str parameter. You can fix this by making the RegEx non-global by removing the g flag and while loop.

Live Demo

var i = 0;
var nodes = [];
var pattern = /(\[sc_(\w+)[\s\w="_-]*\])(.*)(\[\/sc_\2\])/i; // <-- Remove `g` flag

var extractNodes = function (str, parent) {
    var m;
    if (str.indexOf('[sc_') === -1) return;

    if ((m = pattern.exec(str)) !== null) {
        nodes.push({
            id: i,
            tag: m[2],
            children: m[3],
            parentId: parent
        });

        extractNodes(m[3], i++);
    }
}

extractNodes("[sc_div][sc_span][sc_strong]Foo[/sc_strong][/sc_span][/sc_div]", -1);
console.log(nodes);

document.body.innerHTML = '<pre>' + JSON.stringify(nodes, 0, 4) + '</pre>'; // For DEMO purpose only

Console Output (Chrome):

[Object, Object, Object]
0:Object
  children: "[sc_span][sc_strong]Foo[/sc_strong][/sc_span]"
  id: 0
  parentId: -1
  tag: "div"
  __proto__: Object
1:Object
  children: "[sc_strong]Foo[/sc_strong]"
  id: 1
  parentId: 0
  tag: "span"
  __proto__: Object
2:Object
  children: "Foo"
  id: 2
  parentId: 1
  tag: "strong"
  __proto__: Object
length: 3
__proto__: Array[0]

Upvotes: 1

Related Questions