Blame re.lua

Packit 909456
-- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $
Packit 909456
Packit 909456
-- imported functions and modules
Packit 909456
local tonumber, type, print, error = tonumber, type, print, error
Packit 909456
local setmetatable = setmetatable
Packit 909456
local m = require"lpeg"
Packit 909456
Packit 909456
-- 'm' will be used to parse expressions, and 'mm' will be used to
Packit 909456
-- create expressions; that is, 're' runs on 'm', creating patterns
Packit 909456
-- on 'mm'
Packit 909456
local mm = m
Packit 909456
Packit 909456
-- pattern's metatable
Packit 909456
local mt = getmetatable(mm.P(0))
Packit 909456
Packit 909456
Packit 909456
Packit 909456
-- No more global accesses after this point
Packit 909456
local version = _VERSION
Packit 909456
if version == "Lua 5.2" then _ENV = nil end
Packit 909456
Packit 909456
Packit 909456
local any = m.P(1)
Packit 909456
Packit 909456
Packit 909456
-- Pre-defined names
Packit 909456
local Predef = { nl = m.P"\n" }
Packit 909456
Packit 909456
Packit 909456
local mem
Packit 909456
local fmem
Packit 909456
local gmem
Packit 909456
Packit 909456
Packit 909456
local function updatelocale ()
Packit 909456
  mm.locale(Predef)
Packit 909456
  Predef.a = Predef.alpha
Packit 909456
  Predef.c = Predef.cntrl
Packit 909456
  Predef.d = Predef.digit
Packit 909456
  Predef.g = Predef.graph
Packit 909456
  Predef.l = Predef.lower
Packit 909456
  Predef.p = Predef.punct
Packit 909456
  Predef.s = Predef.space
Packit 909456
  Predef.u = Predef.upper
Packit 909456
  Predef.w = Predef.alnum
Packit 909456
  Predef.x = Predef.xdigit
Packit 909456
  Predef.A = any - Predef.a
Packit 909456
  Predef.C = any - Predef.c
Packit 909456
  Predef.D = any - Predef.d
Packit 909456
  Predef.G = any - Predef.g
Packit 909456
  Predef.L = any - Predef.l
Packit 909456
  Predef.P = any - Predef.p
Packit 909456
  Predef.S = any - Predef.s
Packit 909456
  Predef.U = any - Predef.u
Packit 909456
  Predef.W = any - Predef.w
Packit 909456
  Predef.X = any - Predef.x
Packit 909456
  mem = {}    -- restart memoization
Packit 909456
  fmem = {}
Packit 909456
  gmem = {}
Packit 909456
  local mt = {__mode = "v"}
Packit 909456
  setmetatable(mem, mt)
Packit 909456
  setmetatable(fmem, mt)
Packit 909456
  setmetatable(gmem, mt)
Packit 909456
end
Packit 909456
Packit 909456
Packit 909456
updatelocale()
Packit 909456
Packit 909456
Packit 909456
Packit 909456
local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
Packit 909456
Packit 909456
Packit 909456
local function getdef (id, defs)
Packit 909456
  local c = defs and defs[id]
Packit 909456
  if not c then error("undefined name: " .. id) end
Packit 909456
  return c
Packit 909456
end
Packit 909456
Packit 909456
Packit 909456
local function patt_error (s, i)
Packit 909456
  local msg = (#s < i + 20) and s:sub(i)
Packit 909456
                             or s:sub(i,i+20) .. "..."
Packit 909456
  msg = ("pattern error near '%s'"):format(msg)
Packit 909456
  error(msg, 2)
Packit 909456
end
Packit 909456
Packit 909456
local function mult (p, n)
Packit 909456
  local np = mm.P(true)
Packit 909456
  while n >= 1 do
Packit 909456
    if n%2 >= 1 then np = np * p end
Packit 909456
    p = p * p
Packit 909456
    n = n/2
Packit 909456
  end
Packit 909456
  return np
Packit 909456
end
Packit 909456
Packit 909456
local function equalcap (s, i, c)
Packit 909456
  if type(c) ~= "string" then return nil end
Packit 909456
  local e = #c + i
Packit 909456
  if s:sub(i, e - 1) == c then return e else return nil end
Packit 909456
end
Packit 909456
Packit 909456
Packit 909456
local S = (Predef.space + "--" * (any - Predef.nl)^0)^0
Packit 909456
Packit 909456
local name = m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0
Packit 909456
Packit 909456
local arrow = S * "<-"
Packit 909456
Packit 909456
local seq_follow = m.P"/" + ")" + "}" + ":}" + "~}" + "|}" + (name * arrow) + -1
Packit 909456
Packit 909456
name = m.C(name)
Packit 909456
Packit 909456
Packit 909456
-- a defined name only have meaning in a given environment
Packit 909456
local Def = name * m.Carg(1)
Packit 909456
Packit 909456
local num = m.C(m.R"09"^1) * S / tonumber
Packit 909456
Packit 909456
local String = "'" * m.C((any - "'")^0) * "'" +
Packit 909456
               '"' * m.C((any - '"')^0) * '"'
Packit 909456
Packit 909456
Packit 909456
local defined = "%" * Def / function (c,Defs)
Packit 909456
  local cat =  Defs and Defs[c] or Predef[c]
Packit 909456
  if not cat then error ("name '" .. c .. "' undefined") end
Packit 909456
  return cat
Packit 909456
end
Packit 909456
Packit 909456
local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
Packit 909456
Packit 909456
local item = defined + Range + m.C(any)
Packit 909456
Packit 909456
local Class =
Packit 909456
    "["
Packit 909456
  * (m.C(m.P"^"^-1))    -- optional complement symbol
Packit 909456
  * m.Cf(item * (item - "]")^0, mt.__add) /
Packit 909456
                          function (c, p) return c == "^" and any - p or p end
Packit 909456
  * "]"
Packit 909456
Packit 909456
local function adddef (t, k, exp)
Packit 909456
  if t[k] then
Packit 909456
    error("'"..k.."' already defined as a rule")
Packit 909456
  else
Packit 909456
    t[k] = exp
Packit 909456
  end
Packit 909456
  return t
Packit 909456
end
Packit 909456
Packit 909456
local function firstdef (n, r) return adddef({n}, n, r) end
Packit 909456
Packit 909456
Packit 909456
local function NT (n, b)
Packit 909456
  if not b then
Packit 909456
    error("rule '"..n.."' used outside a grammar")
Packit 909456
  else return mm.V(n)
Packit 909456
  end
Packit 909456
end
Packit 909456
Packit 909456
Packit 909456
local exp = m.P{ "Exp",
Packit 909456
  Exp = S * ( m.V"Grammar"
Packit 909456
            + m.Cf(m.V"Seq" * ("/" * S * m.V"Seq")^0, mt.__add) );
Packit 909456
  Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^0 , mt.__mul)
Packit 909456
        * (#seq_follow + patt_error);
Packit 909456
  Prefix = "&" * S * m.V"Prefix" / mt.__len
Packit 909456
         + "!" * S * m.V"Prefix" / mt.__unm
Packit 909456
         + m.V"Suffix";
Packit 909456
  Suffix = m.Cf(m.V"Primary" * S *
Packit 909456
          ( ( m.P"+" * m.Cc(1, mt.__pow)
Packit 909456
            + m.P"*" * m.Cc(0, mt.__pow)
Packit 909456
            + m.P"?" * m.Cc(-1, mt.__pow)
Packit 909456
            + "^" * ( m.Cg(num * m.Cc(mult))
Packit 909456
                    + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow))
Packit 909456
                    )
Packit 909456
            + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div))
Packit 909456
                         + m.P"{}" * m.Cc(nil, m.Ct)
Packit 909456
                         + m.Cg(Def / getdef * m.Cc(mt.__div))
Packit 909456
                         )
Packit 909456
            + "=>" * S * m.Cg(Def / getdef * m.Cc(m.Cmt))
Packit 909456
            ) * S
Packit 909456
          )^0, function (a,b,f) return f(a,b) end );
Packit 909456
  Primary = "(" * m.V"Exp" * ")"
Packit 909456
            + String / mm.P
Packit 909456
            + Class
Packit 909456
            + defined
Packit 909456
            + "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" /
Packit 909456
                     function (n, p) return mm.Cg(p, n) end
Packit 909456
            + "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end
Packit 909456
            + m.P"{}" / mm.Cp
Packit 909456
            + "{~" * m.V"Exp" * "~}" / mm.Cs
Packit 909456
            + "{|" * m.V"Exp" * "|}" / mm.Ct
Packit 909456
            + "{" * m.V"Exp" * "}" / mm.C
Packit 909456
            + m.P"." * m.Cc(any)
Packit 909456
            + (name * -arrow + "<" * name * ">") * m.Cb("G") / NT;
Packit 909456
  Definition = name * arrow * m.V"Exp";
Packit 909456
  Grammar = m.Cg(m.Cc(true), "G") *
Packit 909456
            m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0,
Packit 909456
              adddef) / mm.P
Packit 909456
}
Packit 909456
Packit 909456
local pattern = S * m.Cg(m.Cc(false), "G") * exp / mm.P * (-any + patt_error)
Packit 909456
Packit 909456
Packit 909456
local function compile (p, defs)
Packit 909456
  if mm.type(p) == "pattern" then return p end   -- already compiled
Packit 909456
  local cp = pattern:match(p, 1, defs)
Packit 909456
  if not cp then error("incorrect pattern", 3) end
Packit 909456
  return cp
Packit 909456
end
Packit 909456
Packit 909456
local function match (s, p, i)
Packit 909456
  local cp = mem[p]
Packit 909456
  if not cp then
Packit 909456
    cp = compile(p)
Packit 909456
    mem[p] = cp
Packit 909456
  end
Packit 909456
  return cp:match(s, i or 1)
Packit 909456
end
Packit 909456
Packit 909456
local function find (s, p, i)
Packit 909456
  local cp = fmem[p]
Packit 909456
  if not cp then
Packit 909456
    cp = compile(p) / 0
Packit 909456
    cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) }
Packit 909456
    fmem[p] = cp
Packit 909456
  end
Packit 909456
  local i, e = cp:match(s, i or 1)
Packit 909456
  if i then return i, e - 1
Packit 909456
  else return i
Packit 909456
  end
Packit 909456
end
Packit 909456
Packit 909456
local function gsub (s, p, rep)
Packit 909456
  local g = gmem[p] or {}   -- ensure gmem[p] is not collected while here
Packit 909456
  gmem[p] = g
Packit 909456
  local cp = g[rep]
Packit 909456
  if not cp then
Packit 909456
    cp = compile(p)
Packit 909456
    cp = mm.Cs((cp / rep + 1)^0)
Packit 909456
    g[rep] = cp
Packit 909456
  end
Packit 909456
  return cp:match(s)
Packit 909456
end
Packit 909456
Packit 909456
Packit 909456
-- exported names
Packit 909456
local re = {
Packit 909456
  compile = compile,
Packit 909456
  match = match,
Packit 909456
  find = find,
Packit 909456
  gsub = gsub,
Packit 909456
  updatelocale = updatelocale,
Packit 909456
}
Packit 909456
Packit 909456
if version == "Lua 5.1" then _G.re = re end
Packit 909456
Packit 909456
return re