[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Trace debugger for lpeg
- From: Philippe Lhoste <PhiLho@...>
- Date: Tue, 29 May 2012 15:25:18 +0200
On 29/05/2012 14:48, Roberto Ierusalimschy wrote:
Here is my version:
[...]
local enter = lpeg.P(function (s, p, ...) print("ENTER", k) return true end)
local leave = lpeg.P(function (s, p, ...) print("LEAVE", k) return false end)
I minor detail: These two functions do not need parameters:
"lpeg.P(function () print(..."
Yes, I kept them from the original code, partly because it was documenting the function
capture...
Actually, meanwhile I made some other improvements, giving more information on the
process, and indenting the output for better understanding. I was about to post here, and
seeing your message, I just removed the parameters where I really don't use them. :-)
function trace(grammar, withIndent)
local level = 0
local lastTry = {}
for k, r in pairs(grammar) do
if type(k) == "number" then
-- Doesn't work with grammar only defined with numerical indexes,
-- but I feel they aren't common...
if type(r) ~= "pattern" and type(r) ~= "userdata" then
print("Initial rule: " .. r)
end
else
-- Indentation, if asked, with number of spaces
-- corresponding to the nesting level
local prefix = function (info)
if withIndent then
return string.rep(" ", level) .. info
else
return info
end
end
local try = lpeg.P(function (s, p, ...)
print(prefix"TRY", k, "AT", p, "WITH", "'" .. s:sub(p, p) .. "'")
level = level + 1
lastTry[level] = p
return true
end)
local fail = lpeg.P(function (s, p, ...)
level = level - 1
print(prefix"FAIL", k)
return false
end)
grammar[k] = lpeg.Cmt(try * r + fail,
function (s, p, ...)
local lt = lastTry[level]
level = level - 1
print(prefix"MATCH", k, "UP TO", p, "=", "'" .. s:sub(lt, p-1) .. "'")
print("-->", "'" .. s:sub(1, p-1) .. "'")
return true
end)
end
end
return grammar
end
With a little grammar for testing: parsing something similar to Lua tables.
local test = [[ { a, { b, c, { d }, e, } ; f, {}, { { g, h } } ; i, { { j }, k, } } ]]
local P, S, C, Ct, V = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.V
local OpenBrace = P'{'
local CloseBrace = P'}'
local Separator = S',;'
local Spaces = S" \r\n"^0
local grammar =
{
"Start";
Start = Spaces * V"Table",
Table = OpenBrace * Spaces * V"Elements"^-1 * CloseBrace * Spaces,
Elements = V"Element" *
(Separator * Spaces * V"Element")^0 *
Separator^-1 * Spaces,
Element = V"Table" + V"Unit",
-- Primitive, not fully conform to Lua syntax, but OK for this test
Unit = (1 - Separator - OpenBrace - CloseBrace)^1 * Spaces,
}
print(P(trace(grammar, true)):match(test))
The definition of the grammar is important for proper debugging...
In my initial version, I have put the Spaces before the items. It was working, but was
mostly showing these spaces instead of interesting chars...
Also I defined the base patterns outside of the grammar for performance, but if they are
included in the grammar, they can give more information.
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --