-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
118 lines (107 loc) · 2.18 KB
/
main.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
package main
import (
"fmt"
"os"
"io/ioutil"
"bytes"
)
type action int
const (
Increment action = iota
Decrement
Next
Back
Print
Read
StartLoop
EndLoop
)
const DEFAULT_ARRAY_SIZE = 10
type Token struct {
name action
jumpTo int
}
func execute(bf string) string {
var cursor byte
var output bytes.Buffer
tokens := tokenizer(bf)
arr := make([]byte, DEFAULT_ARRAY_SIZE)
for i := 0; i < len(tokens); i++ {
switch tokens[i].name {
case Increment: arr[cursor] += 1
case Decrement: arr[cursor] -= 1
case Next:
if int(cursor) >= len(arr) {
increasedArray := make([]byte, len(arr)*2)
copy(increasedArray, arr)
arr = increasedArray
}
cursor += 1
case Back: cursor -= 1
case Print: output.WriteString(string(arr[cursor]))
case Read:
var input byte
_, err := fmt.Scanf("%c", &input)
if err != nil {
panic(err)
}
arr[cursor] = input
case StartLoop:
if arr[cursor] == 0 {
i = int(tokens[i].jumpTo)
}
case EndLoop:
if arr[cursor] != 0 {
i = int(tokens[i].jumpTo)
}
}
}
return output.String()
}
func tokenizer(bf string) (tokens []Token) {
var pointer int
jumpStack := make([]int, 0)
for i := 0; i < len(bf); i++ {
switch bf[i] {
case '+':
tokens = append(tokens, Token{Increment, 0})
case '-':
tokens = append(tokens, Token{Decrement, 0})
case '>':
tokens = append(tokens, Token{Next, 0})
case '<':
tokens = append(tokens, Token{Back, 0})
case '.':
tokens = append(tokens, Token{Print, 0})
case ',':
tokens = append(tokens, Token{Read, 0})
case '[':
tokens = append(tokens, Token{StartLoop, 0})
jumpStack = append(jumpStack, i)
case ']':
if len(jumpStack) == 0 {
panic("wrong loop")
}
pointer = jumpStack[len(jumpStack)-1]
jumpStack = jumpStack[:len(jumpStack)-1]
tokens = append(tokens, Token{EndLoop, pointer})
tokens[pointer].jumpTo = i
}
}
return tokens
}
func main() {
args := os.Args
if len(args) != 2 {
fmt.Printf("Usage: %s filename\n", args[0])
return
}
filename := args[1]
content, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Printf("Error reading %s\n", filename)
return
}
str := execute(string(content))
fmt.Print(str)
}