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 |
