-
Notifications
You must be signed in to change notification settings - Fork 0
/
calc.lua
executable file
·109 lines (97 loc) · 2.4 KB
/
calc.lua
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
#!/usr/bin/env lua
function splitTokens(s)
local tokens = {}
for i in string.gmatch(s, '%w+') do
table.insert(tokens, i)
end
return tokens
end
PLUS = 'a'
MINUS = 's'
TIMES = 'm'
DIVIDE = 'd'
function isDash(token)
return token == PLUS or token == MINUS
end
function isDot(token)
return token == TIMES or token == DIVIDE
end
function parseNum(tokens)
local val = table.remove(tokens, 1)
val = tonumber(val)
return {
['type'] = 'num',
['num'] = val
}
end
function parseFactor(tokens)
local lhs = parseNum(tokens)
while isDot(tokens[1]) do
local op = table.remove(tokens, 1)
local rhs = parseNum(tokens)
lhs = {
['type'] = 'op',
['op'] = op,
['lhs'] = lhs,
['rhs'] = rhs
}
end
return lhs
end
function parseTerm(tokens)
local lhs = parseFactor(tokens)
while isDash(tokens[1]) do
local op = table.remove(tokens, 1)
local rhs = parseFactor(tokens)
lhs = {
['type'] = 'op',
['op'] = op,
['lhs'] = lhs,
['rhs'] = rhs,
}
end
return lhs
end
function parseExpr(tokens)
return parseTerm(tokens)
end
function eval(expr)
if expr['type'] == 'num' then
return expr['num']
elseif expr['type'] == 'op' then
local lval = eval(expr['lhs'])
local rval = eval(expr['rhs'])
if expr['op'] == PLUS then
return lval + rval
elseif expr['op'] == MINUS then
return lval - rval
elseif expr['op'] == TIMES then
return lval * rval
elseif expr['op'] == DIVIDE then
return lval / rval
else
print('invalid operator!')
end
else
print('invalid expr type!')
end
end
function printTree(expr, depth)
local indent = string.rep(' ', depth)
print(indent .. 'type: ' .. expr['type'])
if expr['type'] == 'num' then
print(indent .. 'num: ' .. expr['num'])
elseif expr['type'] == 'op' then
print(indent .. 'op: ' .. expr['op'])
print(indent .. 'lhs:')
printTree(expr['lhs'], depth + 1)
print(indent .. 'rhs:')
printTree(expr['rhs'], depth + 1)
else
print('invalid expr type!')
end
end
tree = parseExpr(splitTokens(arg[1]))
print('tree:')
printTree(tree, 0)
print('result: ' .. eval(tree))