From 25af93b5d1281e7a0f8d8869c5bff0a2ce8cf1bf Mon Sep 17 00:00:00 2001 From: Alexander Pickering Date: Mon, 22 Aug 2016 14:32:38 -0400 Subject: Completed minifier, created+completed uglifier --- src/glum.lua | 162 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 67 deletions(-) (limited to 'src/glum.lua') diff --git a/src/glum.lua b/src/glum.lua index a50382a..7ee37b6 100644 --- a/src/glum.lua +++ b/src/glum.lua @@ -11,34 +11,9 @@ This moudle allows you to minify gLua code print(x.minify(str)) Dependencies: lua-parser + lpeg ]] -local strreps = { - ["\\"] = "\\\\", - ["\a"] = "\\a", - ["\b"] = "\\b", - ["\f"] = "\\f", - ["\n"] = "\\n", - ["\r"] = "\\r", - ["\t"] = "\\t", - ["\v"] = "\\v", - ["\""] = "\\\"" -} -local function safe_str (str) - local tep = {} - --print("--------------Safeing str:" .. str) - for c in str:gmatch(".") do - if strreps[c] ~= nil then - --print(string.format("safeing %s:%s",c,strreps[c])) - end - tep[#tep + 1] = strreps[c] or c - end - local output = table.concat(tep) - --print("-------------Returning string:" .. output) - return output -end - - local parser = dofile("../src/parser.lua") local lpeg = require("lpeg") lpeg.locale(lpeg) @@ -109,12 +84,16 @@ local function stringfor(ast,tbl) if syntax[ast.tag] ~= nil then return syntax[ast.tag](ast,tbl) else + print("Valid tags are:") + for k,v in pairs(syntax) do + print(k) + end error("Attempted to use unknown tag type:" .. ast.tag) end end --Abandon all hope, ye who enter here --Refer to the comments at the top of parser.lua for what each function should do. ---If willox ever decides to add new language features, they need to be added to BOTH parser.lua and here. +--If anyone ever decides to add new language features, they need to be added to BOTH parser.lua and here. syntax = { ["Call"] = function(ast,tbl) local exprname = stringfor(ast[1],tbl) @@ -139,45 +118,24 @@ syntax = { --A short hand if it's a simple thing if ast[2].tag == "String" and #ast[2][1] < (#func + 2) then inv = ast[2][1] - output = output .. ":" .. inv .. "(" + output = table.concat({output, ":", inv, "("}) else inv = stringfor(ast[2],tbl) - output = output .. "[" .. inv .. "](" .. func .. "," + output = table.concat({output, "[", inv, "](", func, ","}) end - output = output .. table.concat(invargs,",") - output = output .. ")" + output = output .. table.concat(invargs,",") .. ")" return output end, ["String"] = function(ast,tbl) + local sop,eop = "\"","\"" if tbl.strings[ast[1]] == nil then - local fsstr = safe_str(ast[1]) - local fstr = string.format("\"%s\"",fsstr) - --fstr = safe_str(fstr) - --local lstr = string.format("return %q",ast[1]) - print("Loading string:" .. fstr) - local rstring = loadstring("return " .. fstr) - --print("Returning string:") - --print(ast[1]) - --print("fsstr") - --print(fsstr) - --print("formated:") - --print(string.format("%q",ast[1])) - local rstrs = rstring() - --assert(rstrs == ast[1],string.format("%q is not equal to %q",rstrs,ast[1])) - --print(string.format("%q is equal to %s:%s", rstrs, ast[1],fsstr)) - --print("Returning " .. fstr .. " from " .. ast[1] .. " out of " .. fsstr) - return fstr - --return string.format("%q",ast[1]) - --return safe_str(string.format("%q",ast[1])) - --return string.format("%q",safe_str(ast[1])) - --[[ - if #ast[1] < 4 then return "\""..ast[1].."\"" end - local nextvar = getnextvarname(tbl.lname) - tbl.lname = nextvar - tbl.strings[ast[1] ] = nextvar - return nextvar - ]] + if string.find(ast[1],"\"") then + sop = "[[" + eop = "]]" + end + return table.concat({sop,ast[1],eop}) end + print("Returning non-catated string") return tbl.strings[ast[1]] end, ["Id"] = function(ast,tbl) @@ -194,7 +152,7 @@ syntax = { return table.concat({globalvar, "[", stringfor(ast[2],tbl), "]"}) end, ["Paren"] = function(ast,tbl) - return table.concat({"(" .. stringfor(ast[1],tbl) .. ")"}) + return table.concat({"(",stringfor(ast[1],tbl),")"}) end, ["Dots"] = function(ast,tbl) return "..." @@ -229,18 +187,18 @@ syntax = { ["ExpList"] = function(ast,tbl) local exprs = {} for k = 1,#ast do - exprs[#exprs + 1] = stringfor(ast[k],tbl) + exprs[k] = stringfor(ast[k],tbl) end return table.concat(exprs,",") end, ["Nil"] = function(ast,tbl) - return "nil" + return " nil " end, ["True"] = function(ast,tbl) - return "true" + return " true " end, ["False"] = function(ast,tbl) - return "false" + return " false " end, ["Return"] = function(ast,tbl) local retargs = {} @@ -316,6 +274,12 @@ syntax = { } local opname = ast[1] if uniop[opname] ~= nil then + --Some special case where the parser messes up, fix it here. + --It translates ~= into not ==, but the order of operations makes it so == is evaluated first, and not second. + if opname == "not" and ast[2]["tag"] == "Op" and ast[2][1] == "eq" then + ast[2][1] = "ne" + return stringfor(ast[2],tbl) + end local rhs = stringfor(ast[2],tbl) return uniop[opname] .. rhs end @@ -468,9 +432,9 @@ local function removespaces(str) end --Compress the string, and adds a little decompression code at the top. -local function compress(str) - -end +--local function compress(str) +-- +--end glum.minify = function(str, name) name = name or "anonymous" @@ -479,13 +443,77 @@ glum.minify = function(str, name) error(error_msg) end local localvar = { + ["numlocals"] = 0, ["strings"] = {}, ["ids"] = {}, ["lname"] = "", ["nids"] = {}, } --printtable(ast) - return --[[removespaces(]]stringfor(ast,localvar)--) + return stringfor(ast,localvar) +end + +glum.uglify = function(str) + local avalchars = {} + local capture_chars = {"%","(","[","\13"} + local skipchars = {} + for k,v in pairs(capture_chars) do skipchars[string.byte(v,1)] = true end + for k = 1, 128 do + if skipchars[k] then goto skip_loop end --Skip the % character + if string.find(str,string.char(k)) then + avalchars[k] = false + else + avalchars[k] = true + end + ::skip_loop:: + end + for k,v in pairs(skipchars) do + avalchars[k] = false + end + local prettifycode = [[ +local function p(s) + local r = { + %s + } + for k,v in pairs(r) do + s = s:gsub(v[2],v[1]) + end + return s +end +]] + local replacementtbl = {} + local cursor = 1 + for k,v in pairs(nonames) do + while not avalchars[cursor] do + cursor = cursor + 1 + end + replacementtbl[v] = cursor + avalchars[cursor] = false + end + assert(cursor < 128, "Unable to uglify file, not enough unused characters!") + local replacementstr = {} + for k,v in pairs(replacementtbl) do + local trs = string.format("{%q,%q}",k,string.char(v)) + replacementstr[#replacementstr + 1] = trs + end + local frepstr = table.concat(replacementstr,",") + local pcd = string.format(prettifycode,frepstr) + for k,v in pairs(replacementtbl) do + str = str:gsub(k,string.char(v)) + end + local numdeepcom = math.random(5) + 5 + return table.concat({ + pcd, + "\n", + "return assert(loadstring(p([", + string.rep("=",numdeepcom), + "[", + str, + "]", + string.rep("=",numdeepcom), + "])))()" + }) + --prettifycode = string.format(prettifycode,) end return glum -- cgit v1.2.3-70-g09d2