[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [LPeg] How can I signal parsing errors with LPeg?
- From: Sean Conner <sean@...>
- Date: Sat, 30 Jul 2016 00:20:46 -0400
It was thus said that the Great Soni L. once stated:
> As seen in http://stackoverflow.com/q/38664815/3691554
>
> `Line` and `Data` are the things that when `:match()`ed should return
> `nil, errmsg` on parsing error. Note that only `Line` decides whether a
> line is valid or not, so that's where parsing errors happen. `Data` only
> extracts the data from a (valid) line.
Make sure Line always matches the entirety of a valid line. Then you can
modify it to return nil,errmsg, like:
local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0)
/ function(x) return x end
* nl
* lpeg.Cp()
+ lpeg.Cc(nil) * lpeg.Cc("Invalid parse of a line")
local Data = lpeg.S(" \t")^0
* lpeg.Cs((ws / " " + inlineComment / "" + backslashEscaped + 1 - (lpeg.S(" \t")^0 * nl))^0)
* lpeg.S(" \t")^0
* nl
+ lpeg.Cc(nil) * lpeg.Cc("Invalid data")
If you want more specific errors, then you can do something like this:
local escape = lpeg.P"\\ " / " "
+ lpeg.P"\\\\" / "\\"
+ lpeg.P"\\#" / "#"
+ lpeg.P"\\>" / ">"
+ lpeg.P"\\" / ""
+ lpeg.P"\\n" / "\n"
+ lpeg.P"\\" * lpeg.Cmt(lpeg.Carg(1) * lpeg.C(1),
function(subject,pos,e,c)
table.insert(e,"Bad escape " .. c)
return nil
end)
local char = lpeg.R(" [","]~")
local cleanup = lpeg.Cs((escape + char)^0) * lpeg.P"\n"
local function test(s)
local e = {}
local r = cleanup:match(s,1,e)
if not r then
print(e[1])
end
end
test [[Hello\ There\# foob
]]
test [[Hello\aThere\bfoob
]]
I'm using lpeg.Carg() to pass in a table to accumulate the errors (this
keeps this reentrant). lpeg.Cmt() does a match-time capture and if this
returns nil, then that particular capture fails. I've set up this example
such that if cleanup returns nil, then the passed in table will contain the
error.
-spc