BIFParser.jl 993 Bytes
using ParserCombinator

# AST Nodes with evaluation via calc
abstract type Node end

Base.:(==)(n1::Node, n2::Node) = n1.val == n2.val

calc(n::Float64) = n

struct Inv <: Node val end
calc(i::Inv) = 1.0/calc(i.val)

struct Prd <: Node val end
calc(p::Prd) = Base.prod(map(calc, p.val))

struct Neg <: Node val end
calc(n::Neg) = -calc(n.val)

struct Sum <: Node val end
calc(s::Sum) = Base.sum(map(calc, s.val))


# The Grammar
spc = Drop(Star(Space()))

@with_pre spc begin
    sum = Delayed()
    val = E"(" + sum + E")" | PFloat64()


    neg = Delayed() # allow eg ---3
    neg.matcher = val | (E"-" + neg > Neg)

    mul = E"*" + neg
    div = E"/" + neg > Inv
    prd = neg + (mul | div)[0:end] |> Prd

    add = E"+" + prd
    sub = E"-" + prd > Neg
    sum.matcher = prd + (add | sum)[0:end] |> Sum

    all = sum + Eos()
end

# Test

expr = "1 + 2 * 3 / 4"
parsed = parse_one(expr, all)
value = calc(parsed[1])
println("Expression: $(expr)\nAST       : $parsed\nValue     : $value")