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.

6
  • 1
    You can't do it with a single regex. It's only possible with regex engines that support the recursion feature. Commented Jan 13, 2017 at 18:18
  • Seems like it would be simple enough to write a quick parser. Commented Jan 13, 2017 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))" Commented Jan 13, 2017 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. Commented Jan 13, 2017 at 18:30
  • Take a look at stackoverflow.com/a/4414453/4832389 Commented Jan 13, 2017 at 19:43

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@shuji No problem!
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]);
    }
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.