lua-users home
lua-l archive

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


Perhaps something like the following?

local input = [[
     %[ one
     %[ two ]%
     %[ three
             %[ four ]%
          five ]%
      six ]%
]]

local lpeg = require "lpeg"
local C, Ct, P, R, S, V = lpeg.C, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.V

local grammar = P { "entity";
  whitespace = S" \t\r\n"^0,
  open = P"%[",
  close = P"]%",
  name = C(R("az", "AZ", "__")^1),
  item = (V"name" + V"entity") * V"whitespace",
  entity = V"whitespace" * Ct(V"open" * V"whitespace" * V"item"^0 * V"close"),
}

local t = grammar:match(input)

local function print_a(t)
  io.write"{"
  for i, v in ipairs(t) do
    if type(v) == "table" then
      print_a(v)
    else
      io.write(("%q"):format(v))
    end
    if t[i + 1] then
      io.write", "
    end
  end
  io.write"}"
end

print_a(t) --> {"one", {"two"}, {"three", {"four"}, "five"}, "six"}


2009/6/19 Luís Eduardo Jason Santos <jasonsantos@gmail.com>:
> Hi,
>
> I know this is probably a trivial problem for you, people, but I was hoping
> you could provide me some advice regarding this problem I am facing while
> building an LPEG Grammar.
>
> I am trying to create a parser that reads a recursive pattern and builds a
> tree with each capture.
>
> Given the example:
>
> s = [[
>      %[ one
>      %[ two ]%
>      %[ three
>              %[ four ]%
>           five ]%
>       six ]%
>
> ]]
>
> I would like to get a response 't' where
>
> t = { "one", {"two"}, {"three", {"four"}, "five"}, "six" }
>
>
> I have written a simple grammar to experiment with the problem, but I
> couldn't think of a way to solve it.
>
>
> require'luarocks.require'
> require'lpeg'
>
> local SPACE    = lpeg.S" \t\n\f"
> local OPEN    = lpeg.P"%["
> local CLOSE    = lpeg.P"]%"
> local ITEM, SIMPLEITEM, NONITEM, CONTENT = lpeg.V'ITEM', lpeg.V'SIMPLEITEM',
> lpeg.V'NONITEM', lpeg.V'CONTENT'
>
> local item = function(content)
>     print('>', content)
>     -- TODO: ??
> end
>
> local simpleitem = function(content)
>     print('>', content)
>     -- TODO: ??
> end
>
> local PATT = {
>     CONTENT,
>     ITEM    = OPEN * lpeg.C(CONTENT) * CLOSE,
>     SIMPLEITEM = OPEN * lpeg.C(NONITEM^0) * CLOSE,
>     NONITEM = 1-(OPEN + CLOSE),
>     CONTENT = (SPACE + SIMPLEITEM / simpleitem + ITEM / item + NONITEM)^1
> }
>
> lpeg.match(PATT, s)
>
>
> I wonder if the answer is at some feature of LPEG that I am not quite
> familiar with yet (like folding captures). I have tried that one, but It
> didn't seemed quite right for the job (since I would probablly have to add
> some constant captures and make a 'switch' inside the function to infer my
> position on the grammar).
>
> Can anyone throw me a bone?
>
> Att.
> Luís Eduardo Jason Santos
>
>