jx_client_neibu/lua_probject/tolua_project/lpeg/re.lua

268 lines
6.0 KiB
Lua
Raw Normal View History

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