lua-users home
lua-l archive

Re: Trace debugger for lpeg

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


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
-- -- -- -- -- -- -- -- -- -- -- -- -- --

AltStyle によって変換されたページ (->オリジナル) /