[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: LPeg captures into a table
- From: Sean Conner <sean@...>
- Date: Mon, 3 Aug 2015 17:01:44 -0400
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.
-spc (I could also pass in an extra table and grab it via lpeg.Carg() ... )
[1] https://github.com/spc476/LPeg-Parsers/blob/master/email.lua
[2] But I used a custom function to store the data into a table instead
of rawset(). There can be multiple headers with the same name
(Received: comes to mind) and each one is important.