3e0f9b8a
Francisco Coelho
back to work?
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
using ParserCombinator
# the AST nodes we will construct, with evaluation via calc()
abstract type Node end
Base.:(==)(n1::Node, n2::Node) = n1.val == n2.val
calc(n::Float64) = n
struct Const <: Node val end
calc(c::Const) = c.val
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 (the combinators!)
spc = Drop(Star(Space()))
@with_pre spc begin
sum = Delayed()
val = E"(" + sum + E")" | (PFloat64() > Const)
neg = Delayed() # allow multiple (or no) negations (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 | sub)[0:end] |> Sum
all = sum + Eos()
end
# and test
prog = "1+2*3/4"
expr = parse_one(prog, all)[1]
# this prints 2.5
value = calc(expr)
println("$prog → $expr = $value")
|