• Subject: Lpeg: a question about function captures and named captures
• From: Eduardo Ochs <eduardoochs@...>
• Date: Wed, 12 Apr 2023 15:25:47 -0300

Hi list,

if anyone wants a short version of my question, here it is...
when we use function captures in lpeg - i.e., this thing,

http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html#cap-func

the "f" in patt/f receives "numbered captures" and returns "numbered
captures". Is there a way to write something similar to that returns
named captures?

Now here is a clearer version of that question, with code. In the code
below PP is my favorite pretty-printing functions. It is defined in my
init file, and it prints tables like this:

> PP {a="b", 10, 20}
{1=10, 2=20, "a"="b"}
>

There's even a way to configure it to make it print tables like this,

> PP {a="b", 10, 20}
{[1]=10, [2]=20, ["a"]="b"}
>

but I don't use it much. Anyway, here is the code:

require "lpeg"
B,C,P,R,S,V = lpeg.B,lpeg.C,lpeg.P,lpeg.R,lpeg.S,lpeg.V
Cb,Cc,Cf,Cg = lpeg.Cb,lpeg.Cc,lpeg.Cf,lpeg.Cg
Cp,Cs,Ct    = lpeg.Cp,lpeg.Cs,lpeg.Ct
Carg,Cmt    = lpeg.Carg,lpeg.Cmt

lpeg.ptmatch = function (pat, str) PP(pat:Ct():match(str)) end

PP {a="b", 10, 20}

f = function (a,b) return a..b,b..a end

(Cc"a" * Cc"b")           :ptmatch("ccc")
(Cc"a" * Cc"b" / f)       :ptmatch("ccc")
(Cc"a" * Cc"b" / f):Cg"c" :ptmatch("ccc")
(Cc"a" * Cc"b" / f):Cg(3) :ptmatch("ccc")

If I run it one line at a time in a REPL I get this:

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> require "lpeg"
> B,C,P,R,S,V = lpeg.B,lpeg.C,lpeg.P,lpeg.R,lpeg.S,lpeg.V
> Cb,Cc,Cf,Cg = lpeg.Cb,lpeg.Cc,lpeg.Cf,lpeg.Cg
> Cp,Cs,Ct    = lpeg.Cp,lpeg.Cs,lpeg.Ct
> Carg,Cmt    = lpeg.Carg,lpeg.Cmt
>
> lpeg.ptmatch = function (pat, str) PP(pat:Ct():match(str)) end
>
> PP {a="b", 10, 20}
{1=10, 2=20, "a"="b"}
>
> f = function (a,b) return a..b,b..a end
>
> (Cc"a" * Cc"b")           :ptmatch("ccc")
{1="a", 2="b"}
> (Cc"a" * Cc"b" / f)       :ptmatch("ccc")
{1="ab", 2="ba"}
> (Cc"a" * Cc"b" / f):Cg"c" :ptmatch("ccc")
{"c"="ab"}
> (Cc"a" * Cc"b" / f):Cg(3) :ptmatch("ccc")
{3="ab"}
>

How do I modify the ".../f" above to make it put the first result of f
into :Cg"c" and the second result into :Cg"d"?