Ultima attività 1755999453

february.lua Raw Playground
1local pprint = require "pprint"
2local program = [[
3= = @rpn \\ [3] [4] dup * swap dup * swap + sqrt print
4
5= @rpn dup . @rpn.data $ =
6 @rpn.data \\ $ $
7
8= @rpn swap . @rpn.data \\ $x $y =
9 @rpn.data \\ $y $x
10
11= @rpn * . @rpn.data \\ $y $x =
12 @rpn.data $z . @code [$z = $x * $y]
13
14= @rpn + . @rpn.data \\ $y $x =
15 @rpn.data $z . @code [$z = $x + $y]
16
17= @rpn sqrt . @rpn.data $x =
18 @rpn.data $y . @code [$y = math.sqrt(tonumber($x))]
19
20= @rpn print . @rpn.data $x =
21 @code [print($x)]
22
23= @rpn $x =
24 @rpn.data $x
25]]
26-- [TODO] make parser module
27-- - add symbol parsing hooks (for `[` and `"`)
28-- - add symbol stream hooks (for things like `( a b c )`)
29-- - add rule steam hooks (for things like `?`)
30-- - add post-parsing hooks (for full rule set transformation)
31local stream = program:gmatch(".")
32local char, rule, rule_symbol, label_symbol, depth, symbol, side, striding
33local tuple, rules, LEFT, RIGHT = {}, {}, 1, 2
34repeat
35 rule_symbol, char = "", stream()
36 side, rule = LEFT, {{}, {}}
37 while char and char:match("[%s%.,]") do
38 -- skip all characters that can't be bound
39 char = stream()
40 end
41 if char == nil then
42 break
43 elseif char == "[" then
44 -- rule delimiter is multibyte
45 depth, char = 1, stream()
46 while char do
47 if char == "[" then depth = depth + 1 end
48 if char == "]" then depth = depth - 1 end
49 if depth == 0 then break end
50 rule_symbol, char = rule_symbol .. char, stream()
51 end
52 else
53 -- rule delimiter is a single character
54 rule_symbol = "" while char and not char:match("%s") do
55 rule_symbol, char = rule_symbol .. char, stream() if char == "[" then
56 io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
57 end
58 end
59 end
60 repeat -- consume rules from this set
61 char = stream()
62 while char and (char:match("[%s]") or not label_symbol and char:match("[%.,]")) do
63 -- skip whitespace or [.,] if a label hasn't been selected
64 char = stream()
65 end
66 if not char then
67 if label_symbol and not striding then
68 table.insert(rule[side], {label_symbol, tuple})
69 end
70 break
71 end
72 -- read a symbol from the stream
73 if char:match("[%.,]") then
74 -- we've hit a tuple related delimiter
75 symbol = char
76 elseif char == "[" then
77 -- parse a boxed symbol
78 symbol, depth, char = "", 1, stream() while char do
79 if char == "[" then depth = depth + 1 end
80 if char == "]" then depth = depth - 1 end
81 if depth == 0 then break end
82 symbol, char = symbol .. char, stream()
83 end
84 else
85 -- parse a symbol seperated by spaces
86 -- this segment warns if a symbol contains `[`
87 symbol = "" while char and not char:match("%s") do
88 symbol, char = symbol .. char, stream() if char == "[" then
89 io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
90 end
91 end
92 end
93 -- process that symbol
94 if symbol == "," then
95 -- push a tuple
96 table.insert(rule[side], {label_symbol, tuple})
97 striding, tuple = false, {}
98 elseif symbol == "." then
99 -- push a tuple, clear label symbol
100 if not (striding and #tuple == 0) then
101 table.insert(rule[side], {label_symbol, tuple})
102 end
103 striding, tuple, label_symbol = false, {}, nil
104 elseif symbol == [[\\]] then
105 if #tuple ~= 0 then
106 table.insert(rule[side], {label_symbol, tuple})
107 tuple = {}
108 end
109 striding = true
110 elseif symbol == rule_symbol and side == RIGHT then
111 if label_symbol and not (striding and #tuple == 0) then
112 table.insert(rule[side], {label_symbol, tuple})
113 tuple = {}
114 end
115 if #rule[LEFT] == 0 and #rule[RIGHT] == 0 then
116 break
117 else
118 table.insert(rules, rule)
119 striding, side, rule, label_symbol = false, LEFT, {{}, {}}, nil
120 end
121 elseif symbol == rule_symbol and side == LEFT then
122 -- a rule dilimiter
123 if label_symbol and not (striding and #tuple == 0) then
124 table.insert(rule[side], {label_symbol, tuple})
125 end
126 striding, tuple, side, label_symbol = false, {}, RIGHT, nil
127 elseif not label_symbol then
128 -- a label s symbol
129 label_symbol = symbol
130 elseif striding then
131 table.insert(rule[side], {label_symbol, {symbol}})
132 else
133 -- a symbol in a tuple
134 table.insert(tuple, symbol)
135 end
136 until not char
137 if #rule[LEFT] ~= 0 or #rule[RIGHT] ~= 0 then
138 table.insert(rules, rule)
139 end
140until not char
141
142local compile = require "compiler"
143
144print(compile(rules, {
145 mode = "main",
146 state_every_rewrite = false,
147 state_at_start = true,
148 state_at_end = true,
149}))