diff options
author | Sergio Queiroz <sqmedeiros@gmail.com> | 2016-11-10 16:26:11 -0300 |
---|---|---|
committer | Sergio Queiroz <sqmedeiros@gmail.com> | 2016-11-10 16:26:11 -0300 |
commit | fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea (patch) | |
tree | 875ab38000e52376583bc13741b18701c6294f80 /relabel.lua | |
parent | d84dd6b3659f94b09e67eb90a10e71eb05c5630e (diff) | |
download | lpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.tar.gz lpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.tar.bz2 lpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.zip |
Removing labeled choice, updating testlabel, and disabling an optmization related to Throw
Diffstat (limited to 'relabel.lua')
-rw-r--r-- | relabel.lua | 457 |
1 files changed, 0 insertions, 457 deletions
diff --git a/relabel.lua b/relabel.lua deleted file mode 100644 index 0e7195e..0000000 --- a/relabel.lua +++ /dev/null | |||
@@ -1,457 +0,0 @@ | |||
1 | -- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ | ||
2 | |||
3 | -- imported functions and modules | ||
4 | local tonumber, type, print, error, ipairs = tonumber, type, print, error, ipairs | ||
5 | local pcall = pcall | ||
6 | local setmetatable = setmetatable | ||
7 | local unpack, tinsert, concat = table.unpack or unpack, table.insert, table.concat | ||
8 | local rep = string.rep | ||
9 | local m = require"lpeglabelrec" | ||
10 | |||
11 | -- 'm' will be used to parse expressions, and 'mm' will be used to | ||
12 | -- create expressions; that is, 're' runs on 'm', creating patterns | ||
13 | -- on 'mm' | ||
14 | local mm = m | ||
15 | |||
16 | -- pattern's metatable | ||
17 | local mt = getmetatable(mm.P(0)) | ||
18 | |||
19 | |||
20 | |||
21 | -- No more global accesses after this point | ||
22 | local version = _VERSION | ||
23 | if version == "Lua 5.2" then _ENV = nil end | ||
24 | |||
25 | |||
26 | local any = m.P(1) | ||
27 | local dummy = mm.P(false) | ||
28 | |||
29 | |||
30 | local errinfo = { | ||
31 | {"NoPatt", "no pattern found"}, | ||
32 | {"ExtraChars", "unexpected characters after the pattern"}, | ||
33 | |||
34 | {"ExpPatt1", "expected a pattern after '/' or the label(s)"}, | ||
35 | |||
36 | {"ExpPatt2", "expected a pattern after '&'"}, | ||
37 | {"ExpPatt3", "expected a pattern after '!'"}, | ||
38 | |||
39 | {"ExpPatt4", "expected a pattern after '('"}, | ||
40 | {"ExpPatt5", "expected a pattern after ':'"}, | ||
41 | {"ExpPatt6", "expected a pattern after '{~'"}, | ||
42 | {"ExpPatt7", "expected a pattern after '{|'"}, | ||
43 | |||
44 | {"ExpPatt8", "expected a pattern after '<-'"}, | ||
45 | |||
46 | {"ExpPattOrClose", "expected a pattern or closing '}' after '{'"}, | ||
47 | |||
48 | {"ExpNum", "expected a number after '^', '+' or '-' (no space)"}, | ||
49 | {"ExpCap", "expected a string, number, '{}' or name after '->'"}, | ||
50 | |||
51 | {"ExpName1", "expected the name of a rule after '=>'"}, | ||
52 | {"ExpName2", "expected the name of a rule after '=' (no space)"}, | ||
53 | {"ExpName3", "expected the name of a rule after '<' (no space)"}, | ||
54 | |||
55 | {"ExpLab1", "expected at least one label after '{'"}, | ||
56 | {"ExpLab2", "expected a label after the comma"}, | ||
57 | |||
58 | {"ExpNameOrLab", "expected a name or label after '%' (no space)"}, | ||
59 | |||
60 | {"ExpItem", "expected at least one item after '[' or '^'"}, | ||
61 | |||
62 | {"MisClose1", "missing closing ')'"}, | ||
63 | {"MisClose2", "missing closing ':}'"}, | ||
64 | {"MisClose3", "missing closing '~}'"}, | ||
65 | {"MisClose4", "missing closing '|}'"}, | ||
66 | {"MisClose5", "missing closing '}'"}, -- for the captures | ||
67 | |||
68 | {"MisClose6", "missing closing '>'"}, | ||
69 | {"MisClose7", "missing closing '}'"}, -- for the labels | ||
70 | |||
71 | {"MisClose8", "missing closing ']'"}, | ||
72 | |||
73 | {"MisTerm1", "missing terminating single quote"}, | ||
74 | {"MisTerm2", "missing terminating double quote"}, | ||
75 | } | ||
76 | |||
77 | local errmsgs = {} | ||
78 | local labels = {} | ||
79 | |||
80 | for i, err in ipairs(errinfo) do | ||
81 | errmsgs[i] = err[2] | ||
82 | labels[err[1]] = i | ||
83 | end | ||
84 | |||
85 | local syntaxerrs = {} | ||
86 | |||
87 | local function expect (pattern, labelname) | ||
88 | local label = labels[labelname] | ||
89 | local record = function (input, pos) | ||
90 | tinsert(syntaxerrs, { label = label, pos = pos }) | ||
91 | return true | ||
92 | end | ||
93 | return pattern + m.Cmt("", record) * m.T(label) | ||
94 | end | ||
95 | |||
96 | |||
97 | -- Pre-defined names | ||
98 | local Predef = { nl = m.P"\n" } | ||
99 | local tlabels = {} | ||
100 | |||
101 | |||
102 | local mem | ||
103 | local fmem | ||
104 | local gmem | ||
105 | |||
106 | |||
107 | local function updatelocale () | ||
108 | mm.locale(Predef) | ||
109 | Predef.a = Predef.alpha | ||
110 | Predef.c = Predef.cntrl | ||
111 | Predef.d = Predef.digit | ||
112 | Predef.g = Predef.graph | ||
113 | Predef.l = Predef.lower | ||
114 | Predef.p = Predef.punct | ||
115 | Predef.s = Predef.space | ||
116 | Predef.u = Predef.upper | ||
117 | Predef.w = Predef.alnum | ||
118 | Predef.x = Predef.xdigit | ||
119 | Predef.A = any - Predef.a | ||
120 | Predef.C = any - Predef.c | ||
121 | Predef.D = any - Predef.d | ||
122 | Predef.G = any - Predef.g | ||
123 | Predef.L = any - Predef.l | ||
124 | Predef.P = any - Predef.p | ||
125 | Predef.S = any - Predef.s | ||
126 | Predef.U = any - Predef.u | ||
127 | Predef.W = any - Predef.w | ||
128 | Predef.X = any - Predef.x | ||
129 | mem = {} -- restart memoization | ||
130 | fmem = {} | ||
131 | gmem = {} | ||
132 | local mt = {__mode = "v"} | ||
133 | setmetatable(mem, mt) | ||
134 | setmetatable(fmem, mt) | ||
135 | setmetatable(gmem, mt) | ||
136 | end | ||
137 | |||
138 | |||
139 | updatelocale() | ||
140 | |||
141 | |||
142 | |||
143 | local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) | ||
144 | |||
145 | |||
146 | local function getdef (id, defs) | ||
147 | local c = defs and defs[id] | ||
148 | if not c then | ||
149 | error("undefined name: " .. id) | ||
150 | end | ||
151 | return c | ||
152 | end | ||
153 | |||
154 | |||
155 | local function mult (p, n) | ||
156 | local np = mm.P(true) | ||
157 | while n >= 1 do | ||
158 | if n%2 >= 1 then np = np * p end | ||
159 | p = p * p | ||
160 | n = n/2 | ||
161 | end | ||
162 | return np | ||
163 | end | ||
164 | |||
165 | local function equalcap (s, i, c) | ||
166 | if type(c) ~= "string" then return nil end | ||
167 | local e = #c + i | ||
168 | if s:sub(i, e - 1) == c then return e else return nil end | ||
169 | end | ||
170 | |||
171 | |||
172 | local S = (Predef.space + "--" * (any - Predef.nl)^0)^0 | ||
173 | |||
174 | local name = m.C(m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0) | ||
175 | |||
176 | local arrow = S * "<-" | ||
177 | |||
178 | -- a defined name only have meaning in a given environment | ||
179 | local Def = name * m.Carg(1) | ||
180 | |||
181 | local num = m.C(m.R"09"^1) * S / tonumber | ||
182 | |||
183 | local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1") | ||
184 | + '"' * m.C((any - '"' - m.P"\n")^0) * expect('"', "MisTerm2") | ||
185 | |||
186 | |||
187 | local defined = "%" * Def / function (c,Defs) | ||
188 | local cat = Defs and Defs[c] or Predef[c] | ||
189 | if not cat then | ||
190 | error("name '" .. c .. "' undefined") | ||
191 | end | ||
192 | return cat | ||
193 | end | ||
194 | |||
195 | local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R | ||
196 | |||
197 | local item = defined + Range + m.C(any - m.P"\n") | ||
198 | |||
199 | local Class = | ||
200 | "[" | ||
201 | * (m.C(m.P"^"^-1)) -- optional complement symbol | ||
202 | * m.Cf(expect(item, "ExpItem") * (item - "]")^0, mt.__add) | ||
203 | / function (c, p) return c == "^" and any - p or p end | ||
204 | * expect("]", "MisClose8") | ||
205 | |||
206 | local function adddef (t, k, exp) | ||
207 | if t[k] then | ||
208 | error("'"..k.."' already defined as a rule") | ||
209 | else | ||
210 | t[k] = exp | ||
211 | end | ||
212 | return t | ||
213 | end | ||
214 | |||
215 | local function firstdef (n, r) return adddef({n}, n, r) end | ||
216 | |||
217 | |||
218 | local function NT (n, b) | ||
219 | if not b then | ||
220 | error("rule '"..n.."' used outside a grammar") | ||
221 | else return mm.V(n) | ||
222 | end | ||
223 | end | ||
224 | |||
225 | local function labchoice (...) | ||
226 | local t = { ... } | ||
227 | local n = #t | ||
228 | local p = t[1] | ||
229 | local i = 2 | ||
230 | while i + 1 <= n do | ||
231 | -- t[i] == nil when there are no labels | ||
232 | p = t[i] and mm.Lc(p, t[i+1], unpack(t[i])) or mt.__add(p, t[i+1]) | ||
233 | i = i + 2 | ||
234 | end | ||
235 | |||
236 | return p | ||
237 | end | ||
238 | |||
239 | -- error recovery | ||
240 | local skip = m.P { "Skip", | ||
241 | Skip = (-m.P"/" * -m.P(name * arrow) * m.V"Ignored")^0 * m.Cc(dummy); | ||
242 | Ignored = m.V"Group" + any; | ||
243 | Group = "(" * (-m.P")" * m.V"Ignored")^0 * ")" | ||
244 | + "{" * (-m.P"}" * m.V"Ignored")^0 * "}" | ||
245 | + "[" * (-m.P"]" * m.V"Ignored")^0 * "]" | ||
246 | + "'" * (-m.P"'" * m.V"Ignored")^0 * "'" | ||
247 | + '"' * (-m.P'"' * m.V"Ignored")^0 * '"'; | ||
248 | } | ||
249 | |||
250 | local ignore = m.Cmt(any, function (input, pos) | ||
251 | return syntaxerrs[#syntaxerrs].pos, dummy | ||
252 | end) | ||
253 | |||
254 | local pointAtStart = m.Cmt(any, function (input, pos) | ||
255 | -- like ignore but makes the last syntax error point at the start | ||
256 | local ret = syntaxerrs[#syntaxerrs].pos | ||
257 | syntaxerrs[#syntaxerrs].pos = pos-1 | ||
258 | return ret, dummy | ||
259 | end) | ||
260 | |||
261 | |||
262 | local function labify (labelnames) | ||
263 | for i, l in ipairs(labelnames) do | ||
264 | labelnames[i] = labels[l] | ||
265 | end | ||
266 | return labelnames | ||
267 | end | ||
268 | |||
269 | local labelset1 = labify { | ||
270 | "ExpPatt2", "ExpPatt3", | ||
271 | "ExpPatt4", "ExpPatt5", "ExpPatt6", "ExpPatt7", | ||
272 | "ExpPatt8", "ExpPattOrClose", | ||
273 | "ExpNum", "ExpCap", | ||
274 | "ExpName1", "ExpName2", "ExpName3", | ||
275 | "ExpNameOrLab", "ExpItem", | ||
276 | "MisClose6", "MisClose7" | ||
277 | } | ||
278 | |||
279 | local labelset2 = labify { | ||
280 | "MisClose1", "MisClose2", "MisClose3", "MisClose4", "MisClose5" | ||
281 | } | ||
282 | |||
283 | local labelset3 = labify { | ||
284 | "ExpPatt1", "ExpLab1", "ExpLab2", "MisClose7" | ||
285 | } | ||
286 | |||
287 | local exp = m.P{ "Exp", | ||
288 | Exp = S * ( m.V"Grammar" | ||
289 | + (m.V"RecovSeq" * (S * "/" * m.Lc((m.Ct(m.V"Labels") + m.Cc(nil)) | ||
290 | * expect(S * m.V"RecovSeq", | ||
291 | "ExpPatt1"), | ||
292 | m.Cc(nil) * skip, | ||
293 | unpack(labelset3)) | ||
294 | )^0 | ||
295 | ) / labchoice); | ||
296 | Labels = m.P"{" * expect(S * m.V"Label", "ExpLab1") | ||
297 | * (S * "," * expect(S * m.V"Label", "ExpLab2"))^0 | ||
298 | * expect(S * "}", "MisClose7"); | ||
299 | RecovSeq = m.Lc(m.V"Seq", skip, unpack(labelset1)); | ||
300 | Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix" * (S * m.V"Prefix")^0, mt.__mul); | ||
301 | Prefix = "&" * expect(S * m.V"Prefix", "ExpPatt2") / mt.__len | ||
302 | + "!" * expect(S * m.V"Prefix", "ExpPatt3") / mt.__unm | ||
303 | + m.V"Suffix"; | ||
304 | Suffix = m.Cf(m.V"RecovPrimary" * | ||
305 | ( S * ( m.P"+" * m.Cc(1, mt.__pow) | ||
306 | + m.P"*" * m.Cc(0, mt.__pow) | ||
307 | + m.P"?" * m.Cc(-1, mt.__pow) | ||
308 | + "^" * expect( m.Cg(num * m.Cc(mult)) | ||
309 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) | ||
310 | ), | ||
311 | "ExpNum") | ||
312 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) | ||
313 | + m.P"{}" * m.Cc(nil, m.Ct) | ||
314 | + m.Cg(Def / getdef * m.Cc(mt.__div)) | ||
315 | ), | ||
316 | "ExpCap") | ||
317 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), | ||
318 | "ExpName1") | ||
319 | ) | ||
320 | )^0, function (a,b,f) return f(a,b) end ); | ||
321 | RecovPrimary = m.Lc(m.V"Primary", ignore, unpack(labelset2)); | ||
322 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") | ||
323 | + m.Lc(String / mm.P, pointAtStart, | ||
324 | labels["MisTerm1"], labels["MisTerm2"]) | ||
325 | + m.Lc(Class, pointAtStart, labels["MisClose8"]) | ||
326 | + defined | ||
327 | + "%" * expect(m.V"Labels", "ExpNameOrLab") / mm.T | ||
328 | + "{:" * (name * ":" + m.Cc(nil)) * expect(m.V"Exp", "ExpPatt5") | ||
329 | * expect(S * ":}", "MisClose2") | ||
330 | / function (n, p) return mm.Cg(p, n) end | ||
331 | + "=" * expect(name, "ExpName2") | ||
332 | / function (n) return mm.Cmt(mm.Cb(n), equalcap) end | ||
333 | + m.P"{}" / mm.Cp | ||
334 | + "{~" * expect(m.V"Exp", "ExpPatt6") | ||
335 | * expect(S * "~}", "MisClose3") / mm.Cs | ||
336 | + "{|" * expect(m.V"Exp", "ExpPatt7") | ||
337 | * expect(S * "|}", "MisClose4") / mm.Ct | ||
338 | + "{" * expect(m.V"Exp", "ExpPattOrClose") | ||
339 | * expect(S * "}", "MisClose5") / mm.C | ||
340 | + m.P"." * m.Cc(any) | ||
341 | + (name * -arrow + "<" * expect(name, "ExpName3") | ||
342 | * expect(">", "MisClose6")) * m.Cb("G") / NT; | ||
343 | Label = num + name / function (f) return tlabels[f] end; | ||
344 | Definition = name * arrow * expect(m.V"Exp", "ExpPatt8"); | ||
345 | Grammar = m.Cg(m.Cc(true), "G") | ||
346 | * m.Cf(m.V"Definition" / firstdef * (S * m.Cg(m.V"Definition"))^0, | ||
347 | adddef) / mm.P; | ||
348 | } | ||
349 | |||
350 | local pattern = S * m.Cg(m.Cc(false), "G") * expect(exp, "NoPatt") / mm.P | ||
351 | * S * expect(-any, "ExtraChars") | ||
352 | |||
353 | local function lineno (s, i) | ||
354 | if i == 1 then return 1, 1 end | ||
355 | local adjustment = 0 | ||
356 | -- report the current line if at end of line, not the next | ||
357 | if s:sub(i,i) == '\n' then | ||
358 | i = i-1 | ||
359 | adjustment = 1 | ||
360 | end | ||
361 | local rest, num = s:sub(1,i):gsub("[^\n]*\n", "") | ||
362 | local r = #rest | ||
363 | return 1 + num, (r ~= 0 and r or 1) + adjustment | ||
364 | end | ||
365 | |||
366 | local function splitlines(str) | ||
367 | local t = {} | ||
368 | local function helper(line) tinsert(t, line) return "" end | ||
369 | helper((str:gsub("(.-)\r?\n", helper))) | ||
370 | return t | ||
371 | end | ||
372 | |||
373 | local function compile (p, defs) | ||
374 | if mm.type(p) == "pattern" then return p end -- already compiled | ||
375 | p = p .. " " -- for better reporting of column numbers in errors when at EOF | ||
376 | local ok, cp, label, suffix = pcall(function() return pattern:match(p, 1, defs) end) | ||
377 | if not ok and #syntaxerrs == 0 then | ||
378 | if type(cp) == "string" then | ||
379 | cp = cp:gsub("^[^:]+:[^:]+: ", "") | ||
380 | end | ||
381 | error(cp, 3) | ||
382 | end | ||
383 | if #syntaxerrs > 0 then | ||
384 | local lines = splitlines(p) | ||
385 | local errors = {} | ||
386 | for i, err in ipairs(syntaxerrs) do | ||
387 | local line, col = lineno(p, err.pos) | ||
388 | tinsert(errors, "L" .. line .. ":C" .. col .. ": " .. errmsgs[err.label]) | ||
389 | tinsert(errors, lines[line]) | ||
390 | tinsert(errors, rep(" ", col-1) .. "^") | ||
391 | end | ||
392 | syntaxerrs = {} | ||
393 | error("syntax error(s) in pattern\n" .. concat(errors, "\n"), 3) | ||
394 | end | ||
395 | return cp | ||
396 | end | ||
397 | |||
398 | local function match (s, p, i) | ||
399 | local cp = mem[p] | ||
400 | if not cp then | ||
401 | cp = compile(p) | ||
402 | mem[p] = cp | ||
403 | end | ||
404 | return cp:match(s, i or 1) | ||
405 | end | ||
406 | |||
407 | local function find (s, p, i) | ||
408 | local cp = fmem[p] | ||
409 | if not cp then | ||
410 | cp = compile(p) / 0 | ||
411 | cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) } | ||
412 | fmem[p] = cp | ||
413 | end | ||
414 | local i, e = cp:match(s, i or 1) | ||
415 | if i then return i, e - 1 | ||
416 | else return i | ||
417 | end | ||
418 | end | ||
419 | |||
420 | local function gsub (s, p, rep) | ||
421 | local g = gmem[p] or {} -- ensure gmem[p] is not collected while here | ||
422 | gmem[p] = g | ||
423 | local cp = g[rep] | ||
424 | if not cp then | ||
425 | cp = compile(p) | ||
426 | cp = mm.Cs((cp / rep + 1)^0) | ||
427 | g[rep] = cp | ||
428 | end | ||
429 | return cp:match(s) | ||
430 | end | ||
431 | |||
432 | local function setlabels (t) | ||
433 | tlabels = t | ||
434 | end | ||
435 | |||
436 | local function calcline (s, i) | ||
437 | if i == 1 then return 1, 1 end | ||
438 | local rest, line = s:sub(1,i):gsub("[^\n]*\n", "") | ||
439 | local col = #rest | ||
440 | return 1 + line, col ~= 0 and col or 1 | ||
441 | end | ||
442 | |||
443 | |||
444 | -- exported names | ||
445 | local re = { | ||
446 | compile = compile, | ||
447 | match = match, | ||
448 | find = find, | ||
449 | gsub = gsub, | ||
450 | updatelocale = updatelocale, | ||
451 | setlabels = setlabels, | ||
452 | calcline = calcline | ||
453 | } | ||
454 | |||
455 | if version == "Lua 5.1" then _G.re = re end | ||
456 | |||
457 | return re | ||