neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

re.lua (6684B)


      1 --- @diagnostic disable: no-unknown
      2 --
      3 -- Copyright 2007-2023, Lua.org & PUC-Rio  (see 'lpeg.html' for license)
      4 -- written by Roberto Ierusalimschy
      5 --
      6 --- vendored from lpeg-1.1.0
      7 --- documentation available at runtime/lua/vim/_meta/re.lua
      8 
      9 -- imported functions and modules
     10 local tonumber, type, error = tonumber, type, error
     11 local setmetatable = setmetatable
     12 local m = require"lpeg"
     13 
     14 -- 'm' will be used to parse expressions, and 'mm' will be used to
     15 -- create expressions; that is, 're' runs on 'm', creating patterns
     16 -- on 'mm'
     17 local mm = m
     18 
     19 -- patterns' metatable
     20 local mt = getmetatable(mm.P(0))
     21 
     22 
     23 local version = _VERSION
     24 
     25 -- No more global accesses after this point
     26 _ENV = nil     -- does no harm in Lua 5.1
     27 
     28 
     29 local any = m.P(1)
     30 
     31 
     32 -- Pre-defined names
     33 local Predef = { nl = m.P"\n" }
     34 
     35 
     36 local mem
     37 local fmem
     38 local gmem
     39 
     40 
     41 local function updatelocale ()
     42  mm.locale(Predef)
     43  Predef.a = Predef.alpha
     44  Predef.c = Predef.cntrl
     45  Predef.d = Predef.digit
     46  Predef.g = Predef.graph
     47  Predef.l = Predef.lower
     48  Predef.p = Predef.punct
     49  Predef.s = Predef.space
     50  Predef.u = Predef.upper
     51  Predef.w = Predef.alnum
     52  Predef.x = Predef.xdigit
     53  Predef.A = any - Predef.a
     54  Predef.C = any - Predef.c
     55  Predef.D = any - Predef.d
     56  Predef.G = any - Predef.g
     57  Predef.L = any - Predef.l
     58  Predef.P = any - Predef.p
     59  Predef.S = any - Predef.s
     60  Predef.U = any - Predef.u
     61  Predef.W = any - Predef.w
     62  Predef.X = any - Predef.x
     63  mem = {}    -- restart memoization
     64  fmem = {}
     65  gmem = {}
     66  local mt0 = {__mode = "v"}
     67  setmetatable(mem, mt0)
     68  setmetatable(fmem, mt0)
     69  setmetatable(gmem, mt0)
     70 end
     71 
     72 
     73 updatelocale()
     74 
     75 
     76 
     77 -- local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
     78 
     79 
     80 local function patt_error (s, i)
     81  local msg = (#s < i + 20) and s:sub(i)
     82                             or s:sub(i,i+20) .. "..."
     83  msg = ("pattern error near '%s'"):format(msg)
     84  error(msg, 2)
     85 end
     86 
     87 local function mult (p, n)
     88  local np = mm.P(true)
     89  while n >= 1 do
     90    if n%2 >= 1 then np = np * p end
     91    p = p * p
     92    n = n/2
     93  end
     94  return np
     95 end
     96 
     97 local function equalcap (s, i, c)
     98  if type(c) ~= "string" then return nil end
     99  local e = #c + i
    100  if s:sub(i, e - 1) == c then return e else return nil end
    101 end
    102 
    103 
    104 local S = (Predef.space + "--" * (any - Predef.nl)^0)^0
    105 
    106 local name = m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0
    107 
    108 local arrow = S * "<-"
    109 
    110 local seq_follow = m.P"/" + ")" + "}" + ":}" + "~}" + "|}" + (name * arrow) + -1
    111 
    112 name = m.C(name)
    113 
    114 
    115 -- a defined name only have meaning in a given environment
    116 local Def = name * m.Carg(1)
    117 
    118 
    119 local function getdef (id, defs)
    120  local c = defs and defs[id]
    121  if not c then error("undefined name: " .. id) end
    122  return c
    123 end
    124 
    125 -- match a name and return a group of its corresponding definition
    126 -- and 'f' (to be folded in 'Suffix')
    127 local function defwithfunc (f)
    128  return m.Cg(Def / getdef * m.Cc(f))
    129 end
    130 
    131 
    132 local num = m.C(m.R"09"^1) * S / tonumber
    133 
    134 local String = "'" * m.C((any - "'")^0) * "'" +
    135               '"' * m.C((any - '"')^0) * '"'
    136 
    137 
    138 local defined = "%" * Def / function (c,Defs)
    139  local cat =  Defs and Defs[c] or Predef[c]
    140  if not cat then error ("name '" .. c .. "' undefined") end
    141  return cat
    142 end
    143 
    144 local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
    145 
    146 local item = (defined + Range + m.C(any)) / m.P
    147 
    148 local Class =
    149    "["
    150  * (m.C(m.P"^"^-1))    -- optional complement symbol
    151  * (item * ((item % mt.__add) - "]")^0) /
    152                          function (c, p) return c == "^" and any - p or p end
    153  * "]"
    154 
    155 local function adddef (t, k, exp)
    156  if t[k] then
    157    error("'"..k.."' already defined as a rule")
    158  else
    159    t[k] = exp
    160  end
    161  return t
    162 end
    163 
    164 local function firstdef (n, r) return adddef({n}, n, r) end
    165 
    166 
    167 local function NT (n, b)
    168  if not b then
    169    error("rule '"..n.."' used outside a grammar")
    170  else return mm.V(n)
    171  end
    172 end
    173 
    174 
    175 local exp = m.P{ "Exp",
    176  Exp = S * ( m.V"Grammar"
    177            + m.V"Seq" * ("/" * S * m.V"Seq" % mt.__add)^0 );
    178  Seq = (m.Cc(m.P"") * (m.V"Prefix" % mt.__mul)^0)
    179        * (#seq_follow + patt_error);
    180  Prefix = "&" * S * m.V"Prefix" / mt.__len
    181         + "!" * S * m.V"Prefix" / mt.__unm
    182         + m.V"Suffix";
    183  Suffix = m.V"Primary" * S *
    184          ( ( m.P"+" * m.Cc(1, mt.__pow)
    185            + m.P"*" * m.Cc(0, mt.__pow)
    186            + m.P"?" * m.Cc(-1, mt.__pow)
    187            + "^" * ( m.Cg(num * m.Cc(mult))
    188                    + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow))
    189                    )
    190            + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div))
    191                         + m.P"{}" * m.Cc(nil, m.Ct)
    192                         + defwithfunc(mt.__div)
    193                         )
    194            + "=>" * S * defwithfunc(mm.Cmt)
    195            + ">>" * S * defwithfunc(mt.__mod)
    196            + "~>" * S * defwithfunc(mm.Cf)
    197            ) % function (a,b,f) return f(a,b) end * S
    198          )^0;
    199  Primary = "(" * m.V"Exp" * ")"
    200            + String / mm.P
    201            + Class
    202            + defined
    203            + "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" /
    204                     function (n, p) return mm.Cg(p, n) end
    205            + "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end
    206            + m.P"{}" / mm.Cp
    207            + "{~" * m.V"Exp" * "~}" / mm.Cs
    208            + "{|" * m.V"Exp" * "|}" / mm.Ct
    209            + "{" * m.V"Exp" * "}" / mm.C
    210            + m.P"." * m.Cc(any)
    211            + (name * -arrow + "<" * name * ">") * m.Cb("G") / NT;
    212  Definition = name * arrow * m.V"Exp";
    213  Grammar = m.Cg(m.Cc(true), "G") *
    214            ((m.V"Definition" / firstdef) * (m.V"Definition" % adddef)^0) / mm.P
    215 }
    216 
    217 local pattern = S * m.Cg(m.Cc(false), "G") * exp / mm.P * (-any + patt_error)
    218 
    219 
    220 local function compile (p, defs)
    221  if mm.type(p) == "pattern" then return p end   -- already compiled
    222  local cp = pattern:match(p, 1, defs)
    223  if not cp then error("incorrect pattern", 3) end
    224  return cp
    225 end
    226 
    227 local function match (s, p, i)
    228  local cp = mem[p]
    229  if not cp then
    230    cp = compile(p)
    231    mem[p] = cp
    232  end
    233  return cp:match(s, i or 1)
    234 end
    235 
    236 local function find (s, p, i)
    237  local cp = fmem[p]
    238  if not cp then
    239    cp = compile(p) / 0
    240    cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) }
    241    fmem[p] = cp
    242  end
    243  local e
    244  i, e = cp:match(s, i or 1)
    245  if i then return i, e - 1
    246  else return i
    247  end
    248 end
    249 
    250 local function gsub (s, p, rep)
    251  local g = gmem[p] or {}   -- ensure gmem[p] is not collected while here
    252  gmem[p] = g
    253  local cp = g[rep]
    254  if not cp then
    255    cp = compile(p)
    256    cp = mm.Cs((cp / rep + 1)^0)
    257    g[rep] = cp
    258  end
    259  return cp:match(s)
    260 end
    261 
    262 
    263 -- exported names
    264 local re = {
    265  compile = compile,
    266  match = match,
    267  find = find,
    268  gsub = gsub,
    269  updatelocale = updatelocale,
    270 }
    271 
    272 if version == "Lua 5.1" then _G.re = re end
    273 
    274 return re