diff options
author | Undecidable Robot <undecidabot@gmail.com> | 2016-05-08 16:14:55 +0800 |
---|---|---|
committer | Undecidable Robot <undecidabot@gmail.com> | 2016-05-12 20:43:43 +0800 |
commit | 488fae08f969a09a6cff60470e119cf7010cf834 (patch) | |
tree | 101cd6ffbabc970fb9b884fcb712a70f9d7f8918 | |
parent | 76170bacefad40b79a1f8a93294d2c96711a3b1e (diff) | |
download | lpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.tar.gz lpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.tar.bz2 lpeglabel-488fae08f969a09a6cff60470e119cf7010cf834.zip |
Adding a basic error recovery mechanism
-rw-r--r-- | relabel.lua | 71 | ||||
-rw-r--r-- | testerrors.lua | 3 |
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 |
4 | local tonumber, type, print, error = tonumber, type, print, error | 4 | local tonumber, type, print, error, ipairs = tonumber, type, print, error, ipairs |
5 | local setmetatable = setmetatable | 5 | local setmetatable = setmetatable |
6 | local unpack = table.unpack or unpack | 6 | local unpack = table.unpack or unpack |
7 | local tinsert = table.insert | ||
7 | local m = require"lpeglabel" | 8 | local 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 | ||
24 | local any = m.P(1) | 25 | local any = m.P(1) |
25 | 26 | ||
27 | local errors | ||
28 | |||
29 | local 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) | ||
35 | end | ||
26 | 36 | ||
27 | -- Pre-defined names | 37 | -- Pre-defined names |
28 | local Predef = { nl = m.P"\n" } | 38 | local Predef = { nl = m.P"\n" } |
@@ -120,8 +130,8 @@ local Def = name * m.Carg(1) | |||
120 | 130 | ||
121 | local num = m.C(m.R"09"^1) * S / tonumber | 131 | local num = m.C(m.R"09"^1) * S / tonumber |
122 | 132 | ||
123 | local String = "'" * m.C((any - "'")^0) * ("'" + m.T(31)) + | 133 | local 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 | ||
127 | local defined = "%" * Def / function (c,Defs) | 137 | local defined = "%" * Def / function (c,Defs) |
@@ -137,9 +147,9 @@ local item = defined + Range + m.C(any) | |||
137 | local Class = | 147 | local 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 | ||
144 | local function adddef (t, k, exp) | 154 | local function adddef (t, k, exp) |
145 | if t[k] then | 155 | if t[k] then |
@@ -176,12 +186,12 @@ end | |||
176 | 186 | ||
177 | local exp = m.P{ "Exp", | 187 | local 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 | ||
224 | local pattern = S * m.Cg(m.Cc(false), "G") * (exp + m.T(1)) / mm.P * (-any + m.T(2)) | 234 | local pattern = S * m.Cg(m.Cc(false), "G") * (exp + throw(1)) / mm.P * (-any + throw(2)) |
225 | 235 | ||
226 | local function lineno (s, i) | 236 | local 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 | ||
269 | local function compile (p, defs) | 279 | local 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 |
277 | end | 292 | end |
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 | ||
107 | for i, patt in ipairs(patterns) do | 108 | for i, patt in ipairs(patterns) do |