Convert an Expression to Panfix Notation I was browsing esolangs, and chanced upon this language: https://github.com/catseye/Quylthulg.
One interesting thing about this language, is that it doesn't use prefix, postfix, or infix, it uses all three of them, calling it &quot;panfix&quot; notation.
Here is an example. To represent normal infix 1+2 in panfix, it becomes: +1+2+. Notice how the operator is both before, in between, and after the operands. Another example is (1+2)*3. This becomes *+1+2+*3*. Notice again how * is in all three places with respect to the operands +1+2+ and 3.
The Challenge
As you may have guessed, your task in this challenge is to convert an expression from infix to panfix.
A few clarifications:

You only have to deal with the four basic operations: +-*/
You won't have to deal with the unary versions of those, only binary
You have to deal with parenthesis
Assume the normal precedence rules of */ then +- and left associativity for all of them.
The numbers will be nonnegative integers
You can optionally have a spaces in both the input and output

Test Cases
1+2  -&gt;  +1+2+
1+2+3  -&gt;  ++1+2++3+
(1+2)*3  -&gt;  *+1+2+*3*
10/2*5  -&gt;  */10/2/*5*
(5+3)*((9+18)/4-1)  -&gt;  *+5+3+*-/+9+18+/4/-1-*

This is code-golf, so shortest code in bytes wins!
JavaScript (ES6), 285 282 281 267 251 243 241 238 234 232 231 bytes
~15 bytes thanks to Neil.
f=(I,E=I.match(/\d+|./g),i=0)=&gt;(J=T=&gt;T.map?T.map(J).join``:T)((R=(H,l=(P=_=&gt;(t=E[i++])&lt;&quot;)&quot;?R(0):t)(),C,F)=&gt;{for(;(C=P())&gt;&quot;)&quot;&amp;&amp;(q=C&gt;&quot;*&quot;&amp;&amp;C&lt;&quot;/&quot;)*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C&gt;&quot;)&quot;
return l})(0))

In JavaScript this is a bit harder than in Mathematica. This is basically an over-specialized and golfed operator-precedence parser.
Causes stack overflows on invalid inputs.
Demo


f=(I,E=I.match(/\d+|./g),i=0)=&gt;(J=T=&gt;T.map?T.map(J).join``:T)((R=(H,l=(P=_=&gt;(t=E[i++])&lt;")"?R(0):t)(),C,F)=&gt;{for(;(C=P())&gt;")"&amp;&amp;(q=C&gt;"*"&amp;&amp;C&lt;"/")*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C&gt;")"
return l})(0))
&lt;input id="input" value="(5+3)*((9+18)/4-1)"/&gt;&lt;button onclick="console.log(f(document.querySelector('#input').value))"&gt;Convert&lt;/button&gt;



Ungolfed
convert = input =&gt; {
  tokens = input.match(/\d+|./g);
  i = 0;
  parse_token = () =&gt; (token = tokens[i++]) == &quot;(&quot; ? parse_tree(false) : token;
  parse_tree = (mul_div_mode, left = parse_token()) =&gt; {
    while ((oper = parse_token()) != &quot;)&quot; &amp;&amp; !((is_plus_minus = oper == &quot;+&quot; || oper == &quot;-&quot;) &amp;&amp; mul_div_mode)) {
      if (is_plus_minus || mul_div_mode)
        left = [oper, left, oper, parse_token(), oper];
      else if (non_first)
        left[3] = [oper, left[3], oper, parse_tree(true), oper];
      else
        left = parse_tree(true, left, i--);
      non_first = true;
    }
    if (oper != &quot;)&quot;)
      i--;
    return left;
  };
  format_tree = tree =&gt; tree.map ? tree.map(format_tree).join(&quot;&quot;) : tree;
  return format_tree(parse_tree(false));
}