-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbf.lua
More file actions
124 lines (109 loc) · 2.69 KB
/
bf.lua
File metadata and controls
124 lines (109 loc) · 2.69 KB
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
--[[
TODO: configuration file for some brainfuck behavior like tape size
]]
INC = 0
RIGHT = 1
LEFT = 2
OPENLOOP = 3
CLOSELOOP = 4
OUTPUT = 5
INPUT = 6
DEC = 7
function tape(size)
local cells = {}
local pointer = 1
for i = 1, size do
table.insert(cells, 0)
end
return {
cells = cells,
pointer = pointer
}
end
---@param code string
function brainfuck_parse(code)
local parsed_code = {}
for i = 1, string.len(code) do
local c = code:sub(i, i)
if c == "+" then
table.insert(parsed_code, INC)
elseif c == "-" then
table.insert(parsed_code, DEC)
elseif c == ">" then
table.insert(parsed_code, RIGHT)
elseif c == "<" then
table.insert(parsed_code, LEFT)
elseif c == "." then
table.insert(parsed_code, OUTPUT)
elseif c == "," then
table.insert(parsed_code, INPUT)
elseif c == "[" then
table.insert(parsed_code, OPENLOOP)
elseif c == "]" then
table.insert(parsed_code, CLOSELOOP)
end
end
return parsed_code
end
function brainfuck_eval(program)
local tp = tape(10000)
local memory = tp.cells
local ptr = tp.pointer
local stack = {}
local pc = 1
while pc <= #program do
local cmd = program[pc]
if cmd == RIGHT then
ptr = ptr + 1
elseif cmd == LEFT then
ptr = ptr - 1
elseif cmd == INC then
if memory[ptr] > 256 then
print("Cell overflow.")
os.exit(1)
end
memory[ptr] = (memory[ptr] + 1)
elseif cmd == DEC then
memory[ptr] = (memory[ptr] - 1)
elseif cmd == OUTPUT then
io.write(string.char(memory[ptr]))
elseif cmd == OPENLOOP then
if memory[ptr] == 0 then
local open_brackets = 0 -- in total we have currently 1, but somehow with the number 1 as initial it doesn't works
for i=1, #program do
if program[pc] == OPENLOOP then open_brackets = open_brackets + 1 end
if program[pc] == CLOSELOOP then open_brackets = open_brackets - 1 end
pc = pc + 1
end
if open_brackets > 0 then
error("unbalanced loop "..open_brackets)
end
else
table.insert(stack, pc)
end
elseif cmd == CLOSELOOP then
if memory[ptr] ~= 0 then
pc = stack[#stack]
else
table.remove(stack)
end
elseif cmd == INPUT then
memory[ptr] = tonumber(io.read(1))
if memory[ptr] >= 256 then
print("Cell overflow.")
os.exit(1)
end
end
pc = pc + 1
end
end
assert(#arg > 0, "Expected input file.")
for i=1, #arg do
local file = io.open(arg[i], "r")
if file then
local txt = file:read("a")
local program = brainfuck_parse(txt)
brainfuck_eval(program)
file:close()
end
end