lua-users home
lua-l archive

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


Hello Sean,

On Mon, Aug 3, 2015 at 5:01 PM, Sean Conner <sean@conman.org> wrote:
> It was thus said that the Great Daurnimator once stated:
>> On 3 August 2015 at 13:12, Sean Conner <sean@conman.org> wrote:
>> > I just want a way
>> > to pull in a field name, and set that field in a table, all using LPeg,
>> > ideally without external variables [2].  Oh, and there is no defined order
>> > to the fields---they can come in any order (and for this problem, assume no
>> > duplicates).
>>
>> I frequently solve this using rawset.
>> There's even an example in the lpeg documentation:
>>
>> local space = lpeg.space^0
>> local name = lpeg.C(lpeg.alpha^1) * space
>> local sep = lpeg.S(",;") * space
>> local pair = lpeg.Cg(name * "=" * space * name) * sep^-1
>> local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset)
>> t = list:match("a=b, c = hi; next = pi")  --> { a = "b", c = "hi", next = "pi" }
>>
>> Each pair has the format name = name followed by an optional separator (a
>> comma or a semicolon). The pair pattern encloses the pair in a group
>> pattern, so that the names become the values of a single capture. The list
>> pattern then folds these captures. It starts with an empty table, created
>> by a table capture matching an empty string; then for each capture (a pair
>> of names) it applies rawset over the accumulator (the table) and the
>> capture values (the pair of names). rawset returns the table itself, so
>> the accumulator is always the table.
>
>   I used a folding capture for parsing email headers [1][2] but this is a
> bit slicker than what I did.  I suppose I might have to go with a folding
> capture to get what I want, but man, there are times when I just want access
> to the table (generated via lpeg.Ct() or '{| |}') because lpeg.C() or
> lpeg.Cg() just doesn't cut it.

What's wrong with using a back capture for the table and then using a
function capture? Something like:

patt = lpeg.P {
    foo = lpeg.Cg(lpeg.Ct "", "tab") * V "bar";
    bar = (lpeg.Cb("tab") * V "stuff") / function (t, ...) end;
}

Best part is that you can have nested matches of foo and the most
"complete outermost capture" [1] of "tab" is used in bar. I use this
to great effect in my lua formatter [2].

[1] http://www.inf.puc-rio.br/~roberto/lpeg/#cap-b
[2] https://github.com/batrick/lunadry/blob/master/lunadry.lua#L62-L68

-- 
Patrick Donnelly