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