JSFiddle - React, Tailwind, and code Playground
JavaScript
var groups = [], positions = [], parts;
var str = "(/ (+ 5 (+ 4 (- 2 (- 3 (+ 6 (/ 4 5)))))) (* 3 (* (- 6 2) (- 2 7))))";
while(( parts = str.match(/(^.*?)(\([^()]+\))(.*?$)/) )){
// parts[1] = all text before current parenthesis
// parts[2] = current parenthesis inclusive
// parts[3] = all text after current parenthesis
positions.push( parts[1].length );
groups.push( parts[2] );
str = parts[1] + parts[2].replace(/./g,"@") + parts[3];
}
var result = [];
var offset = 0;
groups.forEach(function( n, i ){
if(/[*+]/.test(n[1]) && n[1] === groups[i+1][1] && groups[i+1].indexOf("@") !== -1 ){
var add = n.replace(/[@)].*/g,"").replace(/^[^\s\d]+/,"");
offsetRxp = RegExp("@{" + (add.length-1) + "}(?!=@)");
groups[i+1] = groups[i+1].replace(/ (?=@)/,add).replace(/@+/,function(){
return n.replace(/[^\s]/g,"@").replace(offsetRxp, "");
});
} else {
for (var j = 0; j < n.length; j++) {
if(n[j] !== "@"){
result[positions[i]+j] = n[j];
}
}
}
});
var normalized = result.join("").replace(/\s+/g," ");
alert( normalized );