diff --git a/Library.lua b/Library.lua new file mode 100644 index 0000000..f82a01c --- /dev/null +++ b/Library.lua @@ -0,0 +1,331 @@ +if table.unpack then + unpack=table.unpack +end +function table.val_to_str ( v ) + if "string" == type( v ) then + v = string.gsub( v, "\n", "\\n" ) + if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then + return "'" .. v .. "'" + end + return '"' .. string.gsub(v,'"', '\\"' ) .. '"' + else + return "table" == type( v ) and table.tostring( v ) or + tostring( v ) + end +end + +function table.key_to_str ( k ) + if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then + return k + else + return "[" .. table.val_to_str( k ) .. "]" + end +end + +function table.tostring( tbl ) + local result, done = {}, {} + for k, v in ipairs( tbl ) do + table.insert( result, table.val_to_str( v ) ) + done[ k ] = true + end + for k, v in pairs( tbl ) do + if not done[ k ] then + table.insert( result, + table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) + end + end + return "{" .. table.concat( result, "," ) .. "}" +end +function table.merge(t1, t2) + t1,t2= t1 or {},t2 or {} + for k,v in pairs(t2) do + if type(v) == "table" then + if type(t1[k] or false) == "table" then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +Library={} +function Library.optimize(func) + local test=Library.convert(func) + rawset(test,"link",{}) + rawset(test,"last","") + rawset(test,"org",func) + test:inject(function(...) + rawset(test,"last",table.tostring({...})) + if test.link[test.last]~=nil then + return Library.forceReturn(unpack(test.link[test.last])) + end + return {...} + end,1) + test:inject(function(...) + test.link[test.last]={test.org(...)} + return test.org(...) + end) + return test +end +function Library.forceReturn(...) + return {[0]="\1\7\6\3\2\99\125",...} +end +function Library.inject(lib,dat,arg) + if type(lib)=="table" then + if type(dat)=="table" then + table.merge(lib,dat) + elseif type(dat)=="string" then + if lib.Version and dat:match("(%d-)%.(%d-)%.(%d-)") then + lib.Version={dat:match("(%d+)%.(%d+)%.(%d+)")} + elseif dat=="meta" and type(arg)=="table" then + local _mt=getmetatable(lib) or {} + local mt={} + table.merge(mt,arg) + table.merge(_mt,mt) + setmetatable(lib,_mt) + elseif dat=="compat" then + lib["getVersion"]=function(self) return self.Version[1].."."..self.Version[2].."."..self.Version[3] end + if not lib.Version then + lib.Version={1,0,0} + end + elseif dat=="inhert" then + if not(lib["!%"..arg.."%!"]) then print("Wrong Password!!") return end + lib["!%"..arg.."%!"].__index=lib["!!%"..arg.."%!!"] + end + elseif type(dat)=="function" then + for i,v in pairs(lib) do + dat(lib,i,v) + end + end + elseif type(lib)=="function" or type(lib)=="userdata" then + if lib==unpack then + print("function unpack cannot yet be injected!") + return unpack + elseif lib==pairs then + print("function pairs cannot yet be injected!") + return lib + elseif lib==ipairs then + print("function ipairs cannot yet be injected!") + return lib + elseif lib==type then + print("function type cannot yet be injected!") + return lib + end + temp={} + local mt={ + __call=function(t,...) + local consume,MainRet,init={},{},{...} + local tt={} + for i=1,#t.__Link do + tt={} + if t.__Link[i]==t.__Main then + if #consume~=0 then + MainRet={t.__Link[i](unpack(consume))} + else + MainRet={t.__Link[i](unpack(init))} + end + else + if i==1 then + consume=(t.__Link[i](unpack(init))) + else + if type(MainRet)=="table" then + table.merge(tt,MainRet) + end + if type(consume)=="table" then + table.merge(tt,consume) + end + consume={t.__Link[i](unpack(tt))} + end + if i==#t.__Link then + return unpack(consume) + end + if consume then if consume[0]=="\1\7\6\3\2\99\125" then consume[0]=nil return unpack(consume) end end + end + end + if type(MainRet)=="table" then + table.merge(tt,MainRet) + end + if type(consume)=="table" then + table.merge(tt,consume) + end + return unpack(tt) + end, + } + temp.__Link={lib} + temp.__Main=lib + temp.__self=temp + function temp:inject(func,i) + if i then + table.insert(self.__Link,i,func) + else + table.insert(self.__Link,func) + end + end + function temp:consume(func) + for i=1,#self.__Link do + if self.__Link[i]==self.__Main then + self.__Link[i]=func + self.__self.__Main=func + return true + end + end + return false + end + setmetatable(temp,mt) + Library.protect(temp,"lolz") + return temp + else + return "arg1 must be a table or a function" + end +end +function Library.parse(lib) + for i,v in pairs(lib) do + print(i,v) + end +end +function Library.protect(lib,pass) + pass=pass or "*" + local mt={} + local test={ + __index = lib, + __newindex = function(tab, key, value) + local t,b=key:find(tab["!%"..pass.."%!"].__pass,1,true) + if t then + local _k=key:sub(b+1) + rawset(tab,_k,value) + else + error("Cannot alter a protected library!") + end + end, + __metatable = false, + __pass=pass or "*" + } + local _mt=getmetatable(lib) or {} + table.merge(mt,_mt) + table.merge(mt,test) + lib["!%"..pass.."%!"]=test + lib["!!%"..pass.."%!!"]=lib + local temp=setmetatable({},mt) + for i,v in pairs(_G) do + if v==lib then + _G[i]=temp + Library(function(link) + link[i]=v + end) + end + end +end +function Library.unprotect(lib,pass) + if not(lib["!%"..pass.."%!"]) then print("Wrong Password or Library is not Protected!") return end + if lib["!%"..pass.."%!"].__pass==pass then + lib["!%"..pass.."%!"].__newindex=lib["!!%"..pass.."%!!"] + lib["!%"..pass.."%!"].__index=nil + lib["!%"..pass.."%!"].__newindex=nil + lib["!%"..pass.."%!"].__metatable = true + setmetatable(lib["!!%"..pass.."%!!"],lib["!%"..pass.."%!"]) + for i,v in pairs(_G) do + if v==lib then + _G[i]=lib["!!%"..pass.."%!!"] + end + end + lib["!!%"..pass.."%!!"]["!%"..pass.."%!"]=nil + lib["!!%"..pass.."%!!"]["!!%"..pass.."%!!"]=nil + else + print("Wrong Password!!!") + end +end +function Library.addPoll(lib,polldata,ref) + lib.__polldata={} + Library.inject(lib.__polldata,polldata) + if type(ref)=="table" then + Library.inject(ref,"meta",{__newindex=function(t,k,v) + t[k].__polldata=polldata + end}) + end +end +function Library.newPollData(t) + local temp={} + temp.__onPolled=function() end + temp.__pollData=false + temp.__advDisc="" + temp.__pollcalls=-1 -- infinte + for i,v in pairs(t) do + if type(v)=="string" then + temp.__advDisc=v + elseif type(v)=="number" then + temp.__pollcalls=v + elseif type(v)=="table" then + temp[v[1]]=v[2] + elseif type(v)=="function" then + temp.__onPolled=v + elseif type(v)=="boolean" then + temp.__pollData=v + else + temp.__userdata=v + end + end + return temp +end +function Library.convert(...) + local temp,rets={...},{} + for i=1,#temp do + if type(temp[i])=="function" then + table.insert(rets,Library.inject(temp[i])) + else + error("Takes only functions and returns in order from functions given. arg # "..i.." is not a function!!! It is a "..type(temp[i])) + end + end + return unpack(rets) +end +function Library.convertIn(...) + local temp,list={...},{} + for i=1,#temp do + if type(temp[i])=="table" then + for k,v in pairs(temp[i]) do + if type(v)=="function" then + temp[i][k]=Library.inject(temp[i][k]) + end + end + else + error("Takes only tables! Arg "..i.." isn't it is a "..type(temp[i])) + end + end +end +function Library.convertInWith(a,func,injectI) + if type(a)=="table" then + for k,v in pairs(a) do + if type(v)=="function" then + a[k]=Library.inject(v) + a[k]:inject(func,injectI) + end + end + else + error("Takes only tables! Arg 1 isn't, it is a "..type(temp[i])) + end +end +function Library.newInjectedFunction() + return Library.convert(function(...) return unpack{...} end) +end +function Library.capulate(lib) + Library.inject(lib,"meta",{ + __index=function(t,k,v) + for i,_v in pairs(t) do + if k:lower()==i:lower() then + return t[i] + end + end + end, + __newindex=function(t,k,v) + rawset(t,k:lower(),v) + end + }) +end +local link={MainLibrary=Library} +Library.inject(Library,"meta",{ + __Link=link, + __call=function(self,func) func(link) end, +}) +--Library.protect(Library,"N@#P!KLkk1(93320") diff --git a/parseManager/init.lua b/parseManager/init.lua index af90212..bc3b7c3 100644 --- a/parseManager/init.lua +++ b/parseManager/init.lua @@ -90,7 +90,8 @@ parseManager._types={} parseManager.__index=parseManager parseManager._variables={__TYPE="ENV"} parseManager.defualtENV=parseManager._variables -function parseManager:varExists(var) +function parseManager:varExists(var,inf) + --print(var) if var==nil or var=="nil" then return end if type(var)=="userdata" then return var end if tonumber(var) then @@ -103,6 +104,11 @@ function parseManager:varExists(var) if var:find('"') then return self:parseHeader(var:sub(2,-2),self.defualtENV) end + if inf then + --print("NO!") + else + return self:evaluate(var) + end if var:find("%[%]") then return {} end @@ -785,12 +791,13 @@ function parseManager:next(chunk,a,env,dd) end return {Type="end",text="Reached end of block!",lastblock=self._cblockname,lastline=self._cblock[self.pos-1],blocktype=self._chunks[self._cblockname][2]} end - local holder,functest,args=line:match("([%w_]-):([%w_]-)%s*%((.-)%)$") + local holder,functest,args=line:match("^([%w_]-):([%w_]-)%s*(%b())") if not functest then - functest,args=line:match("([%w_]-)%s*%((.-)%)$") + functest,args=line:match("^([%w_]-)%s*(%b())") end - if functest then - local funccheck=line:match("([%+%-%*/]+).-%(.-%)") + if not functest then + functest,args=line:match("([%w_]-)%s*(%b())") + local funccheck=line:match("([%+%-%*/"..self:populateSymbolList().."]+).-%(.-%)") if funccheck then functest=nil end @@ -801,6 +808,9 @@ function parseManager:next(chunk,a,env,dd) end end end + if args then + args=args:sub(2,-2) + end line=line:gsub("(.-)%[\"(.-)\"%]=(.+)",function(a,b,c) return b.."="..c.."->"..a end) @@ -945,12 +955,26 @@ function parseManager:next(chunk,a,env,dd) vars={t} end end - _args={} - for k, v in ipairs(parseManager.split(args)) do - if type(v)=="userdata" then - table.insert(_args,v) + local _args={} + print("Calling: "..functest) + local loop=parseManager.split(args) + print("ARG COUNT: ",#loop,args) + for i=1,#loop do + print(loop[i]) + if type(loop[i])=="userdata" then + table.insert(_args,loop[i]) else - table.insert(_args,(self:varExists(v))) +--~ local test,val=pcall(self.evaluate,self,v) +--~ print(test,k,val) +--~ if test then +--~ v=val +--~ else +--~ print("HERE!!!") +--~ v=self:varExists(v) +--~ end + local test=self:varExists(loop[i]) + print("After Processing: ",test) + table.insert(_args,test) end end if not holder then @@ -1100,12 +1124,12 @@ function parseManager:evaluate(cmd,v) local function helper(o,v,r) if type(v)=="string" then if v:find("%D") then - v=self:varExists(v) + v=self:varExists(v,true) end end if type(r)=="string" then if r:find("%D") then - r=self:varExists(r) + r=self:varExists(r,true) end end local r=tonumber(r) or 0 @@ -1148,14 +1172,9 @@ function parseManager:evaluate(cmd,v) end end end - if not loop then return self:varExists(cmd) end + if not loop then return self:varExists(cmd,true) end return v end -parseManager.constructType=function(self,name,t,data,filename) - if t~="construct" then return end - --print(name,t,"[CODE]{"..data.."}") - self:registerSymbol(name,"[CODE]{"..data.."}") -end -- Let's add function Stack = {} function Stack:Create() @@ -1248,30 +1267,11 @@ parseManager.funcType=function(link,name,t,data,filename) end link._methods[name]=func end +--registerSymbol(sym,code) parseManager.OnExtendedBlock(parseManager.funcType) -parseManager.constructType=function(link,name,t,data,filename) - local test,args=t:match("(construct)%(*([%w,]*)%)*") - if not test then return false end - local vars={} - if args~="" then - for k, v in ipairs(parseManager.split(args)) do - table.insert(vars,v) - end - end - link._chunks[name][1]=link._chunks[name][1].."\n__TRACEBACK()" - local func=function(self,...) - local args={...} - local env=self._methods.createENV(self) - local lastEnv=self._methods.getENV(self) - self.funcstack:push({self._cblockname,self.pos,lastEnv}) - if self.funcstack:getn()>1024 then self:pushError("Stack Overflow!") end - self._methods.setENV(self,env) - for i=1,#vars do - self:setVariable(vars[i],args[i]) - end - self._methods.JUMP(self,name) - return env - end - link._methods[name]=func +parseManager.constructType=function(self,name,t,data,filename) + if t~="construct" then return end + --print(name,t,"[CODE]{"..data.."}") + self:registerSymbol(name,"[CODE]{"..data.."}") end parseManager.OnExtendedBlock(parseManager.constructType) diff --git a/parsetest.txt b/parsetest.txt new file mode 100644 index 0000000..ec952e0 --- /dev/null +++ b/parsetest.txt @@ -0,0 +1,114 @@ +ENTRY START +ENABLE forseelabels +DISABLE leaking +ENABLE customcommands +USING EBIM -- Allows for multilined commands +[START]{ + --Defualt enviroment is the GLOBAL one, you can create and swap between them whenever you want. You can have as many as you want as well + a=100 + b=7 + c=21 + "$a$ $b$ $c$" + env=createENV() + setENV(env) + a=15 + b=150 + "$a$ $b$ $c$" + env=getENV("GLOBAL") + setENV(env) + "$a$ $b$ $c$" + test=a<-env -- get var a from an env and set it to test + "Test $test$" + test=51 + a=test->env -- set var a in env to test + "$a$ $b$ $c$" + setENV(env) -- lets go back to the modified enviroment + "$a$ $b$ $c$" + test2=stringLEN("$a$ $b$ $c$") + "Test2 $test2$" + string test5: -- no need for quotes, everything in the block is considered a string... Also no escaping is needed; however, endstring is not useable as a part of the string... + Yo I am able to make a multilined string if i want + Now I am at the next line lol! + endstring + list test6: -- create a multilined list + "elem1" + 2 + 3 + true + false + "elem6" + env + endlist + dict test7: + name: "Ryan" + age: 21 + job: "BUM" + list: test6 + enddict + "Test5 $test5$" + list=[1,2,3,4] + test4=list[2] + env["a"]=10 + test3=env["a"] + "Test3 $test3$" + "List $test6[1]$" + "List $test6[2]$" + "List $test6[3]$" + "List $test6[4]$" + "List $test6[5]$" + "List $test6[6]$" + "List $test6[7]$" + "Dict $test7[name]$" + "Dict $test7[age]$" + "Dict $test7[job]$" + test9="name" + test8=test7[test9] + "Test8 $test8$" + data=test7[list] + data2=data[1] + "Test9 $data2$" + data=tester2(1,2,3) + "Now what are these $a$ $b$ $c$" + "$data[name]$" + "$data[me]$" + ::choices:: + "Pick?"< + "test1" JUMP(C1) + "test2" JUMP(C2) + "test3" JUMP(C3) + > + -- if name=="bob" or name=="ryan": + -- "ADMINS" + -- elseif name=="Joe" + -- "NOT ADMIN" + -- else + -- "Something else" + -- endif +} +[C1]{ + "Hello1" + GOTO(choices) +} +[C2]{ + "Hello2" + GOTO(choices) +} +[C3]{ + "Hello3" + GOTO(choices) +} +[@:construct]{ -- l is left arg r is the right arg + ret=l*(r/100) + return(ret) +} +[tester:function]{ + "lets go" + nest="hey" +} +[tester2:function(a,b,c)]{ -- functions return enviroments which can be indexed + "Interesting: $a$ $b$ $c$" + name="Ryan" + age=15 + yo=tester() + me=yo["nest"] +} diff --git a/parsetest2.txt b/parsetest2.txt new file mode 100644 index 0000000..e9903ab --- /dev/null +++ b/parsetest2.txt @@ -0,0 +1,74 @@ +-- 감사합니다 +ENTRY START +[START]{ + a=10>1 -- bit shift + b=10<1 + "test: $a$ $b$" + testfunc("hello",(5!),(2!)+2) + -- "Hello It is now time to do some tests!" + -- a=15 + -- "a = $a$" + -- b=a@25 + -- test2="Yo $a$ $b$" -- create a string with a and b vars + -- "$test2$" + -- "b = $b$" + -- c=5 + -- "c = $c$" + -- cf=10+(5!)+10 + -- test=(5~5)+5 + -- "c! = $cf$ test = $test$" + -- "All done" + -- JUMP(NOVAR) +} +[@:construct]{ -- get % out of 100 + ret=l/(r/100) + return(ret) +} +[>:construct]{ -- get % out of 100 + ret=rshift(l,r) + return(ret) +} +[<:construct]{ -- get % out of 100 + ret=lshift(l,r) + return(ret) +} +[~:construct]{ -- negate variable + if r~=NONE then GOTO(sub)|GOTO(neg) + ::sub:: + ret=l-r + return(ret) + GOTO(end) + ::neg:: + ret=0-r + return(ret) + ::end:: +} +-- You dont have too many symbols left to use though. For now a symbol is only 1 char long so you are limited +[fact:function(n)]{ + count=1 + stop=n + ::loop:: -- for loop kinda, can become a stateloop as well + n=n*count + count=count+1 + if count==stop then GOTO(end)|GOTO(loop) + ::end:: + ret=n +} +[neg:function(n)]{ + ret=n*(0-1) +} +--Bind the fact function to the symbol '!' +[!:construct]{ + env=fact(l) + ret=ret<-env + return(ret) +} +[NOVAR]{ + ::go:: + "I AM HERE!!!" + NOVAR="TEST" + JUMP(START) +} +[TEST]{ + "We are now here" +} \ No newline at end of file diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..d824027 --- /dev/null +++ b/test.lua @@ -0,0 +1,51 @@ +package.path="?/init.lua;lua/?/init.lua;lua/?.lua;"..package.path +require("bin") +require("multi.all") +require("parseManager") +--~ require("Library") +require("bit") +parseManager:define({ + rshift=function(self,a,b) + return bit.rshift(a,b) + end, + lshift=function(self,a,b) + return bit.lshift(a,b) + end, + testfunc=function(self,a,b,c) + print("> "..tostring(a).." "..tostring(b).." "..tostring(c)) + end +}) +test=parseManager:load("parsetest2.txt") +t=test:start() +while true do + if t.Type=="text" then + print(t.text) + t=test:next() + elseif t.Type=="condition" then + t=test:next() + elseif t.Type=="assignment" then + t=test:next() + elseif t.Type=="label" then + t=test:next() + elseif t.Type=="method" then + t=test:next() + elseif t.Type=="choice" then + print(t.text) + for i=1,#t.choices do + print(i..". "..t.choices[i]) + end + io.write("Choose#: ") + cm=tonumber(io.read()) + t=test:next(nil,cm,nil,t) + elseif t.Type=="end" then + if t.text=="leaking" then -- go directly to the block right under the current block if it exists + t=test:next() + else + os.exit() + end + elseif t.Type=="error" then + error(t.text) + else + t=test:next() + end +end