-
Notifications
You must be signed in to change notification settings - Fork 5
/
parse_expr.go
132 lines (118 loc) · 2.54 KB
/
parse_expr.go
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
124
125
126
127
128
129
130
131
132
package bebop
import (
"fmt"
)
func readBitflagExpr(tr *tokenReader, previousOptions []EnumOption, uinttype bool, bitsize int) (int64, uint64, error) {
// to simplify this a little bit, read everything up until ;
toks, err := readUntil(tr, tokenKindSemicolon)
if err != nil {
return 0, 0, err
}
// TODO: precedence (although there isn't really a natural precedence for these
// operations anyway)
parsed, err := parseBitflagExpr(toks)
if err != nil {
return 0, 0, err
}
val, uval, err := evaluateBitflagExpr(parsed, previousOptions, uinttype, bitsize)
if err != nil {
return 0, 0, err
}
return val, uval, nil
}
// productions
// start = expr
// expr = integer | ident
// expr binop expr |
// ( expr )
type bitFlagExprNode interface {
isNode()
}
type parenNode struct {
inner bitFlagExprNode
}
func (parenNode) isNode() {}
type binOpNode struct {
lhs, rhs bitFlagExprNode
op tokenKind
}
func (binOpNode) isNode() {}
type numberNode struct {
tk token
}
func (numberNode) isNode() {}
type identNode struct {
tk token
}
func (identNode) isNode() {}
func parseBitflagExpr(toks []token) (bitFlagExprNode, error) {
if len(toks) == 0 {
return nil, fmt.Errorf("empty bitflag expression")
}
i := 0
thisTk := toks[0]
var lhs bitFlagExprNode
switch thisTk.kind {
case tokenKindIdent:
lhs = identNode{
tk: thisTk,
}
case tokenKindIntegerLiteral:
lhs = numberNode{
tk: thisTk,
}
case tokenKindOpenParen:
i++
var err error
lhs, i, err = parseParenExpr(i, toks)
if err != nil {
return lhs, err
}
default:
return nil, readError(thisTk, "bad token for bitflag expr %v", thisTk.kind)
}
i++
if i >= len(toks) {
return lhs, nil
}
binOpTk := toks[i]
switch binOpTk.kind {
case tokenKindAmpersand, tokenKindVerticalBar, tokenKindDoubleCaretLeft, tokenKindDoubleCaretRight:
default:
return nil, readError(binOpTk, "undefined binary operator for bitflag %v", binOpTk.kind)
}
tree := binOpNode{
lhs: lhs,
op: binOpTk.kind,
}
i++
rhs, err := parseBitflagExpr(toks[i:])
if err != nil {
return nil, err
}
tree.rhs = rhs
return tree, nil
}
func parseParenExpr(j int, tokens []token) (node bitFlagExprNode, newI int, err error) {
startJ := j
closeNeeded := 1
for j < len(tokens) {
if tokens[j].kind == tokenKindOpenParen {
closeNeeded++
}
if tokens[j].kind == tokenKindCloseParen {
closeNeeded--
if closeNeeded == 0 {
break
}
}
j++
}
inner, err := parseBitflagExpr(tokens[startJ:j])
if err != nil {
return nil, 0, err
}
return parenNode{
inner: inner,
}, j, nil
}