(This post is part of a series, all with the same title) (and needs lots of work for text to actually explain things)
<script src="https://kloimhardt.github.io/blog/js/emmy.js/build/emmy_bundle.js"></script>

var div = emmy.div;

var replaceMath = (txt) => txt.replace(/\//g,"div");

var insertCommas = (txt) =>
txt.replace(/(\w+)/g,'"$1",')
   .replace(/\,\s+\]/g," ]");

var makeBrackets = (txt) =>
txt.trim()
.replace(/\(/g,"[ ")
.replace(/\)/g," ],")
.replace(/,$/,"");

var textToJson = (txt) =>
JSON.parse(insertCommas(replaceMath(makeBrackets(txt))));

var jsonToJs = (j) =>
j.constructor == Array
? jsonToJs(j[0]) + "(" +  j.slice(1).map(jsonToJs) + ")"
: j;

var swapFirst = (j) =>
j.constructor == Array
? [j[1], j[0]].concat(j.slice(2)).map(swapFirst)
: j;

var expressionToJs = (expr) =>
expr[expr.length-1] === " "
? jsonToJs(swapFirst(textToJson(expr))) + ".toString();"
: "'add blank'";
    
<script>
     var oldEval = window.eval;
     var newEval = (txt) =>
         txt[0] === "("
         ? oldEval(expressionToJs(txt))
         : oldEval(txt);
     window.eval = newEval;
</script>

((1 / 2) / 2) 
    

var mul = emmy.mul;

mul(3, div(1, 2)).toString();
    

var _replaceMath = (txt) => // old definition
txt.replace(/\//g,"div");

var __replaceMath = (txt) => // extended version
_replaceMath(txt).replace(/\*/g,"mul");

var replaceMath = __replaceMath;
    

(3 * (1 / 2)) 
    

var sub = emmy.sub;
var add = emmy.add;
var expt = emmy.expt;

var replaceMath = (txt) => // new
__replaceMath(txt)
.replace(/\-/g,"sub")
.replace(/\+/g,"add")
.replace(/\^/g,"expt");

add(1, mul(sub(div(2, 3), 4), 5)).toString();
    

(1 + (((2 / 3) - 4) * 5)) 
    

expt(2,3);
    

var _jsonToJs = (j) => // old definition
j.constructor == Array
? jsonToJs(j[0]) + "(" +  j.slice(1).map(jsonToJs) + ")"
: j;

var jsonToJs = (j) => // new
j.constructor == Array
? jsonToJs(j[0]) + "(" + j.slice(1).map(jsonToJs) + ")"
: _jsonToJs(j);

expressionToJs("(2 ^ 3) ");
    

(2 ^ 3) 
    

Up to now, the numbers in our mathematical expressions, like 1/2, 2^3, always came in pairs. If there is only one argument, like in cos(0), we would need to apply an awkward notation.


expressionToJs("(0 cos) ");
    

This notation is unacceptable and needs fixing. As an intermediate step, we write a dedicated procedure for importing functions

<script>
 var loadEnv = (name) => {
    window[name] = emmy[name];
    return name;
 }

</script>

and us it.


var names = ["sin", "cos"];

names.map(loadEnv);

cos.call(null, 0);
    

var _swapFirst = (j) => // old
j.constructor == Array
? [j[1], j[0]].concat(j.slice(2)).map(swapFirst)
: j;

var swapFirst = (j) =>
j.constructor == Array
&& ["div", "mul", "sub", "add", "expt"].includes(j[1])
? [j[1], j[0]].concat(j.slice(2)).map(swapFirst)
: j.constructor == Array
? j.map(swapFirst)
: _swapFirst(j);

jsonToJs(swapFirst(textToJson("(cos 0)")));
    

Acceptable, we can write


(1 + (cos 0)) 
    

as well as


(+ 1 (cos 0)) 
    

if not happy yet, proposal


var shiftParen = (txt) =>
names.reduce((s,r) => s.replace(r+"(","("+r+" "), txt);

var _textToJson = (txt) => // old
JSON.parse(insertCommas(replaceMath(makeBrackets(txt))));

var textToJson = (txt) =>
_textToJson(shiftParen(txt));

shiftParen("sin(cos(0))", names);
    

better


(1 + cos(sin(0))) 
    

but square has to be written like this


(sin((314 / 100)) ^ 2) 
    

Needs lots of work to improve, so stick without last step.


((sin ^ 2) (314 / 100)) 
    

In this last step we did not square a number, but we squared a function and then applied it to a number,

Before moving on, practice a bit.