about summary refs log tree commit diff
path: root/pkg/lang/ast/op.go
blob: 063a309dbf2ce5b6f1db3883855aab3b9cccc3c6 (plain)
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
114
115
116
117
118
119
120
121
122
123
package ast

import (
	"fmt"
	"jinx/pkg/lang/scanner/token"
)

type BinOp int

const (
	BinOpPlus BinOp = iota
	BinOpMinus
	BinOpStar
	BinOpSlash
	BinOpPercent

	BinOpAssign
	BinOpEq
	BinOpNeq
	BinOpLt
	BinOpLte
	BinOpGt
	BinOpGte

	BinOpDot
)

func BinOpFromToken(tok token.Token) (BinOp, bool) {
	var op BinOp
	switch tok.Kind {
	case token.Plus:
		op = BinOpPlus
	case token.Minus:
		op = BinOpMinus
	case token.Star:
		op = BinOpStar
	case token.Slash:
		op = BinOpSlash
	case token.Percent:
		op = BinOpPercent
	case token.Assign:
		op = BinOpAssign
	case token.Eq:
		op = BinOpEq
	case token.Neq:
		op = BinOpNeq
	case token.Lt:
		op = BinOpLt
	case token.Lte:
		op = BinOpLte
	case token.Gt:
		op = BinOpGt
	case token.Gte:
		op = BinOpGte
	case token.Dot:
		op = BinOpDot
	default:
		return 0, false
	}

	return op, true
}

func (op BinOp) Precedence() int {
	switch op {
	case BinOpAssign:
		return 1
	case BinOpEq, BinOpNeq, BinOpLt, BinOpLte, BinOpGt, BinOpGte:
		return 2
	case BinOpPlus, BinOpMinus:
		return 3
	case BinOpStar, BinOpSlash, BinOpPercent:
		return 4
	case BinOpDot:
		return 5

	default:
		panic(fmt.Sprintf("unknown binary operator: %d", op))
	}
}

type Associativity int

const (
	AssociativityLeft Associativity = iota
	AssociativityRight
)

func (op BinOp) Associativity() Associativity {
	switch op {
	case BinOpPlus, BinOpMinus, BinOpStar, BinOpSlash, BinOpPercent:
		return AssociativityLeft
	case BinOpAssign:
		return AssociativityRight
	case BinOpEq, BinOpNeq, BinOpLt, BinOpLte, BinOpGt, BinOpGte:
		return AssociativityLeft
	case BinOpDot:
		return AssociativityLeft
	default:
		panic(fmt.Sprintf("unknown binary operator: %d", op))
	}
}

type UnOp int

const (
	UnOpBang UnOp = iota
	UnOpMinus
)

func UnOpFromToken(tok token.Token) (UnOp, bool) {
	var op UnOp
	switch tok.Kind {
	case token.Bang:
		op = UnOpBang
	case token.Minus:
		op = UnOpMinus
	default:
		return 0, false
	}

	return op, true
}