Lanzr

hex

Jul 4th, 2024 (edited)
1,071
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.86 KB | None | 0 0
  1. --[[
  2.     * a  mineCraft HexCasting Mod Compiler, can compile the hCode in game and output to the focus
  3.     * need mod : Ducky peripheral
  4.     * author : Lanzr
  5. ]]
  6. require("hexMap")
  7. local completion = require "cc.shell.completion"
  8. local complete = completion.build(
  9.     completion.file
  10. )
  11. shell.setCompletionFunction("hex.lua", complete)
  12. local path = arg[1]
  13. if(path == nil) then
  14.     local programName = arg[0] or fs.getName(shell.getRunningProgram())
  15.     print("Usage: " .. programName .. " <path>")
  16.     return
  17. end
  18. if(fs.exists(path) == false) then
  19.     print("file "..path.." is not exist!")
  20.     return
  21. end
  22.  
  23. local inf = io.open(path,"r") -- the source_code filename
  24. local codeStr = inf.read(inf,"*all")
  25. inf.close(inf)
  26.  
  27. local fPort = peripheral.find("focal_port")
  28.  
  29. local lastIndex = 0
  30. local index = -1
  31. local leftBrackIndex = nil
  32.  
  33. local hexlist = {} -- the final table use to output
  34.  
  35. local funcKey = nil
  36. local funcMap = {}
  37.  
  38.  
  39. -- ---------------------------
  40. -- patch
  41. function findAndReplaceLiteral(source_string, target_substring, replacement_substring, num_replacements)
  42.     local escaped_target = string.gsub(target_substring, "([%.%+%-%*%?%^%$%(%)%[%]%{}])", "%%%1")
  43.     local new_string, count = string.gsub(
  44.         source_string,
  45.         escaped_target,
  46.         function()
  47.             return replacement_substring
  48.         end,
  49.         num_replacements
  50.     )
  51.  
  52.     return new_string, count
  53. end
  54.  
  55.  
  56. function parseFuncDefine(funcstr)
  57.     local start1, end1 = string.find(funcstr,"^[\t ]*@func[ ]+([%w_]+)[\t ]*%(([%w,_ \t]*)%)[\t ]*\r?\n")
  58.     local fundef = string.sub(funcstr,start1,end1-1)
  59.     local start2 = string.find(funcstr,"[\t ]*@end[\t ]*")
  60.     local funcbody = string.sub(funcstr,end1+1,start2-2)
  61.  
  62.     local funcname, params = string.match(fundef,genRegex("@func[ ]+([%w_]+)[\t ]*%(([%w,_ \t]*)%)"))
  63.     local index = 0
  64.     for s in params:gmatch("([^ ,\t]+)") do
  65.         funcbody = findAndReplaceLiteral(funcbody,"$"..s,"$"..index)
  66.         index = index + 1
  67.     end
  68.     funcMap[funcname]=funcbody
  69. end
  70.  
  71. function funcInvoke(cut)
  72.     local funcname, params_string = string.match(cut,genRegex("([%w_]+)[\t ]*%(([%w,_ %(%)\t]*)%)"))
  73.     local index = 0
  74.     local funcbody = funcMap[funcname]
  75.    
  76.     if params_string:match("^%s*$") then
  77.         return funcbody
  78.     end
  79.  
  80.     local balance = 0
  81.     local start_index = 1
  82.     local args = {}
  83.     for i = 1, #params_string do
  84.         local char = params_string:sub(i, i)
  85.  
  86.         if char == '(' then
  87.             balance = balance + 1
  88.         elseif char == ')' then
  89.             balance = balance - 1
  90.         elseif char == ',' and balance == 0 then
  91.             local arg = params_string:sub(start_index, i - 1)
  92.             arg = arg:match("^%s*(.-)%s*$")
  93.             table.insert(args, arg)
  94.             start_index = i + 1
  95.         end
  96.     end
  97.  
  98.     local last_arg = params_string:sub(start_index)
  99.     last_arg = last_arg:match("^%s*(.-)%s*$")
  100.     table.insert(args, last_arg)
  101.     local index = 0
  102.     for i, arg in ipairs(args) do
  103.         index = i - 1
  104.         if string.match(arg,genRegex("([%a_]+[%w_]*)%(([%w,_ \t]*)%)")) then
  105.             local retstr = funcInvoke(arg)
  106.             funcbody = findAndReplaceLiteral(funcbody,"$"..index, retstr)
  107.         else
  108.             funcbody = findAndReplaceLiteral(funcbody,"$"..index, arg)
  109.         end
  110.     end
  111.  
  112.     return funcbody    
  113. end
  114. -- ---------------------------
  115.  
  116. NumMap = {
  117.     [0] = {["startDir"]="SOUTH_EAST",["angles"]="aqaa"},
  118.     [1] = {["startDir"]="SOUTH_EAST",["angles"]="aqaaw"},
  119.     [2] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawa"},
  120.     [3] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawaw"},
  121.     [4] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawaa"},
  122.     [5] = {["startDir"]="SOUTH_EAST",["angles"]="aqaaq"},
  123.     [6] = {["startDir"]="SOUTH_EAST",["angles"]="aqaaqw"},
  124.     [7] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawaq"},
  125.     [8] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawwaa"},
  126.     [9] = {["startDir"]="SOUTH_EAST",["angles"]="aqaawaaq"},
  127.     [10] = {["startDir"]="SOUTH_EAST",["angles"]="aqaaqa"}
  128. }
  129.  
  130. local regMap = {
  131.     [genRegex("([{}>%*%+-=</])")] = (function (cStr)
  132.         table.insert(hexlist,hexMap[cStr])
  133.     return true end),
  134.     [genRegex("rm[ ]+(%d+)")] = (function (cStr)
  135.         addRMPattern(cStr)
  136.     return true end),
  137.     [genRegex("(-?[%d]+)")] = (function (cStr)
  138.         addNumPattern(tonumber(cStr))
  139.     return true end),
  140.     [genRegex("([%a_]+[%w_]*)")] = (function (cStr)
  141.         local t = hexMap[cStr]
  142.         if t == nil then
  143.             return false
  144.         end
  145.         table.insert(hexlist,t)
  146.     return true end),
  147.     -- [genRegex("([%a_]+[%w_]*)%(%)")] = (function (cStr)
  148.     --     parseStr(funcMap[cStr])
  149.     -- return true end)
  150. }
  151.  
  152. function addNumPattern(num)
  153.     local stackOpe = {}
  154.     local len = 0
  155.     local oper = 0
  156.     local rem = num > 0 and num or -num
  157.     if num < 0 then
  158.         table.insert(hexlist,NumMap[0])
  159.     end
  160.     repeat
  161.         oper = rem % 10
  162.         rem = (rem - oper) /10
  163.         table.insert(stackOpe,oper)
  164.         len = len + 1
  165.     until  rem < 1  
  166.     rem = 0
  167.     i = len
  168.     while true do
  169.         table.insert(hexlist,NumMap[stackOpe[i]])
  170.         if(i < len) then
  171.             table.insert(hexlist,hexMap["+"])
  172.         end
  173.         i = i - 1
  174.         if i < 1 then
  175.             break
  176.         end
  177.         table.insert(hexlist,NumMap[10])
  178.         table.insert(hexlist,hexMap["*"])
  179.     end
  180.     if num < 0 then
  181.         table.insert(hexlist,hexMap["-"])
  182.     end
  183. end
  184.  
  185. function addRMPattern(rmPos)
  186.     local rmPattern = {}
  187.     local angleStr = ""
  188.     local pos = tonumber(rmPos)
  189.     rmPattern["startDir"] = "EAST"
  190.     if (pos > 1) then
  191.         for i=1,pos-1,1 do
  192.             angleStr = angleStr.."w"
  193.         end
  194.         angleStr = angleStr.."ea"
  195.     else
  196.         angleStr = "a"
  197.     end
  198.     rmPattern["angles"] = angleStr
  199.     table.insert(hexlist,rmPattern)
  200. end
  201.  
  202. function parseStr(str)
  203.     local lastIndex = 0
  204.     local index = -1
  205.     local cut = ""
  206.     local lineIndex = 0
  207.     local funcstr = ""
  208.     while ( index ~= nil ) do
  209.         local syntaxFlag = true;
  210.         lineIndex = lineIndex + 1
  211.         index = string.find(str,"\n", index + 1);
  212.         if( index ~= nil) then
  213.             cut = string.sub(str,lastIndex+1, index-1)
  214.         else
  215.             cut = string.sub(str,lastIndex+1, index);
  216.         end
  217.         -- comment check
  218.         repeat
  219.             lastIndex = index
  220.             local commentPos = string.find(cut,"#")
  221.             if commentPos ~= nil then
  222.                 cut = string.sub(cut, 1,commentPos-1)
  223.             end
  224.             -- preExp regMap
  225.             -- include check
  226.             if (string.match(cut,genRegex(""))) then
  227.                 break
  228.             end
  229.             if (string.match(cut,genRegex("@.*"))) then
  230.                 if (string.match(cut,preMap["include"])) then
  231.                     local cStr = string.match(cut,preMap["include"])
  232.                     local inf = io.open(cStr,"r") -- the source_code filename
  233.                     local subStr = inf.read(inf,"*all")
  234.                     inf.close(inf)
  235.                     parseStr(subStr)
  236.                     break
  237.                 end
  238.                 -- func check
  239.                 if (string.match(cut,preMap["func"])~= nil) then
  240.                     funcstr = cut.."\n"
  241.                     funcKey = true
  242.                     break
  243.                 elseif(string.match(cut,preMap["end"])) then
  244.                     funcKey = nil
  245.                     funcstr = funcstr..cut.."\n"
  246.                     parseFuncDefine(funcstr)
  247.                     break
  248.                 end
  249.                 -- not found anything
  250.                 syntaxFlag = false
  251.                 break
  252.             end
  253.            
  254.             if(funcKey ~= nil) then
  255.                 funcstr = funcstr..cut.."\n"
  256.                 break
  257.             end
  258.  
  259.             if string.match(cut,genRegex("([%a_]+[%w_]*)%((.*)%)")) then
  260.                 retstr = funcInvoke(cut)
  261.                 parseStr(retstr)
  262.                 break
  263.             end
  264.             -- common regMap
  265.             for key, cb in pairs(regMap) do
  266.                 if (string.match(cut,key)~= nil) then
  267.                     local cStr = string.match(cut,key)
  268.                     syntaxFlag = cb(cStr)
  269.                     break
  270.                 end  
  271.             end
  272.             if syntaxFlag then
  273.                 break
  274.             end
  275.             syntaxFlag = false
  276.         until true
  277.         if syntaxFlag ~= true then
  278.             print("Line : "..cut.." is illegal syntax")
  279.             return false
  280.         end
  281.     end
  282.     return true
  283. end
  284.  
  285. function mainloop()
  286.     ret = parseStr(codeStr)
  287.     if ret then
  288.         if(fPort ~= nil) then
  289.             fPort.writeIota(hexlist)
  290.         end
  291.         -- print("compile success")
  292.     else
  293.         -- print("compile failed")
  294.     end
  295. end
  296.  
  297. mainloop()
  298.  
Advertisement
Add Comment
Please, Sign In to add comment