[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Lpeg error handling
- From: Ico <lua@...>
- Date: Wed, 22 Apr 2009 08:13:18 +0200
Hello,
I'm implementing a parser using Lpeg to parse configuration files for my
application. (for details, see below)
My problem is that I'm not sure how to handle parsing errors gracefully.
If there's a single syntax error somewhere in the file, the Lpeg pattern
does not match at all, so the application is only able to inform the
user that "there is a syntax error somewehere", but no details about the
exact location. Instead I'd like my app to be able to at least report
the line number to the user when the parser finds an error.
What would be the proper way to handle this ?
Regards,
Ico
The configfiles use a recursive language with grouped key-value pairs
like this:
group "lan" {
group "dhcp" {
object "renew" {
type = "action",
label = "Renew lease"
},
},
group "static" {
object "address" {
type = "string",
default = "192.168.1.1",
},
object "netmask" {
type = "string",
default = "255.255.255.0",
},
object "gateway" {
type = "string",
default = "192.168.1.254"
},
},
}
The lpeg parser is quite simple, it defines the basic lexical elements and a
few grammar rules (a group can contain zero or more key-value pairs and zero-or
more groups). The parser uses table captures so the whole configuration file
ends up in a recursive table structure when the parsing is done.
local l = lpeg
-- lexical elements
local space = l.S(" \t\n")^0
local alpha = l.R("az", "AZ")
local num = l.R("09")
local anum = alpha + num
local open = l.P("{")
local close = l.P("}")
local equals = l.P("=")
local comma = l.P(",")
local quote = l.P("\"")
local number = l.C(num^0)
local label = l.C(alpha^1 * anum^0)
local quoted = quote * l.C((l.P(1) - l.P('"'))^0) * quote
local groupdef = space * label * space * quoted * space
local keyvaldef = l.Cf(space * label * space * equals^0 * space * (quoted + number) * space,
function(a, b)
local t={}
t[a]=b
return t
end)
-- grammar
local block = lpeg.V "block"
local item = lpeg.V "item"
local items = lpeg.V "items"
local G = lpeg.P
{
"block",
block = l.Ct(groupdef * open * l.Ct(items) * close),
item = space * (block + keyvaldef) * space,
items = space * item * (space * comma * item)^0 * comma^0 * space
}
schema = io.open("network.schema"):read("*a")
dumpf({G:match(schema)})
--
:wq
^X^Cy^K^X^C^C^C^C