aboutsummaryrefslogtreecommitdiff
path: root/execute.go
blob: 8062d328ec1f6a1898fcfadf16fbed1c7b774275 (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
package expression

import (
	"fmt"
	"go/token"
	"strings"
)

func (e *Evaluator) execute(tokens chan Token) (any, error) {
	stack := Stack{}
	for tok := range tokens {
		switch {
		case tok.IsNumber():
			stack.Push(tok)
		case tok.IsOperator():
			op := e.operators[tok.Token]
			if err := op.fn(&stack); err != nil {
				return nil, err
			}
		case tok.IsFunc():
			fn, fnEsist := e.functions[strings.ToLower(tok.Literal)]
			if !fnEsist {
				return nil, fmt.Errorf("unknown function %s at %d", tok.Literal, tok.Pos)
			}
			if err := fn(&stack); err != nil {
				return nil, err
			}
		case tok.IsError():
			return nil, fmt.Errorf("Error at token %d: %w", tok.Pos, tok.Error())
		}
	}
	if len(stack) != 1 {
		return nil, fmt.Errorf("Expected exact one returning value, go %+v", stack)
	}
	result := stack.Pop()
	switch result.Token {
	case token.INT:
		n, _ := result.Int()
		return n, nil
	case token.FLOAT:
		return result.Float(), nil
	default:
		return result.Literal, nil
	}
}