最後活躍 1 month ago

capitalex's Avatar capitalex 已修改 1 month ago. 還原成這個修訂版本

1 file changed, 24 insertions

tree.lua

@@ -62,6 +62,21 @@ local function parse(string)
62 62 return build_tree(string:gmatch("."))
63 63 end
64 64
65 + local objects = {}
66 + objects.Nowhere = {
67 + objects = {},
68 + create = function(self, stream)
69 + local name = table.concat(stream(), " ")
70 + self.objects[name] = {
71 + lookAt = function(self, stream)
72 + print("You see " .. name)
73 + return self
74 + end
75 + }
76 + return self.objects[name]
77 + end
78 + }
79 +
65 80 local function reduce(tree)
66 81 if type(tree) ~= "table" then
67 82 return tree
@@ -78,6 +93,15 @@ local function reduce(tree)
78 93 for node in node_stream do
79 94 if not target then
80 95 target = reduce(node)
96 + if objects[target] then
97 + target = objects[target]
98 + end
99 + elseif type(target) == "table" then
100 + if target[node] then
101 + target = target[node](target, node_stream)
102 + else
103 + error("Object does not respond to " .. node)
104 + end
81 105 elseif type(target) == "number" then
82 106 local next = reduce(node_stream())
83 107 if node == "+" then

capitalex's Avatar capitalex 已修改 1 month ago. 還原成這個修訂版本

1 file changed, 100 insertions

tree.lua(檔案已創建)

@@ -0,0 +1,100 @@
1 + local function table_stream(t)
2 + return coroutine.wrap(function()
3 + for _, v in ipairs(t) do
4 + coroutine.yield(v)
5 + end
6 + end)
7 + end
8 +
9 + local function push(t, v)
10 + table.insert(t, v)
11 + end
12 +
13 + local 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, " ")
24 + end
25 +
26 +
27 + local 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
34 + end
35 +
36 + local 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
59 + end
60 +
61 + local function parse(string)
62 + return build_tree(string:gmatch("."))
63 + end
64 +
65 + local 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
97 + end
98 +
99 + print(show_tree(parse(arg[1])))
100 + print(reduce(parse(arg[1])))
上一頁 下一頁