summaryrefslogtreecommitdiff
path: root/vendor/lpeglj/lpprint.lua
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2024-09-26 17:46:38 +0600
committerunwox <me@unwox.com>2024-09-26 17:46:38 +0600
commit9b82db238f9e2e02a76f95c793f8d6ef2387ecfd (patch)
treecdb2a16d01f09553b560ab1034d53392d07bae42 /vendor/lpeglj/lpprint.lua
init
Diffstat (limited to 'vendor/lpeglj/lpprint.lua')
-rw-r--r--vendor/lpeglj/lpprint.lua356
1 files changed, 356 insertions, 0 deletions
diff --git a/vendor/lpeglj/lpprint.lua b/vendor/lpeglj/lpprint.lua
new file mode 100644
index 0000000..86f6897
--- /dev/null
+++ b/vendor/lpeglj/lpprint.lua
@@ -0,0 +1,356 @@
+--[[
+LPEGLJ
+lpprint.lua
+Tree, code and debug print function (only for debuging)
+Copyright (C) 2014 Rostislav Sacek.
+based on LPeg v1.0 - PEG pattern matching for Lua
+Lua.org & PUC-Rio written by Roberto Ierusalimschy
+http://www.inf.puc-rio.br/~roberto/lpeg/
+
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+--]]
+
+local ffi = require"ffi"
+local band, rshift, lshift = bit.band, bit.rshift, bit.lshift
+
+ffi.cdef[[
+ int isprint ( int c );
+]]
+
+local RuleLR = 0x10000
+local Ruleused = 0x20000
+
+-- {======================================================
+-- Printing patterns (for debugging)
+-- =======================================================
+
+local TChar = 0
+local TSet = 1
+local TAny = 2 -- standard PEG elements
+local TTrue = 3
+local TFalse = 4
+local TRep = 5
+local TSeq = 6
+local TChoice = 7
+local TNot = 8
+local TAnd = 9
+local TCall = 10
+local TOpenCall = 11
+local TRule = 12 -- sib1 is rule's pattern, sib2 is 'next' rule
+local TGrammar = 13 -- sib1 is initial (and first) rule
+local TBehind = 14 -- match behind
+local TCapture = 15 -- regular capture
+local TRunTime = 16 -- run-time capture
+
+local IAny = 0 -- if no char, fail
+local IChar = 1 -- if char != aux, fail
+local ISet = 2 -- if char not in val, fail
+local ITestAny = 3 -- in no char, jump to 'offset'
+local ITestChar = 4 -- if char != aux, jump to 'offset'
+local ITestSet = 5 -- if char not in val, jump to 'offset'
+local ISpan = 6 -- read a span of chars in val
+local IBehind = 7 -- walk back 'aux' characters (fail if not possible)
+local IRet = 8 -- return from a rule
+local IEnd = 9 -- end of pattern
+local IChoice = 10 -- stack a choice; next fail will jump to 'offset'
+local IJmp = 11 -- jump to 'offset'
+local ICall = 12 -- call rule at 'offset'
+local IOpenCall = 13 -- call rule number 'offset' (must be closed to a ICall)
+local ICommit = 14 -- pop choice and jump to 'offset'
+local IPartialCommit = 15 -- update top choice to current position and jump
+local IBackCommit = 16 -- "fails" but jump to its own 'offset'
+local IFailTwice = 17 -- pop one choice and then fail
+local IFail = 18 -- go back to saved state on choice and jump to saved offset
+local IGiveup = 19 -- internal use
+local IFullCapture = 20 -- complete capture of last 'off' chars
+local IOpenCapture = 21 -- start a capture
+local ICloseCapture = 22
+local ICloseRunTime = 23
+
+local Cclose = 0
+local Cposition = 1
+local Cconst = 2
+local Cbackref = 3
+local Carg = 4
+local Csimple = 5
+local Ctable = 6
+local Cfunction = 7
+local Cquery = 8
+local Cstring = 9
+local Cnum = 10
+local Csubst = 11
+local Cfold = 12
+local Cruntime = 13
+local Cgroup = 14
+
+
+-- number of siblings for each tree
+local numsiblings = {
+ [TRep] = 1,
+ [TSeq] = 2,
+ [TChoice] = 2,
+ [TNot] = 1,
+ [TAnd] = 1,
+ [TRule] = 2,
+ [TGrammar] = 1,
+ [TBehind] = 1,
+ [TCapture] = 1,
+ [TRunTime] = 1,
+}
+local names = {
+ [IAny] = "any",
+ [IChar] = "char",
+ [ISet] = "set",
+ [ITestAny] = "testany",
+ [ITestChar] = "testchar",
+ [ITestSet] = "testset",
+ [ISpan] = "span",
+ [IBehind] = "behind",
+ [IRet] = "ret",
+ [IEnd] = "end",
+ [IChoice] = "choice",
+ [IJmp] = "jmp",
+ [ICall] = "call",
+ [IOpenCall] = "open_call",
+ [ICommit] = "commit",
+ [IPartialCommit] = "partial_commit",
+ [IBackCommit] = "back_commit",
+ [IFailTwice] = "failtwice",
+ [IFail] = "fail",
+ [IGiveup] = "giveup",
+ [IFullCapture] = "fullcapture",
+ [IOpenCapture] = "opencapture",
+ [ICloseCapture] = "closecapture",
+ [ICloseRunTime] = "closeruntime"
+}
+
+local function printcharset(st)
+ io.write("[");
+ local i = 0
+ while i <= 255 do
+ local first = i;
+ while band(st[rshift(i, 5)], lshift(1, band(i, 31))) ~= 0 and i <= 255 do
+ i = i + 1
+ end
+ if i - 1 == first then -- unary range?
+ io.write(("(%02x)"):format(first))
+ elseif i - 1 > first then -- non-empty range?
+ io.write(("(%02x-%02x)"):format(first, i - 1))
+ end
+ i = i + 1
+ end
+ io.write("]")
+end
+
+local modes = {
+ [Cclose] = "close",
+ [Cposition] = "position",
+ [Cconst] = "constant",
+ [Cbackref] = "backref",
+ [Carg] = "argument",
+ [Csimple] = "simple",
+ [Ctable] = "table",
+ [Cfunction] = "function",
+ [Cquery] = "query",
+ [Cstring] = "string",
+ [Cnum] = "num",
+ [Csubst] = "substitution",
+ [Cfold] = "fold",
+ [Cruntime] = "runtime",
+ [Cgroup] = "group"
+}
+
+local function printcapkind(kind)
+ io.write(("%s"):format(modes[kind]))
+end
+
+local function printjmp(p, index)
+ io.write(("-> %d"):format(index + p[index].offset))
+end
+
+local function printrulename(p, index, rulenames)
+ if rulenames and rulenames[index + p[index].offset] then
+ io.write(' ', rulenames[index + p[index].offset])
+ end
+end
+
+local function printinst(p, index, valuetable, rulenames)
+ local code = p[index].code
+ if rulenames and rulenames[index] then
+ io.write(rulenames[index], '\n')
+ end
+ io.write(("%04d: %s "):format(index, names[code]))
+ if code == IChar then
+ io.write(("'%s'"):format(string.char(p[index].val)))
+ elseif code == ITestChar then
+ io.write(("'%s'"):format(string.char(p[index].val)))
+ printjmp(p, index)
+ printrulename(p, index, rulenames)
+ elseif code == IFullCapture then
+ printcapkind(band(p[index].val, 0x0f));
+ io.write((" (size = %d) (idx = %s)"):format(band(rshift(p[index].val, 4), 0xF), tostring(valuetable[p[index].offset])))
+ elseif code == IOpenCapture then
+ printcapkind(band(p[index].val, 0x0f))
+ io.write((" (idx = %s)"):format(tostring(valuetable[p[index].offset])))
+ elseif code == ISet then
+ printcharset(valuetable[p[index].val]);
+ elseif code == ITestSet then
+ printcharset(valuetable[p[index].val])
+ printjmp(p, index);
+ printrulename(p, index, rulenames)
+ elseif code == ISpan then
+ printcharset(valuetable[p[index].val]);
+ elseif code == IOpenCall then
+ io.write(("-> %d"):format(p[index].offset))
+ elseif code == IBehind then
+ io.write(("%d"):format(p[index].val))
+ elseif code == IJmp or code == ICall or code == ICommit or code == IChoice or
+ code == IPartialCommit or code == IBackCommit or code == ITestAny then
+ printjmp(p, index);
+ if (code == ICall or code == IJmp) and p[index].aux > 0 then
+ io.write(' ', valuetable[p[index].aux])
+ else
+ printrulename(p, index, rulenames)
+ end
+ end
+ io.write("\n")
+end
+
+
+local function printpatt(p, valuetable)
+ local ruleNames = {}
+ for i = 0, p.size - 1 do
+ local code = p.p[i].code
+ if (code == ICall or code == IJmp) and p.p[i].aux > 0 then
+ local index = i + p.p[i].offset
+ ruleNames[index] = valuetable[p.p[i].aux]
+ end
+ end
+ for i = 0, p.size - 1 do
+ printinst(p.p, i, valuetable, ruleNames)
+ end
+end
+
+
+local function printcap(cap, index, valuetable)
+ printcapkind(cap[index].kind)
+ io.write((" (idx: %s - size: %d) -> %d\n"):format(valuetable[cap[index].idx], cap[index].siz, cap[index].s))
+end
+
+
+local function printcaplist(cap, limit, valuetable)
+ io.write(">======\n")
+ local index = 0
+ while cap[index].s and index < limit do
+ printcap(cap, index, valuetable)
+ index = index + 1
+ end
+ io.write("=======\n")
+end
+
+-- ======================================================
+
+
+
+-- {======================================================
+-- Printing trees (for debugging)
+-- =======================================================
+
+local tagnames = {
+ [TChar] = "char",
+ [TSet] = "set",
+ [TAny] = "any",
+ [TTrue] = "true",
+ [TFalse] = "false",
+ [TRep] = "rep",
+ [TSeq] = "seq",
+ [TChoice] = "choice",
+ [TNot] = "not",
+ [TAnd] = "and",
+ [TCall] = "call",
+ [TOpenCall] = "opencall",
+ [TRule] = "rule",
+ [TGrammar] = "grammar",
+ [TBehind] = "behind",
+ [TCapture] = "capture",
+ [TRunTime] = "run-time"
+}
+
+
+local function printtree(tree, ident, index, valuetable)
+ for i = 1, ident do
+ io.write(" ")
+ end
+ local tag = tree[index].tag
+ io.write(("%s"):format(tagnames[tag]))
+ if tag == TChar then
+ local c = tree[index].val
+ if ffi.C.isprint(c) then
+ io.write((" '%c'\n"):format(c))
+ else
+ io.write((" (%02X)\n"):format(c))
+ end
+ elseif tag == TSet then
+ printcharset(valuetable[tree[index].val]);
+ io.write("\n")
+ elseif tag == TOpenCall or tag == TCall then
+ io.write((" key: %s\n"):format(tostring(valuetable[tree[index].val])))
+ elseif tag == TBehind then
+ io.write((" %d\n"):format(tree[index].val))
+ printtree(tree, ident + 2, index + 1, valuetable);
+ elseif tag == TCapture then
+ io.write((" cap: %s n: %s\n"):format(modes[bit.band(tree[index].cap, 0xffff)], valuetable[tree[index].val]))
+ printtree(tree, ident + 2, index + 1, valuetable);
+ elseif tag == TRule then
+ local extra = bit.band(tree[index].cap, RuleLR) == RuleLR and ' left recursive' or ''
+ extra = extra .. (bit.band(tree[index].cap, Ruleused) ~= Ruleused and ' not used' or '')
+ io.write((" n: %d key: %s%s\n"):format(bit.band(tree[index].cap, 0xffff) - 1, valuetable[tree[index].val], extra))
+ printtree(tree, ident + 2, index + 1, valuetable);
+ -- do not print next rule as a sibling
+ elseif tag == TGrammar then
+ local ruleindex = index + 1
+ io.write((" %d\n"):format(tree[index].val)) -- number of rules
+ for i = 1, tree[index].val do
+ printtree(tree, ident + 2, ruleindex, valuetable);
+ ruleindex = ruleindex + tree[ruleindex].ps
+ end
+ assert(tree[ruleindex].tag == TTrue); -- sentinel
+ else
+ local sibs = numsiblings[tree[index].tag] or 0
+ io.write("\n")
+ if sibs >= 1 then
+ printtree(tree, ident + 2, index + 1, valuetable);
+ if sibs >= 2 then
+ printtree(tree, ident + 2, index + tree[index].ps, valuetable)
+ end
+ end
+ end
+end
+
+-- }====================================================== */
+
+return {
+ printtree = printtree,
+ printpatt = printpatt,
+ printcaplist = printcaplist,
+ printinst = printinst
+} \ No newline at end of file