lua-users home
lua-l archive

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


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