You know how calc expressions can become a nightmare when growing in size. Nested IIFs, long chains of logical operators, service calls and dozen of brackets. And all these in a single line. It can take minutes before one can understand what is going on. Sometimes I copy the expression into a text editor and manually format it - with tabs and newlines, the same way modern IDE formats the code. Once done, it is much easier to read a logic from the rule.
Inspired by the idea to automate the routine, I did a research and then spent some time on a "grammar playground". Check out the result below or in a new window.
Current formatting logic is to simply print function parameters (when more than 2) on new lines as well as logical expressions enclosed in parenthesis. I plan to make it a bit smarter in future.
Source code
function trav(o, t, f) {
var r = "";
if ("object" === typeof o) {
var p = o.par;
var n = o.not;
if (o.type === "bin") {
r = trav(o.left, t) + " " + o.operator + " " + trav(o.right, t);
} else if (o.type === "log") {
if(p) { // format logical operators eclosed in brackets
tt = t + "\t";
r = "(\n";
r += tt + trav(o.left, tt, true);
r += "\n" + tt + o.operator + " " + trav(o.right, tt, true);
r += "\n" + t + ")";
p = false;
} else {
if(f) {
r = trav(o.left, t, true);
r += "\n" + t + o.operator + " " + trav(o.right, t, true);
} else {
r = trav(o.left, t) + " " + o.operator + " " + trav(o.right, t);
}
}
} else if (o.type === "func") {
var f = o.arguments.length > 2; // split params when more then 2
var s = (f ? "\n" + t : "");
var st = (f ? s + "\t" : "");
r = o.name + "(";
for (var i in o.arguments) {
r += st + trav(o.arguments[i], t + "\t") + (i < o.arguments.length - 1 ? ", " : "");
}
r += s + ")";
} else if (o.type === "field") {
r = "[" + o.field + "]";
} else if (o.type === "param") {
r = "[&" + o.param + "]";
} else if (o.type === "num") {
r = o.value;
} else if (o.type === "str") {
r = o.quote + o.value + o.quote;
}
if (p) {
r = "(" + r + ")";
}
if (n) {
r = "NOT " + r;
}
} else {
r = o.toString();
}
return r;
}
$(document).ready(function(){
$("#ExpParser").on("click", function() {
var s = $("#ExpParserInput").val();
console.log(s);
if (s) {
try {
var o = SiebelQueryLang.parse(s);
s = trav(o.expression, "");
} catch(e) {
s = e.toString();
}
} else {
s = "Please, insert a Siebel expression first";
}
$("#ExpParserOutput").val(s);
}).click();
})
The main outcome of the effort is, of course, to make it a part of Expression Playground. Check out an updated version here.