aboutsummaryrefslogtreecommitdiff
path: root/relabel.lua
diff options
context:
space:
mode:
authorSergio Queiroz <sqmedeiros@gmail.com>2016-11-10 16:26:11 -0300
committerSergio Queiroz <sqmedeiros@gmail.com>2016-11-10 16:26:11 -0300
commitfd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea (patch)
tree875ab38000e52376583bc13741b18701c6294f80 /relabel.lua
parentd84dd6b3659f94b09e67eb90a10e71eb05c5630e (diff)
downloadlpeglabel-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.lua457
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
4local tonumber, type, print, error, ipairs = tonumber, type, print, error, ipairs
5local pcall = pcall
6local setmetatable = setmetatable
7local unpack, tinsert, concat = table.unpack or unpack, table.insert, table.concat
8local rep = string.rep
9local 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'
14local mm = m
15
16-- pattern's metatable
17local mt = getmetatable(mm.P(0))
18
19
20
21-- No more global accesses after this point
22local version = _VERSION
23if version == "Lua 5.2" then _ENV = nil end
24
25
26local any = m.P(1)
27local dummy = mm.P(false)
28
29
30local 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
77local errmsgs = {}
78local labels = {}
79
80for i, err in ipairs(errinfo) do
81 errmsgs[i] = err[2]
82 labels[err[1]] = i
83end
84
85local syntaxerrs = {}
86
87local 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)
94end
95
96
97-- Pre-defined names
98local Predef = { nl = m.P"\n" }
99local tlabels = {}
100
101
102local mem
103local fmem
104local gmem
105
106
107local 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)
136end
137
138
139updatelocale()
140
141
142
143local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
144
145
146local 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
152end
153
154
155local 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
163end
164
165local 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
169end
170
171
172local S = (Predef.space + "--" * (any - Predef.nl)^0)^0
173
174local name = m.C(m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0)
175
176local arrow = S * "<-"
177
178-- a defined name only have meaning in a given environment
179local Def = name * m.Carg(1)
180
181local num = m.C(m.R"09"^1) * S / tonumber
182
183local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1")
184 + '"' * m.C((any - '"' - m.P"\n")^0) * expect('"', "MisTerm2")
185
186
187local 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
193end
194
195local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
196
197local item = defined + Range + m.C(any - m.P"\n")
198
199local 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
206local 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
213end
214
215local function firstdef (n, r) return adddef({n}, n, r) end
216
217
218local 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
223end
224
225local 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
237end
238
239-- error recovery
240local 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
250local ignore = m.Cmt(any, function (input, pos)
251 return syntaxerrs[#syntaxerrs].pos, dummy
252end)
253
254local 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
259end)
260
261
262local function labify (labelnames)
263 for i, l in ipairs(labelnames) do
264 labelnames[i] = labels[l]
265 end
266 return labelnames
267end
268
269local 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
279local labelset2 = labify {
280 "MisClose1", "MisClose2", "MisClose3", "MisClose4", "MisClose5"
281}
282
283local labelset3 = labify {
284 "ExpPatt1", "ExpLab1", "ExpLab2", "MisClose7"
285}
286
287local 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
350local pattern = S * m.Cg(m.Cc(false), "G") * expect(exp, "NoPatt") / mm.P
351 * S * expect(-any, "ExtraChars")
352
353local 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
364end
365
366local 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
371end
372
373local 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
396end
397
398local 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)
405end
406
407local 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
418end
419
420local 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)
430end
431
432local function setlabels (t)
433 tlabels = t
434end
435
436local 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
441end
442
443
444-- exported names
445local re = {
446 compile = compile,
447 match = match,
448 find = find,
449 gsub = gsub,
450 updatelocale = updatelocale,
451 setlabels = setlabels,
452 calcline = calcline
453}
454
455if version == "Lua 5.1" then _G.re = re end
456
457return re