lua-users home
lua-l archive

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


It was thus said that the Great Eduardo Ochs once stated:
> 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". 

  It actually returns captures:

	> lpeg = require "lpeg"
	> number = lpeg.R"09"^1 / tonumber
	> x = number:match "123"
	> print(type(x),x)
	number 123

The "numbered captures" are a result of using lpeg.Ct().

> Is there a way to write something similar to that returns
> named captures?

  Not directly, no.

> Now here is a clearer version of that question, with code. In the code
> below PP is my favorite pretty-printing functions. 
> ...
> 
>   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"?

  If I understand your question correctly, for

	Cc'a' * Cc'b' / f

you want the first result of f() to go into a field named 'c', and the
second result of f() to go into a field named 'd'.  Yes, that isn't going to
work.  You can change f() to be:

	function f(a,b) return { c = a .. b , d = b .. a } end

And then this line:

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

returns:

	{ c = { c = "ab" , d = "ba" } }

  You could do:

	local pattern = (Ct"" * Cc'a' * Cc'b')
		      / function(t,a,b)
			  t.c = a .. b
			  t.d = b .. a
			  return t
			end

	PP(pattern:match "")

and get a table with:

	{ c = "ab" , d = "ba" }

  Personally, I tend to just use Cg() for all my named capture needs.

  -spc