Dernière activité 1756252881

benthos.lua Brut Playground
1local LEFT, RIGHT, LABEL, SYMBOL = 1, 2, 1, 2
2local pprint = require "pprint"
3local function read_symbol(stream)
4 local char, symbol = stream(), {}
5 if not char then return nil end
6 while char:match("%s") do char = stream() end
7 while char:match("%S") do table.insert(symbol, char) char = stream() end
8 return table.concat(symbol)
9end
10
11local function print_stacks(stacks)
12 for key, stack in pairs(stacks) do
13 io.write(key) io.write(":")
14 for i = #stack, 1, -1 do
15 local symbol = stack[i]
16 io.write(" ") io.write(symbol)
17 end
18 io.write("\n")
19 end
20end
21
22local function parse_program(program)
23 local side, rules, stream = LEFT, {{{}, {}}}, program:gmatch(".")
24 local label, rule_delimiter
25
26 local function push_pair(label, symbol)
27 table.insert(rules[#rules][side], {label, symbol})
28 end
29
30 while true do
31 local symbol = read_symbol(stream)
32 if not symbol then
33 if label then push_pair(label, "") end
34 break
35 elseif not rule_delimiter then
36 rule_delimiter = symbol
37 elseif rule_delimiter == symbol then
38 if label then push_pair(label, "") end
39 if side == RIGHT then table.insert(rules, {{}, {}}) end
40 label, side = nil, side == LEFT and RIGHT or LEFT
41 elseif not label and symbol:sub(1,1) == "/" then
42 push_pair(symbol:sub(2), "")
43 elseif not label then
44 label = symbol
45 else
46 push_pair(label, symbol)
47 label = nil
48 end
49 end
50
51 if label then push_pair(label, "") end
52
53 return rules
54end
55
56local function run(rules)
57 local stacks = {}
58 for i = #rules, 1, -1 do
59 local rule = rules[i]
60 if #rule[LEFT] == 0 then
61 for _, pair in ipairs(rule[RIGHT]) do
62 if not stacks[pair[LABEL]] then stacks[pair[LABEL]] = {} end
63 table.insert(stacks[pair[LABEL]], 1, pair[SYMBOL])
64 end
65 table.remove(rules, i)
66 end
67 end
68 local rewrite_happened repeat
69 rewrite_happened = false
70 for _, rule in ipairs(rules) do
71 local retain, bindings, success = {}, {}, true
72 for _, pattern in ipairs(rule[LEFT]) do
73 local label, pat = pattern[LABEL], pattern[SYMBOL]
74 if not stacks[label] then success = false break end
75 if #stacks[label] == 0 then success = false break end
76
77 local symbol = stacks[label][#stacks[label]]
78 table.remove(stacks[label])
79 table.insert(retain, {label, symbol})
80 if pat:sub(1, 1) == "$" then
81 if not bindings[pat] then
82 bindings[pat] = symbol
83 elseif bindings[pat] ~= symbol then
84 success = false break
85 end
86 elseif pat ~= symbol then
87 success = false break
88 end
89 end
90 rewrite_happened = success
91 while #retain ~= 0 do
92 if not success then
93 local pair = retain[#retain]
94 table.remove(retain)
95 table.insert(stacks[pair[LABEL]], pair[SYMBOL])
96 else
97 retain = {}
98 end
99 end
100 if success then
101 for i = #rule[RIGHT], 1, -1 do
102 local pair = rule[RIGHT][i]
103 local r_label, r_symbol, binding = pair[LABEL], pair[SYMBOL], bindings[pair[SYMBOL]]
104 if not stacks[r_label] then stacks[r_label] = {} end
105 table.insert(stacks[r_label], binding and binding or r_symbol)
106 end
107 break
108 end
109 end
110 until not rewrite_happened
111 print_stacks(stacks)
112end
113
114local program = [[
115 === === # bubble # sort /#
116 #list 2
117 #list 3
118 #list 1
119 #list 4
120 #list 0
121
122 === # bubble # sort /# #list $x #list $y ===
123 # ord # $x # $y /#
124 # sort # $x # $y /#
125 # bubble # sort /#
126
127 === # bubble # sort /# /request.sort ===
128 # move # ~list # to # list /#
129 # bubble # sort /#
130
131 === # bubble # sort /# ===
132 # move # ~list # to # list /#
133
134 === # move # ~list # to # list /# ~list $x ===
135 # move # ~list # to # list /# #list $x
136
137 === # move # ~list # to # list /# ===
138
139 === # sort # $x # $y /# #ord gt ===
140 ~list $y #list $x
141 # request # another # sort /#
142
143 === # sort # $x # $y /# #ord eq ===
144 ~list $y ~list $x
145
146 === # sort # $x # $y /# #ord lt ===
147 ~list $x #list $y
148
149 === # request # another # sort /# /request.sort ===
150 /request.sort
151
152 === # request # another # sort /# ===
153 /request.sort
154
155 === # ord # 0 # 0 /# === #ord eq
156 === # ord # 0 # 1 /# === #ord lt
157 === # ord # 0 # 2 /# === #ord lt
158 === # ord # 0 # 3 /# === #ord lt
159 === # ord # 0 # 4 /# === #ord lt
160
161 === # ord # 1 # 1 /# === #ord eq
162 === # ord # 1 # 2 /# === #ord lt
163 === # ord # 1 # 3 /# === #ord lt
164 === # ord # 1 # 4 /# === #ord lt
165
166 === # ord # 2 # 2 /# === #ord eq
167 === # ord # 2 # 3 /# === #ord lt
168 === # ord # 2 # 4 /# === #ord lt
169
170 === # ord # 3 # 3 /# === #ord eq
171 === # ord # 3 # 4 /# === #ord lt
172
173 === # ord # 4 # 4 /# === #ord eq
174
175 === # ord # $x # $y /# ===
176 # ord # $y # $x /#
177 # is # gt /#
178
179 === # is # gt /# #ord lt ===
180 #ord gt
181]]
182
183run(parse_program(program))