lua-users home
lua-l archive

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


Hi list,

this is related to the discussion in this thread:

  http://lua-users.org/lists/lua-l/2023-08/threads.html#00041

I was trying to write a lpeg pattern that would parse strings like
"(%i3)" and "(%o42)" and return tables like these ones:

  {a="i", b="3", c="(%i3)"}
  {a="o", b="42", c="(%o42)"}

The long story is that I'm rewriting my functions that parse the logs
of Maxima sessions. These logs look this, but that's not relevant now:

  https://home.csulb.edu/~woollett/mbe1intro.pdf#page=9

Anyway, here's what I tried to do - the "PP" in lpeg.pm is my favorite
pretty-printing function, defined in my init file...

  require "lpeg"
  B,C,P,R,S,V = lpeg.B,lpeg.C,lpeg.P,lpeg.R,lpeg.S,lpeg.V
  Cb,Cc,Cf,Cg = lpeg.Cb,lpeg.Cc,lpeg.Cf,lpeg.Cg
  Cp,Cs,Ct    = lpeg.Cp,lpeg.Cs,lpeg.Ct
  Carg,Cmt    = lpeg.Carg,lpeg.Cmt
  lpeg.pm     = function (pat, str) PP(pat:match(str or "")) end

  pa = S"io":Cg"a"
  pb = (R"09"^1):Cg"b"
  pabc  = (P"(%" * pa * pb * P")"):C():Cg"c":Ct()
  pfake = (P"(%i42)" * Cc"i":Cg"a" * Cc"42":Cg"b" * Cc"(%i42)":Cg"c"):Ct()

  pabc :pm"(%i42)"   --> {"c"="(%i42)"}
  pfake:pm"(%i42)"   --> {"a"="i", "b"="42", "c"="(%i42)"}

At first I thought that pabc:pm"(%i42)" would print a table with
fields "a", "b", and "c", like the table printed by the "fake" pattern
pfake in pfake:pm"(%i42)"... but that's not what happens. The
explanation is here:

  lpeg.C (patt)

  Creates a simple capture, which captures the substring of the
  subject that matches patt. The captured value is a string. If patt
  has other captures, their values are returned after this one.

  Source: http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html#cap-c

The "their _values_ are returned after this one" means that only the
captures that are "values" are returned; the "named" captures produced
by Cg are dropped. This can also be seen in this other test:

  pe = Cc(20) * Cc(30):Cg"a" * Cc(40) * Cc(50):Cg"b"
  pe         :pm"foo"    --> 20 40
  pe    :Ct():pm"foo"    --> {1=20, 2=40, "a"=30, "b"=50}
  pe:C()     :pm"foo"    --> "" 20 40
  pe:C():Ct():pm"foo"    --> {1="", 2=20, 3=40}

So: I understand what is happening, and why it happens... but is there
a workaround? Is it possible to replace the :C():Cg"c" in

  pabc  = (P"(%" * pa * pb * P")"):C():Cg"c":Ct()

by something else, that would put the substring matched by the

           P"(%" * pa * pb * P")"

into the key "c" without dropping the named captures generated by pa
and pb?

Thanks in advance!
  Eduardo Ochs
  http://anggtwu.net/luaforth.html