forked from wufenggirl/LeetCode-in-Golang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse-lisp-expression.go
executable file
·110 lines (99 loc) · 1.82 KB
/
parse-lisp-expression.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
package problem0736
import "strconv"
func evaluate(expression string) int {
return helper(expression, nil)
}
func helper(exp string, s *scope) int {
if exp[0] != '(' {
num, err := strconv.Atoi(exp)
if err != nil {
return s.get(exp)
}
return num
}
// 删除外层的 "()"
exp = exp[1 : len(exp)-1]
var keyWord string
keyWord, exp = split(exp)
switch keyWord {
case "add":
a, b := split(exp)
return helper(a, s) + helper(b, s)
case "mult":
a, b := split(exp)
return helper(a, s) * helper(b, s)
default:
// 遇到 let 就意味着要生成新的 scope 了
s = newScope(s)
var key, val string
for {
key, exp = split(exp)
if exp == "" {
break
}
val, exp = split(exp)
s.add(key, helper(val, s))
}
return helper(key, s)
}
}
// split 把 exp 分割成 pre 和 post
// 其中 pre 是 exp 中的第一个独立的块,post 则是剩下的部分
// 比如
// exp = "add 1 2"
// 则
// pre = "add"
// post = "1 2"
// 又比如
// exp = "(add x1 (add x2 x3))"
// 则
// pre = "(add x1 (add x2 x3))"
// post = ""
func split(exp string) (pre, post string) {
n := len(exp)
i := 0
if exp[0] == '(' {
countLeft := 0
for i < n {
if exp[i] == '(' {
countLeft++
} else if exp[i] == ')' {
countLeft--
}
if countLeft == 0 {
break
}
i++
}
} else {
for i+1 < n {
if exp[i+1] == ' ' {
break
}
i++
}
}
pre = exp[:i+1]
if i+1 == n {
post = ""
} else {
post = exp[i+2:]
}
return
}
type scope struct {
parent *scope
m map[string]int
}
func newScope(parent *scope) *scope {
return &scope{parent: parent, m: make(map[string]int, 8)}
}
func (s *scope) get(key string) int {
if val, ok := s.m[key]; ok {
return val
}
return s.parent.get(key)
}
func (s *scope) add(key string, val int) {
s.m[key] = val
}