# Get the structure of an arithmetic expression

**URL:** https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712
**Category:** General Usage
**Tags:** question, symbolics
**Created:** [December 16, 2023, 4:26pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712 "2023-12-16T16:26:34Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![\_stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_stla/32/35613_2.png) [@\_stla](https://discourse.julialang.org/u/_stla)
#### Post date: [December 16, 2023, 4:26pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/1 "2023-12-16T16:26:34Z")

</div>

Hello,

Given an arithmetic expression, for example `x + y/z`, I want to decompose it to something like `+(x, /(y, z)`. Is it possible with Julia? I thought this was the result of `:(x + y/z)` but no.

The reason is that I have long arithmetic expression and I want to get `math.add(x, math.divide(y, z))` for a JavaScript code. It’s painful to do that manually.

If you know how to do with another language this is ok too.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [December 16, 2023, 6:13pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/2 "2023-12-16T18:13:30Z")

</div>

> [@\_stla](#):
>
> I thought this was the result of `:(x + y/z)` but no.

You were probably misled by the source code syntax printing, expressions are indeed structured like you’re thinking:

```julia
julia> :(x + y/z)
:(x + y / z)

julia> :( +(x, /(y, z)) )
:(x + y / z)

julia> :( +(x, /(y, z)) ) == :(x + y/z)
true

julia> dump( :(x + y/z) )
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Symbol x
    3: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol /
        2: Symbol y
        3: Symbol z

```

Transpiling may not be this easy, there isn’t always a one-to-one correspondence of functions, and the arity of the most equivalent functions may differ, which can affect operator parsing.

---

<div class="post-metadata">

### Author: ![\_stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_stla/32/35613_2.png) [@\_stla](https://discourse.julialang.org/u/_stla)
#### Post date: [December 16, 2023, 6:17pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/3 "2023-12-16T18:17:26Z")

</div>

Thanks. I only use the four arithmetic operators +, -, \* and /, each binary.

I found a way in R, but I’m still curious concerning a Julia way.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [December 16, 2023, 7:00pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/4 "2023-12-16T19:00:50Z")

</div>

I’m curious, why metaprogram in another language and transpile to Javascript instead of just writing the expressions with binary +,-,\*,/ in Javascript to begin with? Is math.add and math.divide different? Does Javascript not have ways to modify and evaluate AST expressions?

---

<div class="post-metadata">

### Author: ![\_stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_stla/32/35613_2.png) [@\_stla](https://discourse.julialang.org/u/_stla)
#### Post date: [December 16, 2023, 7:02pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/5 "2023-12-16T19:02:55Z")

</div>

Because I deal with complex numbers in JavaScript. `math.add` is the complex addition, etc.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [December 16, 2023, 7:19pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/6 "2023-12-16T19:19:49Z")

</div>

Ah that makes sense. And having looked it up it doesn’t seem like Javascript exposes ASTs as much as Julia and R does, or at least people don’t talk about it. math.js [has its own parser](https://mathjs.org/docs/expressions/parsing.html) and [AST tooling](https://mathjs.org/docs/expressions/expression_trees.html), do you think that can serve your purposes? It may be a bit awkward because the scoping and parsing isn’t tied to the language, but it’s a lot better than doing the metaprogramming in an entirely different language and crossing fingers for a one-to-one translation.

---

<div class="post-metadata">

### Author: ![\_stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_stla/32/35613_2.png) [@\_stla](https://discourse.julialang.org/u/_stla)
#### Post date: [December 16, 2023, 7:25pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/7 "2023-12-16T19:25:31Z")

</div>

That’s ok, I’ve finished to do what I wanted with the help of R.

In JavaScript there’s the **acorn** library which is a complete AST constructor, not only for arithmetic expressions. It constructs an AST for any piece of JavaScript code.

[Here](https://codegolf.stackexchange.com/questions/256990/parse-basic-arithmetic-into-an-ast) is a thread about AST parsers in several languages.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [December 16, 2023, 8:43pm UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/8 "2023-12-16T20:43:33Z")

</div>

Those are fun examples but not very general-purpose. acorn looks more general-purpose but at first browse I couldn’t see how metaprogramming could be done, so math.js’s parsing still seems like the more official way.

How are you transferring ASTs between separate languages anyway, strings? If so, that would explain the post; it’s not that the `Expr`ession is not structured right, it’s that printing and `string` deparses the same way to infix notation. I don’t know of a way to reduce infix notation as much as possible; it’s not possible entirely because some operators are infix-only, like `_?_:_`.

If you replace the operators with alphabetical symbols or expressions, it will be deparsed to function calls like you need; in the general case, it’s just a matter of recursively visiting nested `Expr` and replacing operator symbols mapped to alternate names. I imagine you did something similar in R.

```julia
julia> ex = :( +(x, /(y, z)) )
:(x + y / z)

julia> ex.args[1] = :(math.add); ex.args[3].args[1] = :(math.divide); ex
:(math.add(x, math.divide(y, z)))

julia> string(ex)
"math.add(x, math.divide(y, z))"

julia> function replacesymbols!(ex::Expr, symbolmap::AbstractDict{Symbol})
         ex.head = get(symbolmap, ex.head, ex.head)
         for i in eachindex(ex.args)
           arg = ex.args[i]
           if arg isa Symbol
             ex.args[i] = get(symbolmap, arg, arg)
           elseif arg isa Expr
             replacesymbols!(arg, symbolmap)
           end
         end
         ex # input is already mutated so not a necessary return
       end

julia> altops = Dict(:+ => :(math.add),
                     :- => :(math.subtract),
                     :* => :(math.multiply),
                     :/ => :(math.divide),
                     );

julia> ex = :(a+b/c*e-f^g) # note that ^ is not in mapping
:((a + (b / c) * e) - f ^ g)

julia> replacesymbols!(ex, altops)
:(math.subtract(math.add(a, math.multiply(math.divide(b, c), e)), f ^ g))

julia> string(ex)
"math.subtract(math.add(a, math.multiply(math.divide(b, c), e)), f ^ g)"

```

Bear in mind that there aren’t always built-in alphabetical aliases for infix operators in Julia, for example `÷` has `div` but `+` is by itself, so only `eval` the expression prior to replacement in Julia.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [December 17, 2023, 3:38am UTC](https://discourse.julialang.org/t/get-the-structure-of-an-arithmetic-expression/107712/9 "2023-12-17T03:38:46Z")

</div>

> [@Benny](#):
>
> `function replacesymbols!(ex::Expr, symbolmap::AbstractDict{Symbol})`

Probably easier to use the MacroTools.jl package for this sort of thing. For example:

```julia
julia> using MacroTools

julia> symbolmap = Dict(:+ => :(math.add), :- => :(math.sub), :* => :(math.mul), :/ => :(math.div), :^ => :(math.pow));

julia> MacroTools.postwalk(x -> get(symbolmap, x, x), :(x + y / (z - 2y)))
:(math.add(x, math.div(y, math.sub(z, math.mul(2, y)))))

```
