From ecf376285301e675165aef7314ffc7726e04e1b0 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Sun, 31 Mar 2019 14:49:04 -0400 Subject: [PATCH] big additions Added for loops and while loops for i=1,10 < print(i) > for i=10,1, -1 < print(i) > while a!=1 < print("we looping") > --- DMS.xml | 4 +- parseManager/init.lua | 117 +++++++++++++++++++------------- parseManager/standardDefine.lua | 23 ++++++- test.dms | 31 ++++++--- test.lua | 79 +++++++++++++++++++-- 5 files changed, 191 insertions(+), 63 deletions(-) diff --git a/DMS.xml b/DMS.xml index 28419f3..651e031 100644 --- a/DMS.xml +++ b/DMS.xml @@ -25,9 +25,9 @@ */ ENABLE DISABLE LOAD ENTRY USING VERSION as - if then return and or True False + if then return and or True False for while leaking debugging warnings - ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD JUMP error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread + ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD JUMP error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread setGlobalVar getGlobalVar _VERSION filesystem extendedDefine diff --git a/parseManager/init.lua b/parseManager/init.lua index b011fd3..967aa2d 100644 --- a/parseManager/init.lua +++ b/parseManager/init.lua @@ -1,6 +1,6 @@ require("bin") parseManager={} -parseManager.VERSION = 4.1 +parseManager.VERSION = 5 parseManager.__index=parseManager parseManager.chunks={} parseManager.stats={warnings = true} @@ -58,7 +58,6 @@ function parseManager:run(block) while dat do dat = self:mainRunner() end - -- print("done") end function readonlytable(tab) return setmetatable({},{ @@ -204,12 +203,22 @@ function parseManager:load(path,c) parseManager.currentHandleName=name parseManager.currentHandle=c c:compile(name,ctype,data) + c.runtime = true end --c.chunks=readonlytable(c.chunks) c.mainENV["False"]=false c.mainENV["True"]=true return c end +function push(s,n) + table.insert(s,n) +end +function pop(s) + return table.remove(s) +end +function peek(s) + return s[#s] +end function parseManager:extractState() return {name=self.currentChunk.name,pos = self.currentChunk.pos,variables = self.mainENV,cc = self.currentENV} end @@ -367,23 +376,26 @@ function table.print(tbl, indent) end end function parseManager:pushError(err,sym) - if not self.currentChunk then print("ERROR: ",err,sym) os.exit() end + local run = "Compile Time Error! " + if self.runtime then + run = "Run Time Error! " + end + if not self.currentChunk then print("ERROR compiling: ",err,sym) os.exit() end local lines = bin.load(self.currentChunk.path):lines() local chunk = self.currentChunk[self.currentChunk.pos-1] - -- table.print(chunk) for i=1,#lines do if sym then if lines[i]:find(sym) then - print(err.." <"..sym.."> At line: "..i.." "..(lines[i]:gsub("^\t+",""))) + print(run..err.." <"..sym.."> At line: "..i.." "..(lines[i]:gsub("^\t+",""))) break end elseif chunk.Type=="fwor" or chunk.Type=="fwr" then if lines[i]:match(chunk.Func.."%(") then - print(err.." At line: "..i.." "..(lines[i]:gsub("^\t+","")).." ("..tostring(sym)..")") + print(run..err.." At line: "..i.." "..(lines[i]:gsub("^\t+","")).." ("..tostring(sym)..")") break end else - print(err.." Line: ?") + print(run..err.." Line: ?") break end end @@ -401,7 +413,6 @@ local function pieceList(list,self,name) local L={} for i=1,#list do if list[i]:match("[%w_]-%[.-%]") and list[i]:sub(1,1)~='"' then - -- print("dict") local dict,sym=list[i]:match("([%w_]-)%[(.-)%]") if tonumber(sym) then L[#L+1]={"\1"..dict,tonumber(sym),IsALookup=true} @@ -414,35 +425,26 @@ local function pieceList(list,self,name) L[#L+1]="\1"..sym end elseif list[i]:sub(1,1)=="\"" and list[i]:sub(-1,-1)=="\"" then - -- print("string") L[#L+1]=list[i]:sub(2,-2) elseif list[i]:sub(1,1)=="[" and list[i]:sub(-1,-1)=="]" then - -- print("index") L[#L+1]=pieceList(list[i]:sub(2,-2),self,name) elseif tonumber(list[i]) then - -- print("number") L[#L+1]=tonumber(list[i]) elseif list[i]=="true" then - -- print("true") L[#L+1]=true elseif list[i]=="false" then - -- print("false") L[#L+1]=false elseif list[i]:match("[%w_]+")==list[i] then - -- print("var?") L[#L+1]="\1"..list[i] elseif list[i]:match("[%w_]-%..-") then - -- print("dict?") local dict,sym=list[i]:match("([%w_]-)%.(.+)") L[#L+1]={"\1"..dict,sym,IsALookup=true} elseif list[i]:match("^([%w_]+)%s*%((.*)%)$") then - -- print("func") local func,args = list[i]:match("^([%w_]+)%s*%((.*)%)$") local sym = getSymbol("`") self:compileFWR(func,sym,args,name) L[#L+1]="\1"..sym elseif list[i]:match("[_%w%+%-/%*%^%(%)%%]+") and list[i]:match("[%+%-/%*%^%%]+") then - -- print("math") local char=getSymbol("$") self:compileExpr(char,list[i],name) L[#L+1]="\1"..char @@ -528,6 +530,8 @@ function parseManager:compileAssign(assignA,assignB,name) assign.vals[#assign.vals+1]={"\1"..dict,tonumber(sym),IsALookup=true} elseif sym:sub(1,1)=="\"" and sym:sub(-1,-1)=="\"" then assign.vals[#assign.vals+1]={"\1"..dict,sym:sub(2,-2),IsALookup=true} + else + assign.vals[#assign.vals+1]={"\1"..dict,"\1"..sym,IsALookup=true} end elseif listB[k]:match("[%w_]-%..-") and not listB[k]:match("(%d-)%.(%d-)") then local dict,sym=listB[k]:match("([%w_]-)%.(.+)") @@ -553,7 +557,9 @@ function parseManager:compileAssign(assignA,assignB,name) self:debug(assignA,assignB,name) end end - table.insert(self.chunks[name],assign) + if #assign.vars~=0 then + table.insert(self.chunks[name],assign) + end end function parseManager:compileCondition(condition,iff,elsee,name) self:compileLogic(condition,iff,elsee,name) @@ -655,9 +661,8 @@ function parseManager:compileExpr(eql,expr,name) packFunc("\3"..i,self:pieceExpr(a)) return "@" end) - end--self.cFuncs + end expr=expr:gsub("%b()",function(a) - -- print(">",a) return self:pieceExpr(a:sub(2,-2)) end) local loop @@ -676,7 +681,6 @@ function parseManager:compileExpr(eql,expr,name) end end if expr:match("[!%$%s&_%w%+%-,/%*%.%^%(%)%%]+")==expr then - -- print(expr) expr = expr:gsub("%s","") parseManager:pieceExpr(expr) cmds[#cmds]["vars"]={"\1"..eql} @@ -739,7 +743,7 @@ function parseManager:compileLogic(condition,iff,elsee,name) local mathass=0 _conds=conds:gsub("%s*\5".."1==0","") local cmds={} - for l,eq,r in conds:gmatch("(.-)([=~!><][=]*)(.-)%s*[\4\5]") do + for l,eq,r in conds:gmatch("(.-)%s*([=~!><][=]*)(.-)%s*[\4\5]") do charL=string.char(count+65) charM=string.char(mathass+65) count=count+1 @@ -793,6 +797,9 @@ function parseManager:compileLogic(condition,iff,elsee,name) _conds=_conds:gsub("\4","*") _conds=_conds:gsub("\5","+") if not _conds:find("%*") and not _conds:find("%+") then + if not cmds.vars then + self:pushError("Invalid condition passed!",condition) + end cmds.vars[1]="\1L$" else self:compileExpr("L$",_conds,name) @@ -841,21 +848,55 @@ function parseManager:compile(name,ctype,data) self:debug("COMPILING Block: "..name) local data=bin.new(data):lines() local choiceBlock=false + local stack = {} + local choiceBlockLOOP=false local choice={} for i=1,#data do data[i]=trim1(data[i]) if data[i]~="" then - if data[i]:match(".-\"<%s*") then + if data[i]:match("for[%s%w=%-]-[%d%-,%s]-<") then + choiceBlockFor=true + local sym = getSymbol("FOR") + local var,a,b,c = data[i]:match("for%s*([%w_]+)%s*=%s*(%-*[%d]+),%s*(%-*[%d]+)%s*,*%s*(%-*[%d]*)") + local s = getSymbol(getSymbol("LOOPEND")) + push(stack,{sym,var,a,b,s,1,c}) -- 1 for loop, 2 while loop + data[i] = "::"..sym.."::" + self:compileAssign(var,a,name) + elseif data[i]:match("while ([_%w=><~!%-%s]+)<$") then + -- WHILE LOOP + local sym = getSymbol("WHILE") + local s = getSymbol(getSymbol("LOOPEND")) + self:compileLabel(sym,name) + local cond = data[i]:match("while ([_%w=><~!%-%s]-)%s*<$") + data[i]="if "..cond.." then SKIP(0)|GOTO(\""..s.."\")" + push(stack,{sym,0,0,0,s,2}) -- 1 for loop, 2 while loop + elseif data[i]:match(".-\"%s*<%s*") then choiceBlock=true choice={} j=0 end + if (choiceBlockLOOP or #stack~=0) and not choiceBlock then + if data[i]==">" then + choiceBlockLOOP=false + local dat = pop(stack) + local s = dat[5] + local cmd = dat[6] + if cmd==1 then + self:compileAssign(dat[2],dat[2] .. (tonumber(dat[7]) or "+1"),name) + self:compileCondition(dat[2].."=="..tonumber(dat[4])+(tonumber(dat[7]) or 1),"GOTO(\""..s.."\")","GOTO(\""..dat[1].."\")",name) + data[i] = "::"..s.."::" + elseif cmd == 2 then + self:compileFWOR("GOTO","\""..dat[1].."\"",name) + data[i]="::"..s.."::" + end + end + end if choiceBlock then - if data[i]:find(">") then + if data[i]==">" then choiceBlock=false table.insert(self.chunks[name],choice) else - dat=data[i]:gsub("<","") + dat=data[i]:gsub("%s*<","") if j==0 then choice.Type="choice" choice.prompt=dat:sub(2,-2) @@ -863,12 +904,12 @@ function parseManager:compile(name,ctype,data) else local a,b=dat:match("\"(.-)\"%s*(.+)") if b then - local f,ag=b:match("^([%w_]+)%s*%((.*)%)") + local f,ag=b:match("^([%w_]+)%s*(%b())") if ag~="" then choice[#choice+1]={a,{ Type="fwor", Func=f, - args=pieceList(ag,self,name), + args=pieceList(ag:sub(2,-2),self,name), }} else choice[#choice+1]={a,{ @@ -900,19 +941,14 @@ function parseManager:compile(name,ctype,data) local flags,target = data[i]:match("(%u+)%s([%w%s]+)") ------ if line then - -- print(1) self:compileLine(line,name) elseif condition then - -- print(2) self:compileCondition(condition,iff,elsee,name) elseif FWR then - -- print(3) self:compileFWR(FWR,vars,args,name) elseif FWOR then - -- print(4) self:compileFWOR(FWOR,args,name) elseif FWR2 then - -- print(5) local dict,dot,sym=FWR2:match("([%w_]-)([%.:])(.+)") if dot==":" then args2=dict..","..args2 @@ -922,7 +958,6 @@ function parseManager:compile(name,ctype,data) end self:compileFWR({dict,sym,IsALookup=true},vars2,args2,name) elseif FWOR2 then - -- print(6) local dict,dot,sym=FWOR2:match("([%w_]-)([%.:])(.+)") if dot==":" then args2=dict..","..args2 @@ -932,29 +967,23 @@ function parseManager:compile(name,ctype,data) end self:compileFWOR({dict,sym,IsALookup=true},args2,name) elseif assignA then - -- print(7) self:compileAssign(assignA,assignB,name) elseif label then - -- print(8) self:compileLabel(label,name) elseif Return and isFBlock then - -- print(9) table.insert(self.chunks[name],{ Type="return", RETArgs=pieceList(RETArgs,self,name) }) elseif Return and not(isFBlock) then - -- print(10) self:pushError("Attempt to call return in a non function block!",data[i]) elseif flags and target then - -- print(11) table.insert(self.chunks[name],{ Type = "toggle", Flags = flags, Target = target }) else - -- print(12) table.insert(self.chunks[name],{ Type="customdata", data=data[i], @@ -1006,15 +1035,6 @@ function parseManager:define(t) self.methods[i]=v end end -function push(s,n) - table.insert(s,n) -end -function pop(s) - return table.remove(s) -end -function peek(s) - return s[#s] -end function parseManager:Invoke(func,vars,...) local name=func local func=self.chunks[func] @@ -1222,6 +1242,7 @@ function parseManager:next(block,choice) chunk.pos=chunk.pos+1 data=chunk[chunk.pos] end + if not data then return end chunk.pos=chunk.pos+1 self:debug("TYPE: "..data.Type) if data.Type=="text" then diff --git a/parseManager/standardDefine.lua b/parseManager/standardDefine.lua index 275a0f3..d6f09b8 100644 --- a/parseManager/standardDefine.lua +++ b/parseManager/standardDefine.lua @@ -15,6 +15,12 @@ parseManager:define{ error=function(self,msg) self:pushError(msg,"\2") end, + setGlobalVar=function(self,var,val) + self.mainENV[var]=val + end, + getGlobalVar=function(self,var,val) + self.mainENV[var]=val + end, QUIT=function() os.exit() end, @@ -299,18 +305,33 @@ parseManager:define{ end end, COMPARE=function(self,v1,v2,sym) - if sym==nil then self:pushError("Unexpected Error has occured!",":(") end + if sym==nil then self:pushError("Unexpected Error has occurred!","non-existing variable!") end if sym=="==" then if v1==v2 then return 1 else return 0 end elseif sym==">=" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end if v1>=v2 then return 1 else return 0 end elseif sym=="<=" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end if v1<=v2 then return 1 else return 0 end elseif sym==">" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end if v1>v2 then return 1 else return 0 end elseif sym=="<" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end if v1 + > + ::leave:: + print("t = $t$ i = $i$") } +// [hmm:function(a,b)]{ + // return a+b +// } +// [A1]{ + // "At: 1" +// } +// [A2]{ + // "At: 2" +// } +// [A3]{ + // "At: 3" +// } // [TEST]{ // newThread("TEST2") // ::loop:: diff --git a/test.lua b/test.lua index 383f140..9bd0a22 100644 --- a/test.lua +++ b/test.lua @@ -4,6 +4,8 @@ local multi = require("multi") require("parseManager") test=parseManager:load("test.dms")--load("StoryTest/init.dms") print(test:dump()) + + --Code would happen here anyway t=test:next() while t do @@ -20,13 +22,13 @@ while t do 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]) + print(t.prompt) + for i=1,#t[1] do + print(i..". "..t[1][i]) end io.write("Choose#: ") cm=tonumber(io.read()) - t=test:next(nil,cm,nil,t) + t=test:next(nil,cm) 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() @@ -39,3 +41,72 @@ while t do t=test:next() end end +--[[ +MAIN: + 1: + Type: assign + vals: + 1: 1 + vars: + 1: x + 2: + Type: label + pos: 2 + label: FORA + 3: + Type: fwor + Func: print + args: + 1: x + 2: y + 4: + Func: ADD + Type: fwr + vars: + 1: x + args: + 1: x + 2: 1 + 5: + Type: assign + vals: + vars: + 6: + Type: fwr + vars: + 1: L$ + Func: COMPARE + args: + 1: x + 2: 11 + 3: == + 7: + Type: fwor + Func: CSIM + args: + 1: L$ + 8: + Type: fwor + Func: GOTO + args: + 1: FORENDA + path: test.dms + pos: 1 + 11: + Type: text + text: Tests + labels: + FORA: 2 + FORENDA: 10 + type: BLOCK + 10: + Type: label + pos: 10 + label: FORENDA + name: MAIN + 9: + Type: fwor + Func: GOTO + args: + 1: FORA +]]