joebodo

sys.apis.minify.FormatMini.lua

Sep 6th, 2016
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.78 KB | None | 0 0
  1.  
  2. local parser = require'ParseLua'
  3. local ParseLua = parser.ParseLua
  4. local util = require'Util'
  5. local lookupify = util.lookupify
  6.  
  7. --
  8. -- FormatMini.lua
  9. --
  10. -- Returns the minified version of an AST. Operations which are performed:
  11. -- - All comments and whitespace are ignored
  12. -- - All local variables are renamed
  13. --
  14.  
  15. local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
  16.                              'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
  17.                              's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
  18. local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  19.                              'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
  20.                              'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
  21. local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
  22. local Symbols = lookupify{'+', '-', '*', '/', '^', '%', ',', '{', '}', '[', ']', '(', ')', ';', '#'}
  23.  
  24. local function Format_Mini(ast)
  25.     local formatStatlist, formatExpr;
  26.     local count = 0
  27.     --
  28.     local function joinStatementsSafe(a, b, sep)
  29.     --print(a, b)
  30.         if count > 150 then
  31.             count = 0
  32.             return a.."\n"..b
  33.         end
  34.         sep = sep or ' '
  35.         local aa, bb = a:sub(-1,-1), b:sub(1,1)
  36.         if UpperChars[aa] or LowerChars[aa] or aa == '_' then
  37.             if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then
  38.                 --bb is a symbol, can join without sep
  39.                 return a..b
  40.             elseif bb == '(' then
  41.                 print("==============>>>",aa,bb)
  42.                 --prevent ambiguous syntax
  43.                 return a..sep..b
  44.             else
  45.                 return a..sep..b
  46.             end
  47.         elseif Digits[aa] then
  48.             if bb == '(' then
  49.                 --can join statements directly
  50.                 return a..b
  51.             elseif Symbols[bb] then
  52.                 return a .. b
  53.             else
  54.                 return a..sep..b
  55.             end
  56.         elseif aa == '' then
  57.             return a..b
  58.         else
  59.             if bb == '(' then
  60.                 --don't want to accidentally call last statement, can't join directly
  61.                 return a..sep..b
  62.             else
  63.             --print("asdf", '"'..a..'"', '"'..b..'"')
  64.                 return a..b
  65.             end
  66.         end
  67.     end
  68.  
  69.     formatExpr = function(expr, precedence)
  70.         local precedence = precedence or 0
  71.         local currentPrecedence = 0
  72.         local skipParens = false
  73.         local out = ""
  74.         if expr.AstType == 'VarExpr' then
  75.             if expr.Variable then
  76.                 out = out..expr.Variable.Name
  77.             else
  78.                 out = out..expr.Name
  79.             end
  80.  
  81.         elseif expr.AstType == 'NumberExpr' then
  82.             out = out..expr.Value.Data
  83.  
  84.         elseif expr.AstType == 'StringExpr' then
  85.             out = out..expr.Value.Data
  86.  
  87.         elseif expr.AstType == 'BooleanExpr' then
  88.             out = out..tostring(expr.Value)
  89.  
  90.         elseif expr.AstType == 'NilExpr' then
  91.             out = joinStatementsSafe(out, "nil")
  92.  
  93.         elseif expr.AstType == 'BinopExpr' then
  94.             currentPrecedence = expr.OperatorPrecedence
  95.             out = joinStatementsSafe(out, formatExpr(expr.Lhs, currentPrecedence))
  96.             out = joinStatementsSafe(out, expr.Op)
  97.             out = joinStatementsSafe(out, formatExpr(expr.Rhs))
  98.             if expr.Op == '^' or expr.Op == '..' then
  99.                 currentPrecedence = currentPrecedence - 1
  100.             end
  101.            
  102.             if currentPrecedence < precedence then
  103.                 skipParens = false
  104.             else
  105.                 skipParens = true
  106.             end
  107.             --print(skipParens, precedence, currentPrecedence)
  108.         elseif expr.AstType == 'UnopExpr' then
  109.             out = joinStatementsSafe(out, expr.Op)
  110.             out = joinStatementsSafe(out, formatExpr(expr.Rhs))
  111.  
  112.         elseif expr.AstType == 'DotsExpr' then
  113.             out = out.."..."
  114.  
  115.         elseif expr.AstType == 'CallExpr' then
  116.             out = out..formatExpr(expr.Base)
  117.             out = out.."("
  118.             for i = 1, #expr.Arguments do
  119.                 out = out..formatExpr(expr.Arguments[i])
  120.                 if i ~= #expr.Arguments then
  121.                     out = out..","
  122.                 end
  123.             end
  124.             out = out..")"
  125.  
  126.         elseif expr.AstType == 'TableCallExpr' then
  127.             out = out..formatExpr(expr.Base)
  128.             out = out..formatExpr(expr.Arguments[1])
  129.  
  130.         elseif expr.AstType == 'StringCallExpr' then
  131.             out = out..formatExpr(expr.Base)
  132.             out = out..expr.Arguments[1].Data
  133.  
  134.         elseif expr.AstType == 'IndexExpr' then
  135.             out = out..formatExpr(expr.Base).."["..formatExpr(expr.Index).."]"
  136.  
  137.         elseif expr.AstType == 'MemberExpr' then
  138.             out = out..formatExpr(expr.Base)..expr.Indexer..expr.Ident.Data
  139.  
  140.         elseif expr.AstType == 'Function' then
  141.             expr.Scope:ObfuscateVariables()
  142.             out = out.."function("
  143.             if #expr.Arguments > 0 then
  144.                 for i = 1, #expr.Arguments do
  145.                     out = out..expr.Arguments[i].Name
  146.                     if i ~= #expr.Arguments then
  147.                         out = out..","
  148.                     elseif expr.VarArg then
  149.                         out = out..",..."
  150.                     end
  151.                 end
  152.             elseif expr.VarArg then
  153.                 out = out.."..."
  154.             end
  155.             out = out..")"
  156.             out = joinStatementsSafe(out, formatStatlist(expr.Body))
  157.             out = joinStatementsSafe(out, "end")
  158.  
  159.         elseif expr.AstType == 'ConstructorExpr' then
  160.             out = out.."{"
  161.             for i = 1, #expr.EntryList do
  162.                 local entry = expr.EntryList[i]
  163.                 if entry.Type == 'Key' then
  164.                     out = out.."["..formatExpr(entry.Key).."]="..formatExpr(entry.Value)
  165.                 elseif entry.Type == 'Value' then
  166.                     out = out..formatExpr(entry.Value)
  167.                 elseif entry.Type == 'KeyString' then
  168.                     out = out..entry.Key.."="..formatExpr(entry.Value)
  169.                 end
  170.                 if i ~= #expr.EntryList then
  171.                     out = out..","
  172.                 end
  173.             end
  174.             out = out.."}"
  175.  
  176.         elseif expr.AstType == 'Parentheses' then
  177.             out = out.."("..formatExpr(expr.Inner)..")"
  178.  
  179.         end
  180.         --print(">>", skipParens, expr.ParenCount, out)
  181.         if not skipParens then
  182.             --print("hehe")
  183.             out = string.rep('(', expr.ParenCount or 0) .. out
  184.             out = out .. string.rep(')', expr.ParenCount or 0)
  185.             --print("", out)
  186.         end
  187.         count = count + #out
  188.         return --[[print(out) or]] out
  189.     end
  190.  
  191.     local formatStatement = function(statement)
  192.         local out = ''
  193.         if statement.AstType == 'AssignmentStatement' then
  194.             for i = 1, #statement.Lhs do
  195.                 out = out..formatExpr(statement.Lhs[i])
  196.                 if i ~= #statement.Lhs then
  197.                     out = out..","
  198.                 end
  199.             end
  200.             if #statement.Rhs > 0 then
  201.                 out = out.."="
  202.                 for i = 1, #statement.Rhs do
  203.                     out = out..formatExpr(statement.Rhs[i])
  204.                     if i ~= #statement.Rhs then
  205.                         out = out..","
  206.                     end
  207.                 end
  208.             end
  209.  
  210.         elseif statement.AstType == 'CallStatement' then
  211.             out = formatExpr(statement.Expression)
  212.  
  213.         elseif statement.AstType == 'LocalStatement' then
  214.             out = out.."local "
  215.             for i = 1, #statement.LocalList do
  216.                 out = out..statement.LocalList[i].Name
  217.                 if i ~= #statement.LocalList then
  218.                     out = out..","
  219.                 end
  220.             end
  221.             if #statement.InitList > 0 then
  222.                 out = out.."="
  223.                 for i = 1, #statement.InitList do
  224.                     out = out..formatExpr(statement.InitList[i])
  225.                     if i ~= #statement.InitList then
  226.                         out = out..","
  227.                     end
  228.                 end
  229.             end
  230.  
  231.         elseif statement.AstType == 'IfStatement' then
  232.             out = joinStatementsSafe("if", formatExpr(statement.Clauses[1].Condition))
  233.             out = joinStatementsSafe(out, "then")
  234.             out = joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body))
  235.             for i = 2, #statement.Clauses do
  236.                 local st = statement.Clauses[i]
  237.                 if st.Condition then
  238.                     out = joinStatementsSafe(out, "elseif")
  239.                     out = joinStatementsSafe(out, formatExpr(st.Condition))
  240.                     out = joinStatementsSafe(out, "then")
  241.                 else
  242.                     out = joinStatementsSafe(out, "else")
  243.                 end
  244.                 out = joinStatementsSafe(out, formatStatlist(st.Body))
  245.             end
  246.             out = joinStatementsSafe(out, "end")
  247.  
  248.         elseif statement.AstType == 'WhileStatement' then
  249.             out = joinStatementsSafe("while", formatExpr(statement.Condition))
  250.             out = joinStatementsSafe(out, "do")
  251.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  252.             out = joinStatementsSafe(out, "end")
  253.  
  254.         elseif statement.AstType == 'DoStatement' then
  255.             out = joinStatementsSafe(out, "do")
  256.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  257.             out = joinStatementsSafe(out, "end")
  258.  
  259.         elseif statement.AstType == 'ReturnStatement' then
  260.             out = "return"
  261.             for i = 1, #statement.Arguments do
  262.                 out = joinStatementsSafe(out, formatExpr(statement.Arguments[i]))
  263.                 if i ~= #statement.Arguments then
  264.                     out = out..","
  265.                 end
  266.             end
  267.  
  268.         elseif statement.AstType == 'BreakStatement' then
  269.             out = "break"
  270.  
  271.         elseif statement.AstType == 'RepeatStatement' then
  272.             out = "repeat"
  273.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  274.             out = joinStatementsSafe(out, "until")
  275.             out = joinStatementsSafe(out, formatExpr(statement.Condition))
  276.  
  277.         elseif statement.AstType == 'Function' then
  278.             statement.Scope:ObfuscateVariables()
  279.             if statement.IsLocal then
  280.                 out = "local"
  281.             end
  282.             out = joinStatementsSafe(out, "function ")
  283.             if statement.IsLocal then
  284.                 out = out..statement.Name.Name
  285.             else
  286.                 out = out..formatExpr(statement.Name)
  287.             end
  288.             out = out.."("
  289.             if #statement.Arguments > 0 then
  290.                 for i = 1, #statement.Arguments do
  291.                     out = out..statement.Arguments[i].Name
  292.                     if i ~= #statement.Arguments then
  293.                         out = out..","
  294.                     elseif statement.VarArg then
  295.                         --print("Apply vararg")
  296.                         out = out..",..."
  297.                     end
  298.                 end
  299.             elseif statement.VarArg then
  300.                 out = out.."..."
  301.             end
  302.             out = out..")"
  303.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  304.             out = joinStatementsSafe(out, "end")
  305.  
  306.         elseif statement.AstType == 'GenericForStatement' then
  307.             statement.Scope:ObfuscateVariables()
  308.             out = "for "
  309.             for i = 1, #statement.VariableList do
  310.                 out = out..statement.VariableList[i].Name
  311.                 if i ~= #statement.VariableList then
  312.                     out = out..","
  313.                 end
  314.             end
  315.             out = out.." in"
  316.             for i = 1, #statement.Generators do
  317.                 out = joinStatementsSafe(out, formatExpr(statement.Generators[i]))
  318.                 if i ~= #statement.Generators then
  319.                     out = joinStatementsSafe(out, ',')
  320.                 end
  321.             end
  322.             out = joinStatementsSafe(out, "do")
  323.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  324.             out = joinStatementsSafe(out, "end")
  325.  
  326.         elseif statement.AstType == 'NumericForStatement' then
  327.             statement.Scope:ObfuscateVariables()
  328.             out = "for "
  329.             out = out..statement.Variable.Name.."="
  330.             out = out..formatExpr(statement.Start)..","..formatExpr(statement.End)
  331.             if statement.Step then
  332.                 out = out..","..formatExpr(statement.Step)
  333.             end
  334.             out = joinStatementsSafe(out, "do")
  335.             out = joinStatementsSafe(out, formatStatlist(statement.Body))
  336.             out = joinStatementsSafe(out, "end")
  337.         elseif statement.AstType == 'LabelStatement' then
  338.             out = getIndentation() .. "::" .. statement.Label .. "::"
  339.         elseif statement.AstType == 'GotoStatement' then
  340.             out = getIndentation() .. "goto " .. statement.Label
  341.         elseif statement.AstType == 'Comment' then
  342.             -- ignore
  343.         elseif statement.AstType == 'Eof' then
  344.             -- ignore
  345.         else
  346.             print("Unknown AST Type: " .. statement.AstType)
  347.         end
  348.         count = count + #out
  349.         return out
  350.     end
  351.  
  352.     formatStatlist = function(statList)
  353.         local out = ''
  354.         statList.Scope:ObfuscateVariables()
  355.         for _, stat in pairs(statList.Body) do
  356.             out = joinStatementsSafe(out, formatStatement(stat), ';')
  357.         end
  358.         return out
  359.     end
  360.  
  361.     ast.Scope:ObfuscateVariables()
  362.     return formatStatlist(ast)
  363. end
  364.  
  365. return Format_Mini
Add Comment
Please, Sign In to add comment