最后活跃于 1755999453

capitalex's Avatar capitalex 修订了这个 Gist 1755999453. 转到此修订

1 file changed, 71 insertions, 23 deletions

february.lua

@@ -1,31 +1,47 @@
1 + local pprint = require "pprint"
1 2 local program = [[
2 - = [What is] February =
3 - [February is] a syntax front end for nova , designed around streaming tokens .
4 - = = =
3 + = = @rpn \\ [3] [4] dup * swap dup * swap + sqrt print
5 4
6 - ~ [Many Rules] Many Delimiter ~
7 - [February can] let you switch between them on the fly .
8 - ~ ~ ~
5 + = @rpn dup . @rpn.data $ =
6 + @rpn.data \\ $ $
9 7
10 - *** [A note] ***
11 - SAYS you don't need those [backets] .
12 - BUT they might help with clarity
13 -
14 - *** *** [What is] February
15 - *** *** ***
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
16 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)
17 31 local stream = program:gmatch(".")
18 - local char, rule, rule_symbol, label_symbol, depth, symbol, side
32 + local char, rule, rule_symbol, label_symbol, depth, symbol, side, striding
19 33 local tuple, rules, LEFT, RIGHT = {}, {}, 1, 2
20 34 repeat
21 35 rule_symbol, char = "", stream()
22 36 side, rule = LEFT, {{}, {}}
23 37 while char and char:match("[%s%.,]") do
38 + -- skip all characters that can't be bound
24 39 char = stream()
25 40 end
26 41 if char == nil then
27 42 break
28 43 elseif char == "[" then
44 + -- rule delimiter is multibyte
29 45 depth, char = 1, stream()
30 46 while char do
31 47 if char == "[" then depth = depth + 1 end
@@ -34,26 +50,31 @@ repeat
34 50 rule_symbol, char = rule_symbol .. char, stream()
35 51 end
36 52 else
53 + -- rule delimiter is a single character
37 54 rule_symbol = "" while char and not char:match("%s") do
38 55 rule_symbol, char = rule_symbol .. char, stream() if char == "[" then
39 56 io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
40 57 end
41 58 end
42 59 end
43 - repeat
60 + repeat -- consume rules from this set
44 61 char = stream()
45 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
46 64 char = stream()
47 65 end
48 66 if not char then
49 - if label_symbol then
67 + if label_symbol and not striding then
50 68 table.insert(rule[side], {label_symbol, tuple})
51 69 end
52 70 break
53 71 end
72 + -- read a symbol from the stream
54 73 if char:match("[%.,]") then
74 + -- we've hit a tuple related delimiter
55 75 symbol = char
56 76 elseif char == "[" then
77 + -- parse a boxed symbol
57 78 symbol, depth, char = "", 1, stream() while char do
58 79 if char == "[" then depth = depth + 1 end
59 80 if char == "]" then depth = depth - 1 end
@@ -61,20 +82,33 @@ repeat
61 82 symbol, char = symbol .. char, stream()
62 83 end
63 84 else
85 + -- parse a symbol seperated by spaces
86 + -- this segment warns if a symbol contains `[`
64 87 symbol = "" while char and not char:match("%s") do
65 88 symbol, char = symbol .. char, stream() if char == "[" then
66 89 io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
67 90 end
68 91 end
69 92 end
93 + -- process that symbol
70 94 if symbol == "," then
95 + -- push a tuple
71 96 table.insert(rule[side], {label_symbol, tuple})
72 - tuple = {}
97 + striding, tuple = false, {}
73 98 elseif symbol == "." then
74 - table.insert(rule[side], {label_symbol, tuple})
75 - tuple, label_symbol = {}, nil
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
76 110 elseif symbol == rule_symbol and side == RIGHT then
77 - if label_symbol then
111 + if label_symbol and not (striding and #tuple == 0) then
78 112 table.insert(rule[side], {label_symbol, tuple})
79 113 tuple = {}
80 114 end
@@ -82,20 +116,34 @@ repeat
82 116 break
83 117 else
84 118 table.insert(rules, rule)
85 - side, rule, label_symbol = LEFT, {{}, {}}, nil
119 + striding, side, rule, label_symbol = false, LEFT, {{}, {}}, nil
86 120 end
87 121 elseif symbol == rule_symbol and side == LEFT then
88 - if label_symbol then
122 + -- a rule dilimiter
123 + if label_symbol and not (striding and #tuple == 0) then
89 124 table.insert(rule[side], {label_symbol, tuple})
90 125 end
91 - tuple, side, label_symbol = {}, RIGHT, nil
126 + striding, tuple, side, label_symbol = false, {}, RIGHT, nil
92 127 elseif not label_symbol then
128 + -- a label s symbol
93 129 label_symbol = symbol
130 + elseif striding then
131 + table.insert(rule[side], {label_symbol, {symbol}})
94 132 else
133 + -- a symbol in a tuple
95 134 table.insert(tuple, symbol)
96 135 end
97 136 until not char
98 137 if #rule[LEFT] ~= 0 or #rule[RIGHT] ~= 0 then
99 138 table.insert(rules, rule)
100 139 end
101 - until not char
140 + until not char
141 +
142 + local compile = require "compiler"
143 +
144 + print(compile(rules, {
145 + mode = "main",
146 + state_every_rewrite = false,
147 + state_at_start = true,
148 + state_at_end = true,
149 + }))

capitalex's Avatar capitalex 修订了这个 Gist 1755914597. 转到此修订

1 file changed, 101 insertions

february.lua(文件已创建)

@@ -0,0 +1,101 @@
1 + local program = [[
2 + = [What is] February =
3 + [February is] a syntax front end for nova , designed around streaming tokens .
4 + = = =
5 +
6 + ~ [Many Rules] Many Delimiter ~
7 + [February can] let you switch between them on the fly .
8 + ~ ~ ~
9 +
10 + *** [A note] ***
11 + SAYS you don't need those [backets] .
12 + BUT they might help with clarity
13 +
14 + *** *** [What is] February
15 + *** *** ***
16 + ]]
17 + local stream = program:gmatch(".")
18 + local char, rule, rule_symbol, label_symbol, depth, symbol, side
19 + local tuple, rules, LEFT, RIGHT = {}, {}, 1, 2
20 + repeat
21 + rule_symbol, char = "", stream()
22 + side, rule = LEFT, {{}, {}}
23 + while char and char:match("[%s%.,]") do
24 + char = stream()
25 + end
26 + if char == nil then
27 + break
28 + elseif char == "[" then
29 + depth, char = 1, stream()
30 + while char do
31 + if char == "[" then depth = depth + 1 end
32 + if char == "]" then depth = depth - 1 end
33 + if depth == 0 then break end
34 + rule_symbol, char = rule_symbol .. char, stream()
35 + end
36 + else
37 + rule_symbol = "" while char and not char:match("%s") do
38 + rule_symbol, char = rule_symbol .. char, stream() if char == "[" then
39 + io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
40 + end
41 + end
42 + end
43 + repeat
44 + char = stream()
45 + while char and (char:match("[%s]") or not label_symbol and char:match("[%.,]")) do
46 + char = stream()
47 + end
48 + if not char then
49 + if label_symbol then
50 + table.insert(rule[side], {label_symbol, tuple})
51 + end
52 + break
53 + end
54 + if char:match("[%.,]") then
55 + symbol = char
56 + elseif char == "[" then
57 + symbol, depth, char = "", 1, stream() while char do
58 + if char == "[" then depth = depth + 1 end
59 + if char == "]" then depth = depth - 1 end
60 + if depth == 0 then break end
61 + symbol, char = symbol .. char, stream()
62 + end
63 + else
64 + symbol = "" while char and not char:match("%s") do
65 + symbol, char = symbol .. char, stream() if char == "[" then
66 + io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
67 + end
68 + end
69 + end
70 + if symbol == "," then
71 + table.insert(rule[side], {label_symbol, tuple})
72 + tuple = {}
73 + elseif symbol == "." then
74 + table.insert(rule[side], {label_symbol, tuple})
75 + tuple, label_symbol = {}, nil
76 + elseif symbol == rule_symbol and side == RIGHT then
77 + if label_symbol then
78 + table.insert(rule[side], {label_symbol, tuple})
79 + tuple = {}
80 + end
81 + if #rule[LEFT] == 0 and #rule[RIGHT] == 0 then
82 + break
83 + else
84 + table.insert(rules, rule)
85 + side, rule, label_symbol = LEFT, {{}, {}}, nil
86 + end
87 + elseif symbol == rule_symbol and side == LEFT then
88 + if label_symbol then
89 + table.insert(rule[side], {label_symbol, tuple})
90 + end
91 + tuple, side, label_symbol = {}, RIGHT, nil
92 + elseif not label_symbol then
93 + label_symbol = symbol
94 + else
95 + table.insert(tuple, symbol)
96 + end
97 + until not char
98 + if #rule[LEFT] ~= 0 or #rule[RIGHT] ~= 0 then
99 + table.insert(rules, rule)
100 + end
101 + until not char
上一页 下一页