From 5871a659d3436cfd7ed813bd317036d9b45e2e90 Mon Sep 17 00:00:00 2001 From: Alexander Pickering Date: Sat, 20 Aug 2016 01:36:47 -0400 Subject: A halfway commit in case anyone from facepunch comes looking --- src/amalg.cache | 3 -- src/glum.lua | 113 +++++++++++++++++++++++++++++++++++++++----------------- src/parser.lua | 66 +++++++++++++++++---------------- src/scope.lua | 2 +- src/test.lua | 32 ++++++++++++++++ 5 files changed, 148 insertions(+), 68 deletions(-) delete mode 100644 src/amalg.cache create mode 100644 src/test.lua (limited to 'src') diff --git a/src/amalg.cache b/src/amalg.cache deleted file mode 100644 index de81b62..0000000 --- a/src/amalg.cache +++ /dev/null @@ -1,3 +0,0 @@ -return { - [ "lpeg" ] = "C", -} diff --git a/src/glum.lua b/src/glum.lua index ff05953..a50382a 100644 --- a/src/glum.lua +++ b/src/glum.lua @@ -12,27 +12,39 @@ This moudle allows you to minify gLua code Dependencies: lua-parser ]] + +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) local glum = {} ---- Creates a deep copy of a table. --- Creates a deep copy, will even copy metamethods. --- @tab orig the original table to copy --- @return a copy of the table -local function deepcopy(orig) end --Creates a deep copy of a table - -local function getnextvarname(latname) end --generates the next valid variable name from the last valid variable name. - -local function printtable(tbl) end --A debugging function, a replacement for glua PrintTable - -local function stringfor(ast,tbl) end --Returns the string for the given abstract syntax tree, within the scope of tbl - -local function removespaces(string) end --Removes extra spaces and semicolons in string - - --Creates a deep copy of a table local function deepcopy(orig) local orig_type = type(orig) @@ -91,10 +103,19 @@ local function printtable(tbl, tabset) end end +local syntax = {} + +local function stringfor(ast,tbl) + if syntax[ast.tag] ~= nil then + return syntax[ast.tag](ast,tbl) + else + 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. -local syntax = { +syntax = { ["Call"] = function(ast,tbl) local exprname = stringfor(ast[1],tbl) local argnames = {} @@ -129,10 +150,33 @@ local syntax = { end, ["String"] = function(ast,tbl) 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 + tbl.strings[ast[1] ] = nextvar return nextvar + ]] end return tbl.strings[ast[1]] end, @@ -267,17 +311,17 @@ local syntax = { ["mod"] = "%", ["pow"] = "^", } local uniop = { - ["len"] = "#", ["not"] = "not", + ["len"] = "#", ["not"] = " not ", ["unm"] = "-", ["bnot"] = "~", } local opname = ast[1] if uniop[opname] ~= nil then local rhs = stringfor(ast[2],tbl) - return optbl[opname] .. rhs + return uniop[opname] .. rhs end local lhs = stringfor(ast[2],tbl) local rhs = stringfor(ast[3],tbl) - local output = table.concat(lhs,binop[opname],rhs) + local output = table.concat({lhs,binop[opname],rhs}) return output end, ["Pair"] = function(ast,tbl) @@ -317,12 +361,14 @@ local syntax = { end, ["Set"] = function(ast,tbl) local lhs = {} + local a1 = ast[1].tag ~= nil and ast[1] or ast[1][1] for k = 1,#ast[1] do - lhs[#lhs + 1] = stringfor(ast[1],tbl) + lhs[#lhs + 1] = stringfor(a1,tbl) end local rhs = {} + local a2 = ast[2].tag ~= nil and ast[2] or ast[2][1] for k = 1,#ast[2] do - rhs[#rhs + 1] = stringfor(ast[2],tbl) + rhs[#rhs + 1] = stringfor(a2,tbl) end local ostring = table.concat(lhs,",") ostring = ostring .. "=" .. table.concat(rhs,",") @@ -345,7 +391,7 @@ local syntax = { return " goto " .. tbl.nids[ast[1]] end, ["Function"] = function(ast,tbl) - local funcargs = stringfor(ast[1],tbl) + local funcargs = ast[1].tag ~= nil and stringfor(ast[1],tbl) or "" local code = stringfor(ast[2],tbl) return table.concat({" function(",funcargs,")",code," end "}) end, @@ -359,7 +405,7 @@ local syntax = { tbl.ids[ast[1][1][1]] = newvar ident = newvar end - local argstr = stringfor(ast[2][1][1],tbl) + local argstr = ast[2][1][1].tag ~= nil and stringfor(ast[2][1][1],tbl) or "" local expr = stringfor(ast[2][1][2],tbl) return table.concat({" local function ",ident,"(",argstr,")",expr," end "}) end, @@ -369,7 +415,7 @@ local syntax = { ["While"] = function(ast,tbl) local expr = stringfor(ast[1],tbl) local block = stringfor(ast[2],tbl) - local output = table.concat(" while " , expr , " do " , block , " end ") + local output = table.concat({" while " , expr , " do " , block , " end "}) return output end, ["Break"] = function(ast,tbl) @@ -400,13 +446,7 @@ local syntax = { end, } -local function stringfor(ast,tbl) - if syntax[ast.tag] ~= nil then - return syntax[ast.tag](ast,tbl) - else - error("Attempted to use unknown tag type:" .. ast.tag) - end -end + --Removes extra spaces and duplicated ; from a string local function removespaces(str) @@ -427,7 +467,13 @@ local function removespaces(str) return str end +--Compress the string, and adds a little decompression code at the top. +local function compress(str) + +end + glum.minify = function(str, name) + name = name or "anonymous" local ast, error_msg = parser.parse(str, name) if not ast then error(error_msg) @@ -438,7 +484,8 @@ glum.minify = function(str, name) ["lname"] = "", ["nids"] = {}, } - return removespaces(stringfor(ast,localvar)) + --printtable(ast) + return --[[removespaces(]]stringfor(ast,localvar)--) end return glum diff --git a/src/parser.lua b/src/parser.lua index c36baf3..ffcca71 100644 --- a/src/parser.lua +++ b/src/parser.lua @@ -130,6 +130,26 @@ local function updateffp (name) return Cmt(Carg(1) * Cc(name), setffp) end +--Fixes strings +local function fix_str (str) + --print("I need to fix string:" .. str) + --print("attempt:" .. string.format("%q",str)) + str = string.gsub(str, "\\a", "\a") + str = string.gsub(str, "\\b", "\b") + str = string.gsub(str, "\\f", "\f") + str = string.gsub(str, "\\n", "\n") + str = string.gsub(str, "\\r", "\r") + str = string.gsub(str, "\\t", "\t") + str = string.gsub(str, "\\v", "\v") + str = string.gsub(str, "\\\n", "\n") + str = string.gsub(str, "\\\r", "\n") + str = string.gsub(str, "\\'", "'") + str = string.gsub(str, '\\"', '"') + str = string.gsub(str, '\\\\', '\\') + --print("actual:" .. str) + return str +end + -- regular combinators and auxiliary functions local function token (pat, name) @@ -192,33 +212,17 @@ local function chainl1 (pat, sep) end local function sepby (pat, sep, tag) - return taggedCap(tag, (pat * (sep * pat)^0)^-1) + return taggedCap(tag, (pat * (sep * pat)^0)^(-1)) end local function sepby1 (pat, sep, tag) return taggedCap(tag, pat * (sep * pat)^0) end -local function fix_str (str) - str = string.gsub(str, "\\a", "\a") - str = string.gsub(str, "\\b", "\b") - str = string.gsub(str, "\\f", "\f") - str = string.gsub(str, "\\n", "\n") - str = string.gsub(str, "\\r", "\r") - str = string.gsub(str, "\\t", "\t") - str = string.gsub(str, "\\v", "\v") - str = string.gsub(str, "\\\n", "\n") - str = string.gsub(str, "\\\r", "\n") - str = string.gsub(str, "\\'", "'") - str = string.gsub(str, '\\"', '"') - str = string.gsub(str, '\\\\', '\\') - return str -end - -- grammar local G = { V"Lua", - Lua = V"Shebang"^-1 * V"Skip" * V"Chunk" * -1 + report_error(); + Lua = V"Shebang"^(-1) * V"Skip" * V"Chunk" * -1 + report_error(); -- parser Chunk = V"Block"; StatList = (symb(";") + V"Stat")^0; @@ -229,11 +233,11 @@ local G = { V"Lua", Field = taggedCap("Pair", (symb("[") * V"Expr" * symb("]") * symb("=") * V"Expr") + (taggedCap("String", token(V"Name", "Name")) * symb("=") * V"Expr")) + V"Expr"; - FieldList = (V"Field" * (V"FieldSep" * V"Field")^0 * V"FieldSep"^-1)^-1; + FieldList = (V"Field" * (V"FieldSep" * V"Field")^0 * V"FieldSep"^(-1))^(-1); Constructor = taggedCap("Table", symb("{") * V"FieldList" * symb("}")); NameList = sepby1(V"Id", symb(","), "NameList"); ExpList = sepby1(V"Expr", symb(","), "ExpList"); - FuncArgs = symb("(") * (V"Expr" * (symb(",") * V"Expr")^0)^-1 * symb(")") + + FuncArgs = symb("(") * (V"Expr" * (symb(",") * V"Expr")^0)^(-1) * symb(")") + V"Constructor" + taggedCap("String", token(V"String", "String")); Expr = V"SubExpr_1"; @@ -250,7 +254,7 @@ local G = { V"Lua", SubExpr_10 = chainl1(V"SubExpr_11", V"MulOp"); SubExpr_11 = V"UnOp" * V"SubExpr_11" / unaryop + V"SubExpr_12"; - SubExpr_12 = V"SimpleExp" * (V"PowOp" * V"SubExpr_11")^-1 / binaryop; + SubExpr_12 = V"SimpleExp" * (V"PowOp" * V"SubExpr_11")^(-1) / binaryop; SimpleExp = taggedCap("Number", token(V"Number", "Number")) + taggedCap("String", token(V"String", "String")) + taggedCap("Nil", kw("nil")) + @@ -281,11 +285,11 @@ local G = { V"Lua", end); PrimaryExp = V"Var" + taggedCap("Paren", symb("(") * V"Expr" * symb(")")); - Block = taggedCap("Block", V"StatList" * V"RetStat"^-1); + Block = taggedCap("Block", V"StatList" * V"RetStat"^(-1)); IfStat = taggedCap("If", kw("if") * V"Expr" * kw("then") * V"Block" * (kw("elseif") * V"Expr" * kw("then") * V"Block")^0 * - (kw("else") * V"Block")^-1 * + (kw("else") * V"Block")^(-1) * kw("end")); WhileStat = taggedCap("While", kw("while") * V"Expr" * kw("do") * V"Block" * kw("end")); @@ -297,7 +301,7 @@ local G = { V"Lua", ForBody = kw("do") * V"Block"; ForNum = taggedCap("Fornum", V"Id" * symb("=") * V"Expr" * symb(",") * - V"Expr" * (symb(",") * V"Expr")^-1 * + V"Expr" * (symb(",") * V"Expr")^(-1) * V"ForBody"); ForGen = taggedCap("Forin", V"NameList" * kw("in") * V"ExpList" * V"ForBody"); ForStat = kw("for") * (V"ForNum" + V"ForGen") * kw("end"); @@ -309,14 +313,14 @@ local G = { V"Lua", return {tag = "Index", pos = t1.pos, [1] = t1, [2] = t2} end return t1 - end) * (symb(":") * taggedCap("String", token(V"Name", "Name")))^-1 / + end) * (symb(":") * taggedCap("String", token(V"Name", "Name")))^(-1) / function (t1, t2) if t2 then return {tag = "Index", pos = t1.pos, is_method = true, [1] = t1, [2] = t2} end return t1 end; - ParList = V"NameList" * (symb(",") * symb("...") * taggedCap("Dots", Cp()))^-1 / + ParList = V"NameList" * (symb(",") * symb("...") * taggedCap("Dots", Cp()))^(-1) / function (t, v) if v then table.insert(t, v) end return t @@ -349,7 +353,7 @@ local G = { V"Lua", BreakStat = taggedCap("Break", kw("break")); ContinueStat = taggedCap("Continue", kw("continue")); GoToStat = taggedCap("Goto", kw("goto") * token(V"Name", "Name")); - RetStat = taggedCap("Return", kw("return") * (V"Expr" * (symb(",") * V"Expr")^0)^-1 * symb(";")^-1); + RetStat = taggedCap("Return", kw("return") * (V"Expr" * (symb(",") * V"Expr")^0)^(-1) * symb(";")^(-1)); ExprStat = Cmt( (V"SuffixedExp" * (Cc(function (...) @@ -379,14 +383,14 @@ local G = { V"Lua", return false end))) , function (s, i, s1, f, ...) return f(s1, ...) end); - Assignment = ((symb(",") * V"SuffixedExp")^1)^-1 * symb("=") * V"ExpList"; + Assignment = ((symb(",") * V"SuffixedExp")^1)^(-1) * symb("=") * V"ExpList"; Stat = V"IfStat" + V"WhileStat" + V"DoStat" + V"ForStat" + V"RepeatStat" + V"FuncStat" + V"LocalStat" + V"LabelStat" + V"BreakStat" + V"GoToStat" + V"ExprStat" + V"ContinueStat"; -- lexer Space = space^1; Equals = P"="^0; - Open = "[" * Cg(V"Equals", "init") * "[" * P"\n"^-1; + Open = "[" * Cg(V"Equals", "init") * "[" * P"\n"^(-1); Close = "]" * C(V"Equals") * "]"; CloseEQ = Cmt(V"Close" * Cb("init"), function (s, i, a, b) return a == b end); @@ -407,9 +411,9 @@ local G = { V"Lua", Identifier = V"idStart" * V"idRest"^0; Name = -V"Reserved" * C(V"Identifier") * -V"idRest"; Hex = (P("0x") + P("0X")) * xdigit^1; - Expo = S("eE") * S("+-")^-1 * digit^1; + Expo = S("eE") * S("+-")^(-1) * digit^1; Float = (((digit^1 * P(".") * digit^0) + - (P(".") * digit^1)) * V"Expo"^-1) + + (P(".") * digit^1)) * V"Expo"^(-1)) + (digit^1 * V"Expo"); Int = digit^1; Number = C(V"Hex" + V"Float" + V"Int") / diff --git a/src/scope.lua b/src/scope.lua index dd19392..b5fd3c6 100644 --- a/src/scope.lua +++ b/src/scope.lua @@ -1,5 +1,5 @@ --[[ -This module implements functions that handle scoping rules +This module implements functions that handle scoping rules ]] local scope = {} diff --git a/src/test.lua b/src/test.lua new file mode 100644 index 0000000..68de568 --- /dev/null +++ b/src/test.lua @@ -0,0 +1,32 @@ + local function a(b) + b=string.gsub(b,"\\","\\\\"); + b=string.gsub(b,"\a","\\\a"); + b=string.gsub(b,"\b","\\\b"); + b=string.gsub(b,"\f","\\\f"); + b=string.gsub(b,"\n","\n"); + b=string.gsub(b,"\r","\n"); + b=string.gsub(b,"\t","\\\t"); + b=string.gsub(b,"\v","\\\v"); + b=string.gsub(b,"\'","\\\'"); + b=string.gsub(b,"\"","\\\""); + return b +end +local function c(b) + b=string.gsub(b,"\\\a","\a"); + b=string.gsub(b,"\\\b","\b"); + b=string.gsub(b,"\\\f","\f"); + b=string.gsub(b,"\n","\n"); + b=string.gsub(b,"\n","\r"); + b=string.gsub(b,"\\\t","\t"); + b=string.gsub(b,"\\\v","\v"); + b=string.gsub(b,"\\\n","\n"); + b=string.gsub(b,"\\\n","\n"); + b=string.gsub(b,"\\\'","\'"); + b=string.gsub(b,"\\\"","\""); + b=string.gsub(b,"\\\\","\\"); + return b +end +local d= function() + local d={}; + local e=require("lpeg"); + local f= function()local f={};f.lineno= function(g,h) if h==1 then return 1,1 end local i,j=0,"";g=g["sub"](g,1,h).."\n"; for k in g["gmatch"](g,"[^\n]*[\n]") do i=i+1;j=k; end local k=j["len"](j,)-1; return i, not k==0 and k or 1 end ;f.new_scope= function(i) if not i.scope then i.scope=0; else i.scope=i.scope+1; end local f=i.scope;i.maxscope=f;i[f]={};i[f].label={};i[f].local={};i[f].goto={}; end ;f.begin_scope= function(i)i.scope=i.scope+1; end ;f.end_scope= function(i)i.scope=i.scope-1; end ;f.new_function= function(i) if not i.fscope then i.fscope=0; else i.fscope=i.fscope+1; end local j=i.fscope;i.function[j]={}; end ;f.begin_function= function(i)i.fscope=i.fscope+1; end ;f.end_function= function(i)i.fscope=i.fscope-1; end ;f.begin_loop= function(i) if not i.loop then i.loop=1; else i.loop=i.loop+1; end end ;f.end_loop= function(i)i.loop=i.loop-1; end ;f.insideloop= function(i) return i.loop and 0=")/"ge"+ba("<")/"lt"+ba(">")/"gt"+ba("!=")/"ne",["BOrOp"]=ba("|")/"bor",["BXorOp"]=ba("~")/"bxor",["BAndOp"]=ba("&")/"band",["ShiftOp"]=ba("<<")/"shl"+ba(">>")/"shr",["ConOp"]=ba("..")/"concat",["AddOp"]=ba("+")/"add"+ba("-")/"sub",["MulOp"]=ba("*")/"mul"+ba("/")/"div"+ba("%")/"mod",["UnOp"]=ca("not")/"not"+ba("-")/"unm"+ba("#")/"len"+ba("~")/"bnot"+ba("!")/"not",["PowOp"]=ba("^")/"pow",["Shebang"]=g("#")*(g(1)-g("\n"))^0*g("\n"),["OneWord"]=i("Name")+i("Number")+i("String")+i("Reserved")+g("...")+g(1)}; local function za(Aa,f,Ba)local Ca=Ba[1]; for P=f,0,-1 do if Aa[P].label[Ca] then return true end end return false end local function Ca(Aa,Da,M)local f=Aa.scope;local Ea=Aa[f].label[Da]; if not Ea then Aa[f].label[Da]={["name"]=Da,["pos"]=M}; return true else local N="label \'%s\' already defined at line %d";local Fa=x(Aa.errorinfo.subject,Ea.pos);N=string.format(N,Da,Fa); return nil,K(Aa.errorinfo,M,N) end end local function Ea(Aa,Ba)local f=Aa.scope;table.insert(Aa[f].goto,Ba) return true end local function Fa(Aa) for P=Aa.maxscope,0,-1 do for Ga,ua in ipairs(Aa[P].goto) do if not za(Aa,P,ua) then local N="no visible label \'%s\' for ";N=string.format(N,ua[1]); return nil,K(Aa.errorinfo,ua.pos,N) end end end return true end local function Ga(Aa,Ha)Aa.function[Aa.fscope].is_vararg=Ha; end local Ia,Ja,Kalocal La,Ma,Na,OaOa= function(Aa,Pa)local Qa=#Pa;local Ha=false; if 0