february.lua
· 3.5 KiB · Lua
原始文件
Playground
local program = [[
= [What is] February =
[February is] a syntax front end for nova , designed around streaming tokens .
= = =
~ [Many Rules] Many Delimiter ~
[February can] let you switch between them on the fly .
~ ~ ~
*** [A note] ***
SAYS you don't need those [backets] .
BUT they might help with clarity
*** *** [What is] February
*** *** ***
]]
local stream = program:gmatch(".")
local char, rule, rule_symbol, label_symbol, depth, symbol, side
local tuple, rules, LEFT, RIGHT = {}, {}, 1, 2
repeat
rule_symbol, char = "", stream()
side, rule = LEFT, {{}, {}}
while char and char:match("[%s%.,]") do
char = stream()
end
if char == nil then
break
elseif char == "[" then
depth, char = 1, stream()
while char do
if char == "[" then depth = depth + 1 end
if char == "]" then depth = depth - 1 end
if depth == 0 then break end
rule_symbol, char = rule_symbol .. char, stream()
end
else
rule_symbol = "" while char and not char:match("%s") do
rule_symbol, char = rule_symbol .. char, stream() if char == "[" then
io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
end
end
end
repeat
char = stream()
while char and (char:match("[%s]") or not label_symbol and char:match("[%.,]")) do
char = stream()
end
if not char then
if label_symbol then
table.insert(rule[side], {label_symbol, tuple})
end
break
end
if char:match("[%.,]") then
symbol = char
elseif char == "[" then
symbol, depth, char = "", 1, stream() while char do
if char == "[" then depth = depth + 1 end
if char == "]" then depth = depth - 1 end
if depth == 0 then break end
symbol, char = symbol .. char, stream()
end
else
symbol = "" while char and not char:match("%s") do
symbol, char = symbol .. char, stream() if char == "[" then
io.stderr:write "Warning: symbol contains `[`. A space may be missing?"
end
end
end
if symbol == "," then
table.insert(rule[side], {label_symbol, tuple})
tuple = {}
elseif symbol == "." then
table.insert(rule[side], {label_symbol, tuple})
tuple, label_symbol = {}, nil
elseif symbol == rule_symbol and side == RIGHT then
if label_symbol then
table.insert(rule[side], {label_symbol, tuple})
tuple = {}
end
if #rule[LEFT] == 0 and #rule[RIGHT] == 0 then
break
else
table.insert(rules, rule)
side, rule, label_symbol = LEFT, {{}, {}}, nil
end
elseif symbol == rule_symbol and side == LEFT then
if label_symbol then
table.insert(rule[side], {label_symbol, tuple})
end
tuple, side, label_symbol = {}, RIGHT, nil
elseif not label_symbol then
label_symbol = symbol
else
table.insert(tuple, symbol)
end
until not char
if #rule[LEFT] ~= 0 or #rule[RIGHT] ~= 0 then
table.insert(rules, rule)
end
until not char
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 |