lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Jun 12, 2012, at 5:25 AM, steve donovan wrote:

> On Tue, Jun 12, 2012 at 2:10 PM, Gavin Wraith <gavin@wra1th.plus.com> wrote:
>> I would be interested to know how others use lpeg.
>> One strategy is to try and get the bare pattern right
>> first, without using captures
> 
> Being a bear of little brain, I find it helps to test the individual
> patterns with their captures interactively.
> 
> Then one can compose these patterns with some confidence to build
> complicated structures bottom-up.
> 
> steve d.


I found it useful to put captures in as soon as possible, because this can help to understand where the parser is going (and where it is going wrong, when it does). If you have a pretty-printer around (e.g. Serpent), then table captures are especially handy. 

I often wrap the nonterminal rule patterns in this function, which creates a table capture annotated with position and rule name information:

local function rule(name, patt) 
	return lpeg.Ct(lpeg.Cg(lpeg.Cc(name), "rule") * lpeg.Cg(lpeg.Cp(), "pos") * patt) 
end

Also it can be useful to append the following pattern to the end of ordered choice patterns, and always to the root pattern of the grammar, so that if a pattern or grammar fails, you get information about where/why:

local function perror(err)
	return lpeg.P(1)^0 / function(str) 
		if #str > 10 then str = str:sub(1, 10) end	-- just capture first 10 characters 
		format("error: %s (%s)", err or "?", str)
	end
end

Combined:

local function validate(name, patt)
	return (rule(name, patt) * -1) + perror(name)
end

e.g. 
patt = validate("digit", lpeg.R("09"))

Another way of figuring out what the grammar is doing is to attach match-time captures for the good old debug print method of debugging:

local function ptrace(name)
	return lpeg.Cmt(#lpeg.P(1), function(s, i)
		print(format("%s matched %s", string.rep(" ", i), name), i, s:sub(i, i+3))
		return true
	end)
end

e.g. 
patt = ptrace("predigit") * lpeg.R("09") * ptrace("postdigit")