最後活躍 1 month ago

修訂 e937327a7408471e4f5d695beae50b077b23564b

tree.lua 原始檔案 Playground
1local function table_stream(t)
2 return coroutine.wrap(function()
3 for _, v in ipairs(t) do
4 coroutine.yield(v)
5 end
6 end)
7end
8
9local function push(t, v)
10 table.insert(t, v)
11end
12
13local function show_tree(tree)
14 local buffer = {}
15 for node in table_stream(tree) do
16 if type(node) == "table" then
17 local subtree = ("(%s)"):format(show_tree(node))
18 push(buffer, subtree)
19 else
20 push(buffer, tostring(node))
21 end
22 end
23 return table.concat(buffer, " ")
24end
25
26
27local function build_symbol(bits)
28 local symbol = table.concat(bits)
29 if tonumber(symbol) then return tonumber(symbol)
30 elseif symbol == "true" then return true
31 elseif symbol == "false" then return false
32 else return symbol
33 end
34end
35
36local function build_tree(stream)
37 local tree = {}
38 local symbol = {}
39 for char in stream do
40 if char == "(" then
41 push(tree, build_tree(stream))
42 elseif char == ")" then
43 break
44 elseif char == " " and #symbol ~= 0 then
45 push(tree, build_symbol(symbol))
46 symbol = {}
47 elseif char:match("%s") then
48 -- no op
49 else
50 push(symbol, char)
51 end
52 end
53
54 if #symbol ~= 0 then
55 push(tree, build_symbol(symbol))
56 end
57
58 return tree
59end
60
61local function parse(string)
62 return build_tree(string:gmatch("."))
63end
64
65local function reduce(tree)
66 if type(tree) ~= "table" then
67 return tree
68 end
69
70 local index = 1
71 local target = nil
72 local node_stream = coroutine.wrap(function()
73 for _, node in ipairs(tree) do
74 coroutine.yield(node)
75 end
76 end)
77
78 for node in node_stream do
79 if not target then
80 target = reduce(node)
81 elseif type(target) == "number" then
82 local next = reduce(node_stream())
83 if node == "+" then
84 target = target + next
85 elseif node == "-" then
86 target = target - next
87 elseif node == "*" then
88 target = target * next
89 elseif node == "/" then
90 target = target / next
91 else
92 error("Object does not respond to " .. node)
93 end
94 end
95 end
96 return target
97end
98
99print(show_tree(parse(arg[1])))
100print(reduce(parse(arg[1])))
101