capitalex zrewidował ten Gist . Przejdź do rewizji
1 file changed, 230 insertions
nova-parser.lua(stworzono plik)
@@ -0,0 +1,230 @@ | |||
1 | + | local pprint = require "pprint" | |
2 | + | local None = {} | |
3 | + | local whitespace = { | |
4 | + | [' '] = true, | |
5 | + | ['\n'] = true, | |
6 | + | ['\r'] = true, | |
7 | + | ['\t'] = true, | |
8 | + | } | |
9 | + | local yield, wrap = coroutine.yield, coroutine.wrap | |
10 | + | ||
11 | + | local function gen(t) | |
12 | + | return wrap(function() | |
13 | + | for i, v in ipairs(t) do | |
14 | + | yield(i, v) | |
15 | + | end | |
16 | + | end) | |
17 | + | end | |
18 | + | local function iter(f) | |
19 | + | return function(arg) | |
20 | + | return wrap(function () f(arg) end) | |
21 | + | end | |
22 | + | end | |
23 | + | ||
24 | + | local function chars(string) | |
25 | + | local cs = {} | |
26 | + | for char in string:gmatch(".") do | |
27 | + | table.insert(cs, char) | |
28 | + | end | |
29 | + | return cs | |
30 | + | end | |
31 | + | ||
32 | + | local function copy(t) | |
33 | + | local t_copy = {} | |
34 | + | for k, v in pairs(t) do | |
35 | + | t_copy[k] = v | |
36 | + | end | |
37 | + | return t_copy | |
38 | + | end | |
39 | + | ||
40 | + | local function append(a, b) | |
41 | + | local appended = {} | |
42 | + | for _, v in ipairs(a) do | |
43 | + | table.insert(appended, v) | |
44 | + | end | |
45 | + | for _, v in ipairs(b) do | |
46 | + | table.insert(appended, v) | |
47 | + | end | |
48 | + | return appended | |
49 | + | end | |
50 | + | ||
51 | + | local function clear(t) | |
52 | + | for k, v in pairs(t) do | |
53 | + | t[k] = nil | |
54 | + | end | |
55 | + | end | |
56 | + | ||
57 | + | local function insert(t, what) | |
58 | + | table.insert(t, what) | |
59 | + | return t | |
60 | + | end | |
61 | + | ||
62 | + | local parser_container = iter(function(string) | |
63 | + | local left = {} | |
64 | + | local right = {} | |
65 | + | local target = left | |
66 | + | local characters = gen(insert(chars(string), None)) | |
67 | + | local delimiter = None | |
68 | + | ||
69 | + | for _, character in characters do | |
70 | + | if not whitespace[character] then | |
71 | + | delimiter = character | |
72 | + | break | |
73 | + | end | |
74 | + | ||
75 | + | end | |
76 | + | if delimiter == None then | |
77 | + | return None | |
78 | + | end | |
79 | + | ||
80 | + | for _, character in characters do | |
81 | + | if character == delimiter or character == None then | |
82 | + | if target == left then | |
83 | + | target = right | |
84 | + | else | |
85 | + | target = left | |
86 | + | yield(copy(left), copy(right)) | |
87 | + | clear(left) clear(right) | |
88 | + | end | |
89 | + | else | |
90 | + | table.insert(target, character) | |
91 | + | end | |
92 | + | end | |
93 | + | end) | |
94 | + | ||
95 | + | local parse_labels = iter(function(rules) | |
96 | + | local left = {} | |
97 | + | local right = {} | |
98 | + | local pair = {{}, {}} | |
99 | + | local target = left | |
100 | + | local delimiter = None | |
101 | + | for condition, result in rules do | |
102 | + | for _, side in ipairs({condition, result}) do | |
103 | + | local characters = gen(insert(side, None)) | |
104 | + | local state = "find delimiter" | |
105 | + | for _, character in characters do | |
106 | + | if character == None then | |
107 | + | local label = table.concat(pair[1]):match "^%s*(.-)%s*$" | |
108 | + | local pattern = table.concat(pair[2]):match "^%s*(.-)%s*$" | |
109 | + | if not (#label == 0 and #pattern == 0) then | |
110 | + | table.insert(target, {label, pattern}) | |
111 | + | end | |
112 | + | clear(pair[1]) clear(pair[2]) | |
113 | + | break | |
114 | + | elseif state == "find delimiter" then | |
115 | + | if not whitespace[character] then | |
116 | + | delimiter = character | |
117 | + | state = "parse label" | |
118 | + | end | |
119 | + | elseif state == "parse label" then | |
120 | + | if character == delimiter then | |
121 | + | state = "parse pattern" | |
122 | + | else | |
123 | + | table.insert(pair[1], character) | |
124 | + | end | |
125 | + | elseif state == "parse pattern" then | |
126 | + | if character == delimiter or character == None then | |
127 | + | state = "parse label" | |
128 | + | local label = table.concat(pair[1]):match "^%s*(.-)%s*$" | |
129 | + | local pattern = table.concat(pair[2]):match "^%s*(.-)%s*$" | |
130 | + | if not (#label == 0 and #pattern == 0) then | |
131 | + | table.insert(target, {label, pattern}) | |
132 | + | end | |
133 | + | clear(pair[1]) clear(pair[2]) | |
134 | + | else | |
135 | + | table.insert(pair[2], character) | |
136 | + | end | |
137 | + | end | |
138 | + | end | |
139 | + | if target == left then | |
140 | + | target = right | |
141 | + | else | |
142 | + | target = left | |
143 | + | end | |
144 | + | end | |
145 | + | yield(copy(left), copy(right)) | |
146 | + | clear(left) clear(right) | |
147 | + | end | |
148 | + | end) | |
149 | + | ||
150 | + | local parse_patterns = iter(function(rules) | |
151 | + | for conditions, results in rules do | |
152 | + | local left = {} | |
153 | + | local right = {} | |
154 | + | local preserves = {} | |
155 | + | for _, condition in ipairs(conditions) do | |
156 | + | local label, pattern = condition[1], condition[2] | |
157 | + | local preserve = false | |
158 | + | if pattern:match("%?$") then | |
159 | + | pattern = pattern:sub(1, -2) | |
160 | + | preserve = true | |
161 | + | end | |
162 | + | if pattern:match("^[\"'](.*)[\"']$") then | |
163 | + | for i, character in ipairs(chars(pattern:match("^[\"'](.*)[\"\']$"))) do | |
164 | + | table.insert(left, {label, {tostring(string.byte(character))}}) | |
165 | + | if preserves then | |
166 | + | table.insert(right, {label, {tostring(string.byte(character))}}) | |
167 | + | end | |
168 | + | end | |
169 | + | elseif pattern:match("^%((.*)%)$") then | |
170 | + | for token in pattern:match("^%((.*)%)$"):gmatch("%S+") do | |
171 | + | table.insert(left, {label, {token}}) | |
172 | + | if preserve then | |
173 | + | table.insert(right, {label, {token}}) | |
174 | + | end | |
175 | + | end | |
176 | + | elseif pattern:find("^%.") then | |
177 | + | -- TODO | |
178 | + | else | |
179 | + | local words = {} | |
180 | + | for word in pattern:gmatch("%S+") do | |
181 | + | table.insert(words, word) | |
182 | + | end | |
183 | + | table.insert(left, {label, words}) | |
184 | + | if preserve then | |
185 | + | table.insert(preserves, {label, words}) | |
186 | + | end | |
187 | + | end | |
188 | + | end | |
189 | + | ||
190 | + | for _, result in ipairs(results) do | |
191 | + | local label, pattern = result[1], result[2] | |
192 | + | ||
193 | + | if pattern:match("^[\"'](.*)[\"']$") then | |
194 | + | for i, character in ipairs(chars(pattern:match("^[\"'](.*)[\"\']$"))) do | |
195 | + | table.insert(right, {label, {tostring(string.byte(character))}}) | |
196 | + | end | |
197 | + | elseif pattern:match("^%((.*)%)$") then | |
198 | + | for token in pattern:match("^%((.*)%)$"):gmatch("%S+") do | |
199 | + | table.insert(right, {label, {token}}) | |
200 | + | end | |
201 | + | elseif pattern:find("^%.") then | |
202 | + | -- TODO | |
203 | + | else | |
204 | + | local words = {} | |
205 | + | for word in pattern:gmatch("%S+") do | |
206 | + | table.insert(words, word) | |
207 | + | end | |
208 | + | table.insert(right, {label, words}) | |
209 | + | end | |
210 | + | end | |
211 | + | ||
212 | + | yield(copy(left), append(right, preserves)) | |
213 | + | clear(left) clear(right) clear(preserves) | |
214 | + | end | |
215 | + | end) | |
216 | + | ||
217 | + | local file = io.open("main.nv", "r") | |
218 | + | for left, right in parse_patterns(parse_labels(parser_container(file:read("*a")))) do | |
219 | + | io.write("|") | |
220 | + | local left_pattern = {} | |
221 | + | for _, pattern in ipairs(left) do | |
222 | + | table.insert(left_pattern, ":" .. pattern[1] .. ": " .. table.concat(pattern[2], " ")) | |
223 | + | end | |
224 | + | io.write(table.concat(left_pattern, " ")) | |
225 | + | io.write("|\n") | |
226 | + | for _, pattern in ipairs(right) do | |
227 | + | print("", ":" .. pattern[1] .. ": " .. table.concat(pattern[2], " ")) | |
228 | + | end | |
229 | + | io.write("\n") | |
230 | + | end |
Nowsze
Starsze