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
|
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")
|