aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUndecidable Robot <undecidabot@gmail.com>2016-05-08 16:14:55 +0800
committerUndecidable Robot <undecidabot@gmail.com>2016-05-12 20:43:43 +0800
commit488fae08f969a09a6cff60470e119cf7010cf834 (patch)
tree101cd6ffbabc970fb9b884fcb712a70f9d7f8918
parent76170bacefad40b79a1f8a93294d2c96711a3b1e (diff)
downloadlpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.tar.gz
lpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.tar.bz2
lpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.zip
Adding a basic error recovery mechanism
-rw-r--r--relabel.lua71
-rw-r--r--testerrors.lua3
2 files changed, 45 insertions, 29 deletions
diff --git a/relabel.lua b/relabel.lua
index 16c5473..89797ad 100644
--- a/relabel.lua
+++ b/relabel.lua
@@ -1,9 +1,10 @@
1-- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ 1-- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $
2 2
3-- imported functions and modules 3-- imported functions and modules
4local tonumber, type, print, error = tonumber, type, print, error 4local tonumber, type, print, error, ipairs = tonumber, type, print, error, ipairs
5local setmetatable = setmetatable 5local setmetatable = setmetatable
6local unpack = table.unpack or unpack 6local unpack = table.unpack or unpack
7local tinsert = table.insert
7local m = require"lpeglabel" 8local m = require"lpeglabel"
8 9
9-- 'm' will be used to parse expressions, and 'mm' will be used to 10-- 'm' will be used to parse expressions, and 'mm' will be used to
@@ -23,6 +24,15 @@ if version == "Lua 5.2" then _ENV = nil end
23 24
24local any = m.P(1) 25local any = m.P(1)
25 26
27local errors
28
29local function throw(label)
30 local record = function (input, pos)
31 tinsert(errors, {label, pos})
32 return true
33 end
34 return m.Cmt("", record) * m.T(label)
35end
26 36
27-- Pre-defined names 37-- Pre-defined names
28local Predef = { nl = m.P"\n" } 38local Predef = { nl = m.P"\n" }
@@ -120,8 +130,8 @@ local Def = name * m.Carg(1)
120 130
121local num = m.C(m.R"09"^1) * S / tonumber 131local num = m.C(m.R"09"^1) * S / tonumber
122 132
123local String = "'" * m.C((any - "'")^0) * ("'" + m.T(31)) + 133local String = "'" * m.C((any - "'")^0) * ("'" + throw(31)) +
124 '"' * m.C((any - '"')^0) * ('"' + m.T(30)) 134 '"' * m.C((any - '"')^0) * ('"' + throw(30))
125 135
126 136
127local defined = "%" * Def / function (c,Defs) 137local defined = "%" * Def / function (c,Defs)
@@ -137,9 +147,9 @@ local item = defined + Range + m.C(any)
137local Class = 147local Class =
138 "[" 148 "["
139 * (m.C(m.P"^"^-1)) -- optional complement symbol 149 * (m.C(m.P"^"^-1)) -- optional complement symbol
140 * m.Cf((item + m.T(24)) * (item - "]")^0, mt.__add) / 150 * m.Cf((item + throw(24)) * (item - "]")^0, mt.__add) /
141 function (c, p) return c == "^" and any - p or p end 151 function (c, p) return c == "^" and any - p or p end
142 * ("]" + m.T(25)) 152 * ("]" + throw(25))
143 153
144local function adddef (t, k, exp) 154local function adddef (t, k, exp)
145 if t[k] then 155 if t[k] then
@@ -176,12 +186,12 @@ end
176 186
177local exp = m.P{ "Exp", 187local exp = m.P{ "Exp",
178 Exp = S * ( m.V"Grammar" 188 Exp = S * ( m.V"Grammar"
179 + (m.V"Seq") * ("/" * m.V"Labels" * S * (m.V"Seq" + m.T(3)))^1 / labchoice 189 + (m.V"Seq") * ("/" * m.V"Labels" * S * (m.V"Seq" + throw(3)))^1 / labchoice
180 + m.Cf(m.V"Seq" * ("/" * S * (m.V"Seq" + m.T(4)))^0, mt.__add) ); 190 + m.Cf(m.V"Seq" * ("/" * S * m.Lc(m.V"Seq" + throw(4), (-m.P"/" * any)^0, 4, 5, 6, 7, 8, 9, 10))^0, mt.__add) );
181 Labels = m.Ct(m.P"{" * S * (m.V"Label" + m.T(27)) * (S * "," * S * (m.V"Label" + m.T(28)))^0 * S * ("}" + m.T(29))); 191 Labels = m.Ct(m.P"{" * S * (m.V"Label" + throw(27)) * (S * "," * S * (m.V"Label" + throw(28)))^0 * S * ("}" + throw(29)));
182 Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^1 , mt.__mul); 192 Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^1 , mt.__mul);
183 Prefix = "&" * S * (m.V"Prefix" + m.T(5)) / mt.__len 193 Prefix = "&" * S * (m.V"Prefix" + throw(5)) / mt.__len
184 + "!" * S * (m.V"Prefix" + m.T(6)) / mt.__unm 194 + "!" * S * (m.V"Prefix" + throw(6)) / mt.__unm
185 + m.V"Suffix"; 195 + m.V"Suffix";
186 Suffix = m.Cf(m.V"Primary" * S * 196 Suffix = m.Cf(m.V"Primary" * S *
187 ( ( m.P"+" * m.Cc(1, mt.__pow) 197 ( ( m.P"+" * m.Cc(1, mt.__pow)
@@ -189,39 +199,39 @@ local exp = m.P{ "Exp",
189 + m.P"?" * m.Cc(-1, mt.__pow) 199 + m.P"?" * m.Cc(-1, mt.__pow)
190 + "^" * ( m.Cg(num * m.Cc(mult)) 200 + "^" * ( m.Cg(num * m.Cc(mult))
191 + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow)) 201 + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow))
192 + m.T(7) 202 + throw(7)
193 ) 203 )
194 + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div)) 204 + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div))
195 + m.P"{" * (m.P"}" + m.T(8)) * m.Cc(nil, m.Ct) 205 + m.P"{" * (m.P"}" + throw(8)) * m.Cc(nil, m.Ct)
196 + m.Cg(Def / getdef * m.Cc(mt.__div)) 206 + m.Cg(Def / getdef * m.Cc(mt.__div))
197 + m.T(9) 207 + throw(9)
198 ) 208 )
199 + "=>" * S * (m.Cg(Def / getdef * m.Cc(m.Cmt)) + m.T(10)) 209 + "=>" * S * (m.Cg(Def / getdef * m.Cc(m.Cmt)) + throw(10))
200 ) * S 210 ) * S
201 )^0, function (a,b,f) return f(a,b) end ); 211 )^0, function (a,b,f) return f(a,b) end );
202 Primary = "(" * (m.V"Exp" + m.T(11)) * (")" + m.T(12)) 212 Primary = "(" * (m.V"Exp" + throw(11)) * (")" + throw(12))
203 + String / mm.P 213 + String / mm.P
204 + Class 214 + Class
205 + defined 215 + defined
206 + "%{" * S * (m.V"Label" + m.T(27)) * (S * "," * S * (m.V"Label" + m.T(28)))^0 * S * ("}" + m.T(29)) / mm.T 216 + "%{" * S * (m.V"Label" + throw(27)) * (S * "," * S * (m.V"Label" + throw(28)))^0 * S * ("}" + throw(29)) / mm.T
207 + ("%" * m.T(13)) 217 + ("%" * throw(13))
208 + "{:" * (name * ":" + m.Cc(nil)) * (m.V"Exp" + m.T(14)) * (":}" + m.T(15)) / 218 + "{:" * (name * ":" + m.Cc(nil)) * (m.V"Exp" + throw(14)) * (":}" + throw(15)) /
209 function (n, p) return mm.Cg(p, n) end 219 function (n, p) return mm.Cg(p, n) end
210 + "=" * (name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end + m.T(16)) 220 + "=" * (name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end + throw(16))
211 + m.P"{}" / mm.Cp 221 + m.P"{}" / mm.Cp
212 + "{~" * (m.V"Exp" + m.T(17)) * ("~}" + m.T(18)) / mm.Cs 222 + "{~" * (m.V"Exp" + throw(17)) * ("~}" + throw(18)) / mm.Cs
213 + "{|" * (m.V"Exp" + m.T(32)) * ("|}" + m.T(33)) / mm.Ct 223 + "{|" * (m.V"Exp" + throw(32)) * ("|}" + throw(33)) / mm.Ct
214 + "{" * (m.V"Exp" + m.T(19)) * ("}" + m.T(20)) / mm.C 224 + "{" * (m.V"Exp" + throw(19)) * ("}" + throw(20)) / mm.C
215 + m.P"." * m.Cc(any) 225 + m.P"." * m.Cc(any)
216 + (name * -arrow + "<" * (name + m.T(21)) * (">" + m.T(22))) * m.Cb("G") / NT; 226 + (name * -arrow + "<" * (name + throw(21)) * (">" + throw(22))) * m.Cb("G") / NT;
217 Label = num + name / function (f) return tlabels[f] end; 227 Label = num + name / function (f) return tlabels[f] end;
218 Definition = name * arrow * (m.V"Exp" + m.T(23)); 228 Definition = name * arrow * (m.V"Exp" + throw(23));
219 Grammar = m.Cg(m.Cc(true), "G") * 229 Grammar = m.Cg(m.Cc(true), "G") *
220 m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0, 230 m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0,
221 adddef) / mm.P 231 adddef) / mm.P
222} 232}
223 233
224local pattern = S * m.Cg(m.Cc(false), "G") * (exp + m.T(1)) / mm.P * (-any + m.T(2)) 234local pattern = S * m.Cg(m.Cc(false), "G") * (exp + throw(1)) / mm.P * (-any + throw(2))
225 235
226local function lineno (s, i) 236local function lineno (s, i)
227 if i == 1 then return 1, 1 end 237 if i == 1 then return 1, 1 end
@@ -268,10 +278,15 @@ local errorMessages = {
268 278
269local function compile (p, defs) 279local function compile (p, defs)
270 if mm.type(p) == "pattern" then return p end -- already compiled 280 if mm.type(p) == "pattern" then return p end -- already compiled
281 errors = {}
271 local cp, label, suffix = pattern:match(p, 1, defs) 282 local cp, label, suffix = pattern:match(p, 1, defs)
272 if not cp then 283 if #errors > 0 then
273 local line, col = lineno(p, p:len() - suffix:len()) 284 local errmsg = ""
274 error("Line" .. line .. ", Col " .. col .. ": " .. errorMessages[label], 3) 285 for i, err in ipairs(errors) do
286 local line, col = lineno(p, err[2])
287 errmsg = errmsg .. "Line" .. line .. ", Col " .. col .. ": " .. errorMessages[err[1]] .. "\n"
288 end
289 error(errmsg, 3)
275 end 290 end
276 return cp 291 return cp
277end 292end
diff --git a/testerrors.lua b/testerrors.lua
index 07bbaef..7ffcd04 100644
--- a/testerrors.lua
+++ b/testerrors.lua
@@ -99,9 +99,10 @@ local patterns = {
99 [[{||}]], 99 [[{||}]],
100 [[{|@|}]], 100 [[{|@|}]],
101 [['p' {| 'q' / 'r' }]], 101 [['p' {| 'q' / 'r' }]],
102 -- 71-72 102 -- 71-73
103 [['a'/{1}'b'/'c']], 103 [['a'/{1}'b'/'c']],
104 [[x <- {:x:}]], 104 [[x <- {:x:}]],
105 [[&'p'/&/!/'p'^'q']]
105} 106}
106 107
107for i, patt in ipairs(patterns) do 108for i, patt in ipairs(patterns) do