0

I have a string of type "sum(sum(_))" in which _ can be one or many(separated by commas) function call, string between quotes, etc.

//should return true
/sum\(sum\(_\)\)/.test('sum(sum(2,3,4))')
/sum\(sum\(_\)\)/.test('sum(sum(a,b,c))')
/sum\(sum\(_\)\)/.test('sum(sum(neg(2),neg(neg(3))))')

I can actually match the string and other parameters but there is complication when I try to match nested function calls.

Anyone knows how to do this with regex or some library in javascript made for dealing with this type of problem? Thanks in advance.

shuji
  • 7,369
  • 7
  • 34
  • 49
  • 1
    You can't do it with a single regex. It's only possible with regex engines that support the recursion feature. – Casimir et Hippolyte Jan 13 '17 at 18:18
  • Seems like it would be simple enough to write a quick parser. –  Jan 13 '17 at 18:18
  • @squint ok fair enough but when I try to parse the content the parenthesis are always on the way. Any hint will be apreciated for example when I have something like this: "div(sum(sum(2,3),3))" – shuji Jan 13 '17 at 18:22
  • You'd use recursion. You create a function that parses the function call. When analyzing and parsing each argument, if an argument is another function call, you make another call into the function that parses the function call. –  Jan 13 '17 at 18:30
  • Take a look at http://stackoverflow.com/a/4414453/4832389 – Joe Jan 13 '17 at 19:43
  • @Joe thank you bro, I remember once I tried to count the parenthesis but it was a very messy solution I guess I'll have to stick with it or find some regex implementation with those recursion features. – shuji Jan 13 '17 at 20:11

2 Answers2

1

I suggest you use a parser like below to get the inner string.

var nestedFunctions = getInnerString("sum(sum(neg(2),neg(neg(3))))", 8)
console.log(nestedFunctions); // should return -> neg(2),neg(neg(3))


function getInnerString(text, startIndex) {
  startIndex = !startIndex ? 0 : startIndex;
  var endIndex = getEndIndexForParathesis(text, startIndex);
  var innerString = text.substring(startIndex, endIndex);
  return innerString;
}

function getEndIndexForParathesis(text, start) {
  start = !start ? 0 : start;
  var subGroups = 0
  var endIndex = 0;
  for (var i = start, len = text.length; i < len; i++) {
    var letter = text[i]
    if (letter === '(') {
      subGroups++;
      continue;
    }
    if (letter === ')' && subGroups != 0) {
      subGroups--;
      continue;
    }
    if (letter === ')' && subGroups == 0) {
      endIndex = i;
      break;
    }
  }
  return endIndex;
}

I hope this works for you. I tried regex but it was getting very difficult to extract the inner text in all three cases.

Piyush
  • 1,162
  • 9
  • 17
0

Here is an example of a parsing algorithm. It works best, if you don't use commas in a function call. Commas are at the moment only working on top level. You need to further improve the algorithm, if you want to use commas. It is only a first draft to give you a hint on how to recursively parse an expression:

var expression = "neg(2),neg(neg(3))";
var data = [];
parse(data, expression);
console.log(data);

function parse(data, expression) {
  var expressionArray = expression.split(",");
  for(var i = 0; i < expressionArray.length; i++) {
    var element = expressionArray[i];
    var match = element.match(/^([a-zA-Z]+?)\((.*)\)$/);
    var entry = {};
    data.push(entry);
    
    entry.element = element;
    entry.children = [];
    if(match) {
       entry.function = match[1];
       parse(entry.children, match[2]);
    }
  }
}
ssc-hrep3
  • 15,024
  • 7
  • 48
  • 87