blob: f5eca167ee53e5a19922dbb4da3dae12fb894083 (
plain) (
blame)
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
|
package lexpr
import (
"context"
"fmt"
"strings"
)
func (l *Lexpr) execute(ctx context.Context, tokens <-chan Token) chan Result {
out := make(chan Result)
stack := TokenStack{}
go func() {
defer func() {
for len(stack) > 0 {
ret := stack.Pop()
switch ret.typ {
case str:
out <- Result{Value: ret.value}
case number:
out <- Result{Value: ret.ivalue}
}
}
close(out)
}()
for {
select {
case <-ctx.Done():
return
case tkn, ok := <-tokens:
if !ok {
return
}
switch tkn.typ {
case number:
stack.Push(tkn)
case str:
stack.Push(Token{
typ: str,
value: strings.Trim(tkn.value, `"`),
})
case funct:
fn := l.functions[tkn.value]
if err := fn(&stack); err != nil {
out <- Result{Error: err}
return
}
case op:
op := l.operators[tkn.value]
if err := op.handler(&stack); err != nil {
out <- Result{Error: err}
return
}
case word:
variable, hasVariable := l.variables[strings.ToLower(tkn.value)]
if !hasVariable {
stack.Push(tkn)
continue
}
vtkn, ok := TokenFromAny(variable)
if !ok {
out <- Result{Error: fmt.Errorf("invalid variable value: %+v", variable)}
return
}
stack.Push(vtkn)
case tokError:
out <- Result{Error: fmt.Errorf(tkn.value)}
return
}
}
}
}()
return out
}
|