[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: LPeg indent/whitespace based grammar
- From: Duncan Cross <duncan.cross@...>
- Date: Tue, 11 Jul 2017 19:51:30 +0100
On Sat, Jul 8, 2017 at 8:12 PM, Matthias Dörfelt <lists@mokafolio.de> wrote:
> I tried to do so using table and named group capture, but I can’t for the
> life of me figure out how to dynamically set the name of the group capture.
> Will I have to write a custom helper function to achieve this or is there a
> pure re way?
You do need to use a function for this -- re is only a thin layer on
top of the same basic primitives as lpeg itself, and lpeg.Cg() takes a
constant value, not a pattern capture, for the group name specifier.
One approach is to capture an array of key/value pair objects, and
then use a function capture to transform this array into an object
with named fields. Something like this:
--
local re = require 're'
local fields = re.compile([[
fields <- {| <kvpair>* !. |} -> kvpairs_to_fields
kvpair <- {| %s* {:key: <key> :} %s* '=' %s* {:value: <value> :} %s* |}
key <- [a-zA-Z_] [a-zA-Z_0-9]*
value <- <single_quoted> / <double_quoted>
single_quoted <- ['] { [^']* } [']
double_quoted <- ["] { [^"]* } ["]
]], {
kvpairs_to_fields = function(kvpairs)
local attrs = {}
for _, kv in ipairs(kvpairs) do
attrs[kv.key] = kv.value
end
return attrs
end;
})
for k,v in pairs(fields:match[[ a="one" b = 'two' c="three" ]]) do
print(k, v)
end
--
-Duncan