lua-users home
lua-l archive

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


On 11 Aug 2023, at 14:48, Sean Conner <sean@conman.org> wrote:

Then adding *delim to the end of atom and list, but this seems a bit
clumsy to me.  Is there a better way?  Is there a way to get LPeg to do a
two-stage pass, so you can effectively say match all atoms first, then
match lisp ignoring all spaces?

 No, unless you have two different LPEG expressions.

Ok, here’s what I’ve come up with.  I’m interested in any criticisms you have, as I’m new to LPeg.  (I’ve also fleshed it out with different types of atoms: strings, numbers, etc.)

local tokens = {}

local function add_token(t)
  tokens[#tokens + 1] = t
  t = ('[%d]'):format(#tokens)
  return t
end

local function get_token(t)
  return tokens[tonumber(t)] or ''
end

local space = lpeg.S(' \t\n\r\v')
local atom_g = lpeg.P{
  'atom',
  atom = lpeg.Cs(((lpeg.V'str' + lpeg.V'uuid' + lpeg.V'ident' + lpeg.V'num') / add_token + 1)^0),
  ident = (lpeg.R('az') + lpeg.S'_')^1,
  str = '"' * (1 - lpeg.P('"'))^0 * '"',
  num = lpeg.P('-')^-1 * lpeg.R('09')^1 * ('.' * lpeg.R('09')^1)^-1,
  uuid_part = (lpeg.R('az') + lpeg.R('09'))^1,
  uuid = (lpeg.V'uuid_part' * ('-' * lpeg.V'uuid_part')^1),
}

local ignore_space = lpeg.Cs((space^1 / '' + 1)^0)

local lisp_g = lpeg.P{
  'lisp',
  token = '[' * (lpeg.R("09")^1 / get_token) * ']',
  lisp = '(' * lpeg.Ct((lpeg.V'token' + lpeg.V'lisp')^0) * ')',
}

local m = lisp_g:match(ignore_space:match((atom_g:match(input))))

Regards,
Chris

Chris Smith <space.dandy@icloud.com>