Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/Gram1.lua.html
--   http://anggtwu.net/LUA/Gram1.lua
--          (find-angg "LUA/Gram1.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun e () (interactive) (find-angg "LUA/Gram1.lua"))
-- (defun d () (interactive) (find-luademo-links "LUA/Gram1.lua" "Gram-tests"))
-- (find-es "lpeg" "lpeg-quickref")
-- (find-es "lua5" "metatable-reductions")
-- (find-angg "LUA/eoo.lua")

-- «.without-Gram»	(to "without-Gram")
-- «.Gram»		(to "Gram")
-- «.Gram-tests»	(to "Gram-tests")

require "lpeg"  -- (find-es "lpeg" "lpeg-quickref")
                -- (find-es "lpeg" "globals")
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



-- __        ___ _   _                 _      ____                     
-- \ \      / (_) |_| |__   ___  _   _| |_   / ___|_ __ __ _ _ __ ___  
--  \ \ /\ / /| | __| '_ \ / _ \| | | | __| | |  _| '__/ _` | '_ ` _ \ 
--   \ V  V / | | |_| | | | (_) | |_| | |_  | |_| | | | (_| | | | | | |
--    \_/\_/  |_|\__|_| |_|\___/ \__,_|\__|  \____|_|  \__,_|_| |_| |_|
--                                                                     
-- «without-Gram»  (to ".without-Gram")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Gram1.lua"

gram = {
  Num  = (R"09")^1,
  S    = (S" \t\n")^0,
  Nums = (V"S" * V"Num")^1,
}
gram[1]  = "Num"
=          P(gram):match("987 654 321")
gram.Num = Cs(R"09"^1)
=          P(gram):match("987 654 321")
gram[1]  = "Nums"
=          P(gram):match("987 654 321")

--]]



--   ____                     
--  / ___|_ __ __ _ _ __ ___  
-- | |  _| '__/ _` | '_ ` _ \ 
-- | |_| | | | (_| | | | | | |
--  \____|_|  \__,_|_| |_| |_|
--                            
-- In the terminology of
--   http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html#grammar
-- an object of the class Gram is a grammar that:
--   1) hasn't been "fixed" yet,
--   2) doesn't have an initial rule yet,
--   3) has a nicer interface.
--
-- The typical usage is:
--   gr,V = Gram.new()
-- This "V" can be used both as an lvalue and as a synonym for lpeg.V.
-- For example, these two lines
--   V.foo  = V.bar
--   V.plic = V"ploc"
-- are equivalent to:
--   gr.entries["foo"]  = lpeg.V("bar")
--   gr.entries["plic"] = lpeg.V("ploc")
-- Actually the lvalues here are V.foo and V.bar, not V itself.
--
-- «Gram»  (to ".Gram")
Gram = Class {
  type = "Gram",
  new = function ()
     return Gram.fromentries(VTable {})
   end,
  fromentries = function (entries)
      return Gram {entries=entries},
             Gram.buildV (entries)
    end,
  buildV = function (entries)
      local V = {}
      local mt = {}
      setmetatable(V, mt)
      mt.__call     = function (v,key) return lpeg.V(key) end
      mt.__index    = function (v,key) return lpeg.V(key) end
      mt.__newindex = function (v,key,val) entries[key] = val end
      return V
    end,
  --
  from = function (oldgram)
      return Gram.fromentries(VTable(copy(oldgram.entries)))
    end,
  --
  __tostring = function (gr) return gr:tostring() end,
  __index = {
    compile = function (gr, top)
        local entries = copy(gr.entries)
        entries[1] = top
        return lpeg.P(entries)
      end,
    cm = function (gr, top, subj, pos)
        if type(pos) == "string" then pos = subj:match(pos) end
        return gr:compile(top):match(subj, pos)
      end,
    cmp = function (gr, top, subj, pos)
        return PP(gr:cm(top, subj, pos))
      end,
    tostring = function (gr, sep)
        local ks = sorted(keys(gr.entries))
        return mapconcat(mytostring, ks, sep or "\n")
      end,
  },
}

-- «Gram-tests»  (to ".Gram-tests")
--[[

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Gram1.lua"
gr,V = Gram.new()

V.Num  = (R"09")^1
V.S    = (S" \t\n")^0
V.sNum = Cs(V"Num")

= gr.entries
= gr
= gr:tostring("\n")
= gr:compile("sNum")
= gr:compile("sNum"):match("1234abc")
= gr:compile("sNum"):match("1234abc", 2)
= gr:cmp("sNum", "1234abc", 2)
  gr:cmp("sNum", "1234abc", 2)
  gr:cmp("sNum", "1234abc", "()3")
  gr:cmp("sNum", "1234abc")
  gr:cmp("sNum", "abc")

s      = V"S"
V.Sum  = V"Num" * s * "+" * s * V"Num"
V.sSum = Cs(V"Sum")

  gr:cmp("Sum",  "1 + 2 + 3 + 4 abc")
  gr:cmp("sSum", "1 + 2 + 3 + 4 abc")

V.Sum  = V"Num" * (s * "+" * s * V"Num")^0

  gr:cmp("sSum", "1 + 2 + 3 + 4 abc")

--]]






-- Local Variables:
-- coding:  utf-8-unix
-- End: