arithfunclang.jl
2.77 KB
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
# repr(n::Float64) = string(n)
struct Const <: Node val end
calc(c::Const) = c.val
# repr(c::Const) = repr(c.val)
struct Inv <: Node val end
calc(i::Inv) = 1.0/calc(i.val)
# repr(i::Inv) = "1.0/$(repr(i.val))"
struct Prd <: Node val end
calc(p::Prd) = Base.prod(map(calc, p.val))
# repr(p::Prd) = join(map(repr, p.val), "×")
struct Neg <: Node val end
calc(n::Neg) = -calc(n.val)
# repr(n::Neg) = "-$(repr(n.val))"
struct Sum <: Node val end
calc(s::Sum) = Base.sum(map(calc, s.val))
# repr(s::Sum) = join(map(repr, s.val), "+")
struct TermSequence <: Node val end
calc(ts::TermSequence) = map(calc, ts.val)
# repr(ts::TermSequence) = join(map(repr, ts.val), ",")
struct Functor <: Node val end
calc(f::Functor) = nothing
# repr(f::Functor) = "$(ts.val)"
struct Function <: Node val end
calc(f::Function) = Const(0.0)
# repr(f::Function) = "$(repr(f.val[1]))($(repr(f.val[2])))"
# the grammar (the combinators!)
#=
sum ::= prd (add | sub)*
add ::= "+" prd
sub ::= "-" prd
prd ::= neg (mul | div)*
=#
@with_names begin
spc = Drop(Star(Space()))
@with_pre spc begin
sum = Delayed()
term_sequence = StarList(sum, E",") |> TermSequence
functor = p"[a-z][a-zA-Z0-9_]*" > Functor
func = functor + E"(" + term_sequence + E")" |> Function
val = E"(" + sum + E")" | (PFloat64() > Const)
neg = Delayed() # allow multiple (or no) negations (eg ---3)
neg.matcher = func | val | (E"-" + neg > Neg)
mul = E"*" + neg
div = E"/" + neg > Inv
prd = neg + Star(mul | div) |> Prd
add = E"+" + prd
sub = E"-" + prd > Neg
sum.matcher = prd + Star(add | sub) |> Sum
arith_lang = (func | val | neg | prd | sum) + Eos()
func_lang = func + Eos()
tl_lang = term_sequence + Eos()
end
end
# and test
source = "f(1,2,3+4)*1+g(5,10,h(100,3))"
grammar = arith_lang
debug, task = make(Debug, source, grammar; delegate=NoCache)
try
expr = once(task)
println("---\n\"$source\"\tparses to\t\"$(expr)\"\n---")
catch ParserException
println("Error parsing after \"$(source[1:debug.max_iter - 1])\" and before \"$(source[debug.max_iter:end])\".\n")
#println(grammar)
parse_dbg(source, Trace(grammar))
end
x = Any[
Sum(
Any[
Prd(
Any[
Const(2.0)
]
),
Prd(
Any[
Const(3.0),
Const(4.0)
]
)
]
)
]