diff --git a/compiler2.lua b/compiler2.lua index 4ccf752..38c8729 100644 --- a/compiler2.lua +++ b/compiler2.lua @@ -1,4 +1,4 @@ package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path -local parser = require("dms.parser") -local p = parser:new("test.dms") -p:parse() +local Interpreter = require("dms.interpreter") +local i = Interpreter:new("test.dms") +print(i:dump()) \ No newline at end of file diff --git a/dms/chunk.lua b/dms/chunk.lua index 69b5af9..0cff633 100644 --- a/dms/chunk.lua +++ b/dms/chunk.lua @@ -1,4 +1,5 @@ -local cmd = require("dms.cmd") +local Stack = require("dms.stack") +local Queue = require("dms.queue") local Chunk = {} Chunk.__index = Chunk function Chunk:__tostring() @@ -18,16 +19,53 @@ function Chunk:new(cname,ctype,filename) c.variables = {} c.pos = 0 c.cmds = {} + c.control = Stack:new() + c.lastCMD = nil + c.alerts = {} return c end function Chunk:addVariable(value) self.varaiables[value.name] = value.value end function Chunk:addCmd(cmd) - cmd.chunk = self - table.insert(self.cmds,cmd) + --print(">",cmd) + if self.control:count()==0 then + cmd.chunk = self + table.insert(self.cmds,cmd) + else + if cmd.line[2] < self.lastCMD.line[2] then + self:doPop() + self:addCmd(cmd) + return + end + cmd.chunk = self + table.insert(self.cmds,cmd) + end + self.lastCMD = cmd end function Chunk:count() return #self.cmds end +function Chunk:finished() + self:doPop() +end +function Chunk:doPop(amt) + if amt then + for i=1,amt do + self.control:pop()() + end + else + local scope = self.control:pop() + --while scope do + if scope then + scope() + scope = self.control:pop() + end + --end + end +end +function Chunk:setScope(func) + self.first = true + self.control:push(func) +end return Chunk \ No newline at end of file diff --git a/dms/expr.lua b/dms/expr.lua deleted file mode 100644 index 0ba4a90..0000000 --- a/dms/expr.lua +++ /dev/null @@ -1,8 +0,0 @@ -local Expr = {} -Expr.__index = Expr -function Expr:new(expr) - local c = {} - setmetatable(c,self) - - return c -end \ No newline at end of file diff --git a/dms/interpreter.lua b/dms/interpreter.lua new file mode 100644 index 0000000..a219759 --- /dev/null +++ b/dms/interpreter.lua @@ -0,0 +1,30 @@ +local Parser = require("dms.parser") +local Interpreter= {} +Interpreter.__index = Interpreter +function Interpreter:new(file) + local c = {} + setmetatable(c,self) + if file then + c.parser = Parser:new(file) + c.chunks = c.parser:parse() + else + c.chunks = {} + end + return c +end +function Interpreter:compile(file) + if not file then error("You must provide a file path to compile!") end + self.chunks = Parser:new(file,self.chunks):parse() +end +function Interpreter:dump() + local filedat = "" + + for i,v in pairs(self.chunks) do + filedat = filedat..tostring(v) .. "\n" + end + return filedat +end +function Interpreter:interprete() + -- +end +return Interpreter \ No newline at end of file diff --git a/dms/parser.lua b/dms/parser.lua index 35d621a..48a172b 100644 --- a/dms/parser.lua +++ b/dms/parser.lua @@ -1,11 +1,12 @@ require("dms.utils") +file = io.open("dump.dat","wb") local char = string.char local Stack = require("dms.stack") local Chunk = require("dms.chunk") local Cmd = require("dms.cmd") local Value = require("dms.value") local Queue = require("dms.queue") -local ENTR,ENAB,DISA,LOAD,VERN,USIN,STAT,DISP,ASGN,LABL,CHOI,OPTN,FORE,UNWN,WHLE,FNWR,FNNR,IFFF,ELIF,ELSE,DEFN,SKIP,COMP,INDX,JMPZ = "ENTR","ENAB","DISA","LOAD","VERN","USIN","STAT","DISP","ASGN","LABL","CHOI","OPTN","FORE","????","WHLE","FNWR","FNNR","IFFF","ELIF","ELSE","DEFN","SKIP","COMP","INDX","JMPZ" +local ENTR,ENAB,DISA,LOAD,VERN,USIN,STAT,DISP,ASGN,LABL,CHOI,OPTN,FORE,UNWN,WHLE,FNWR,FNNR,IFFF,ELIF,ELSE,DEFN,SKIP,COMP,INDX,JMPZ,NOOP = "ENTR","ENAB","DISA","LOAD","VERN","USIN","STAT","DISP","ASGN","LABL","CHOI","OPTN","FORE","????","WHLE","FNWR","FNNR","IFFF","ELIF","ELSE","DEFN","SKIP","COMP","INDX","JMPZ","NOOP" local controls = {STAT,CHOI,FORE,WHLE,IFFF,ELIF,ELSE} local flags = {ENTR,ENAB,DISA,LOAD,VERN,USIN,DEFN} local recognizedFlags = { @@ -15,16 +16,17 @@ local recognizedFlags = { } local parser = {} parser.__index = parser -local iStack = Stack:new() -local fStack = Stack:new() -local wStack = Stack:new() -function parser:new(path) +local controlStack = Stack:new() -- Handles If/elseif/else while/for loops +function parser:new(path,cc) local c = {} setmetatable(c,self) + if cc then + c.internal = true + end c.filename = path or error("Must provied a path!") - c.content = io.open(c.filename,"rb"):read("*a") + c.content = io.open(c.filename,"rb"):read("*a") .. "\n" c.flags = {} - c.chunks = {} + c.chunks = cc or {} c.ver = {1,0,0} c.pos = 0 c.lines = {} @@ -70,7 +72,7 @@ function parser:manageFlag(line) if not self:isRecognizedFlag(dat) then self:warn("Flag \""..dat.."\" is not recognized!",line) end self.flags[dat] = false elseif flag == LOAD then - -- TODO + parser:new(dat,self.chunks):parse() elseif flag == VERN then local v local a,b,c = dat:match("(%d*)%.?(%d*)%.?(%d*)") @@ -295,7 +297,6 @@ function parser:parse() end if line=="" then goto continue end ::back:: - self.current_lineStats = {line_num,self.filename} if line:match("^%[[_:,%w%(%)]+%]") then groupStack:append{line_num,group,STAT,self.filename,line:trim()} noblock = false @@ -331,17 +332,17 @@ function parser:parse() end elseif line:match("[%s,%$_%w]*=%s*[%l_][%w_]-%(.+%)") then groupStack:append{line_num,group,FNWR,self.filename,line:trim()} + elseif line:trim():match("[%s,%$_%w]-\".+\"") == line:trim():match(".+") then + groupStack:append{line_num,group,DISP,self.filename,line:trim()} elseif line:match("elseif%s*(.+)") then groupStack:append{line_num,group,ELIF,self.filename,line:trim()} elseif line:match("if%s*(.+)") then groupStack:append{line_num,group,IFFF,self.filename,line:trim()} elseif line:match("else%s*(.+)") then groupStack:append{line_num,group,ELSE,self.filename,line:trim()} - elseif line:match("[%l_][%w_]-%(.+%)") then + elseif line:match("[%l_][%w_]-%(.+%)") and not line:match("[%s,%$_%w]-=(.+)") then groupStack:append{line_num,group,FNNR,self.filename,line:trim()} - elseif line:match("\"(.+)\"") and not line:match("=.-\".-\"") then - groupStack:append{line_num,group,DISP,self.filename,line:trim()} - elseif line:match("[%s,%$_%w]-=(.+)") then + elseif line:match("[%s,%$_%w]-=(.+)") and not line:match("[%l_][%w_]-%(.+%)") then groupStack:append{line_num,group,ASGN,self.filename,line:trim()} else groupStack:append{line_num,group,UNWN,self.filename,line:trim()} @@ -359,31 +360,37 @@ function parser:parse() return k1[1]","<" function parser:JMPZ(v,label) - local cmd = Cmd:new({self.current_lineStats[1],0,JMPZ,self.current_lineStats[2],"?"},JMPZ,{label = label,var = v}) + if not v then error("Fix this now!!!") end + local cmd = Cmd:new({self.current_line[1],self.current_line[2],JMPZ,self.current_line[4],"?"},JMPZ,{label = label,var = v}) function cmd:tostring() return self.args.var .. ", " ..self.args.label end self.current_chunk:addCmd(cmd) end +function parser:NOOP() + local cmd = Cmd:new({self.current_line[1],self.current_line[2],NOOP,self.current_line[4],"?"},NOOP,{}) + function cmd:tostring() + return "" + end + self.current_chunk:addCmd(cmd) +end +local fStack = Stack:new() +local function checkELIS() + local stackfix = fStack:peek()[3] + --print("STACK TEST:",stackfix) + if stackfix then stackfix() fStack:peek()[3]=nil end +end +function parser:processIFFFBlock() + local test = self:peek() + local dat = fStack:peek() + local labelE,labelN = dat[1],dat[2] + --print("Current line is an",self.current_line[3],self.current_line[5]) + --print(test[3]) + if self.current_line[3] == ELIF then + self:parseFNNR({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"JUMP(\""..labelE.."\")"}) + self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::"..labelN.."::"}) + elseif self.current_line[3] == ELSE then + self:parseFNNR({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"JUMP(\""..labelE.."\")"}) + self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::"..labelN.."::"}) + else + --print("Popping FStack") + fStack:pop() + self:parseFNNR({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"JUMP(\""..labelE.."\")"}) + self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::"..labelE.."::"}) + end +end +function parser:parseELSE(line) + checkELIS() + local cmd = Cmd:new() + self:NOOP() + --self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::".."WTF".."::"}) + self.current_chunk:setScope(function() + local labelE = fStack:pop()[1] + self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::"..labelE.."::"}) + end) -- Finishes the IFFF scope +end function parser:parseIFFF(line) - line[5] = self:logicChop(line[5]) - print(line[5]) - local v = self:parseExpr(line[5]) + local tempfunc + if fStack:count()>0 then + --print("We have a nested if going on... Lets work on this") + local dat = fStack:peek() + local lE,lN = dat[1],dat[2] + local lG = gen("$labelNext_") + fStack:peek()[3] = function() + --print("HERE WE ARE!",lE,lN,lG) + self:parseFNNR({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"JUMP(\""..lE.."\")"}) + self:parseLABL({self.current_line[1],self.current_line[2],self.current_line[3],self.current_line[4],"::"..lN.."::"}) + end + end + local l = self:logicChop(line[5]) + local v = self:parseExpr(l) local labelE = gen("$labelEnd_") - self:JMPZ(v,labelE) - iStack:push({cmds = Queue:new()}) - io.read() + local labelN = gen("$labelNext_") + self:JMPZ(v,labelN) + fStack:push({labelE,labelN}) + self.current_chunk:setScope(function() + self:processIFFFBlock() + end) -- Sets the scope to IFFF. The chunk object handles everything +end +function parser:parseELIF(line) + checkELIS() + line[5] = line[5]:sub(5,-1) + line[5] = self:logicChop(line[5]) + local v = self:parseExpr(line[5]) + local labelN = gen("$labelNext_") + fStack:peek()[2]=labelN + self:JMPZ(v,labelN) + self.current_chunk:setScope(function() + self:processIFFFBlock() + end) -- Continues the scope to ELIF. end function parser:buildLogic(l,o,r,v) - local cmd = Cmd:new({self.current_lineStats[1],0,COMP,self.current_lineStats[2],"?"},COMP,{left=l,op=o,right=r,var=v}) + local cmd = Cmd:new({self.current_line[1],self.current_line[2],COMP,self.current_line[4],"?"},COMP,{left=l,op=o,right=r,var=v}) function cmd:tostring() return table.concat({self.args.op,tostring(self.args.left),tostring(self.args.right)},", ").." -> "..self.args.var end self.current_chunk:addCmd(cmd) end function parser:buildIndex(name,ind,v) - local cmd = Cmd:new({self.current_lineStats[1],0,INDX,self.current_lineStats[2],"?"},INDX,{name = name, index = ind, var = v}) + local cmd = Cmd:new({self.current_line[1],self.current_line[2],INDX,self.current_line[3],"?"},INDX,{name = name, index = ind, var = v}) function cmd:tostring() return table.concat({tostring(self.args.name),tostring(self.args.index)},", ").." -> "..self.args.var end @@ -440,8 +522,7 @@ end function parser:logicChop(expr) expr = expr:gsub("([_%w]+)(%b())",function(func,args) local v = gen("$") - print(v.." = "..func..args) - local fnwr = {self.current_lineStats[1],0,FWNR,self.current_lineStats[2],v.." = "..func..args} + local fnwr = {self.current_line[1],self.current_line[2],FWNR,self.current_line[4],v.." = "..func..args} self:parseFNWR(fnwr) return v end) @@ -466,7 +547,7 @@ function parser:logicChop(expr) if l~='' then o = op else - self:error("Invalid Syntax 2") + self:error("Invalid Syntax",self.current_line) end end local function index(right) @@ -488,7 +569,6 @@ function parser:logicChop(expr) elem = elem .. v elseif l~= "" and r=="" then v = gen("$") - print(l.."["..ind.."] -> "..v) l = v end if not(c=="]") then @@ -594,8 +674,7 @@ function parser:logicChop(expr) elem = elem .. v end else - print(l,o,r) - self:error("Invalid syntax!") + self:error("Invalid syntax!",self.current_line) end else elem = elem .. c @@ -660,19 +739,17 @@ function parser:chop(expr) for l,o,r in expr:gmatch("(.-)([/%^%+%-%*%%])(.+)") do if r:match("(.-)([/%^%+%-%*%%])(.+)") then local v = gen("$") - --print(l,o,self:chop(r),"->",v) self:buildMFunc(l,o,self:chop(r),v) return v else local v = gen("$") - --print(l,o,r,"->",v) self:buildMFunc(l,o,r,v) return v end end end function parser:buildMFunc(l,o,r,v) - local fnwr = {self.current_lineStats[1],0,FWNR,self.current_lineStats[2]} + local fnwr = {self.current_line[1],self.current_line[2],FWNR,self.current_line[4]} local line if o == "+" then line = v.." = ADD("..table.concat({l,r},",")..")" @@ -693,6 +770,7 @@ function parser:buildMFunc(l,o,r,v) self:parseFNWR(fnwr) end function parser:parseExpr(expr) + if not expr:match("[/%^%+%-%*%%]") then --[[print("No math to do!")]] return expr end -- handle pharanses expr=expr:gsub("([%W])(%-%d)",function(b,a) return b.."(0-"..a:match("%d+")..")" @@ -700,7 +778,7 @@ function parser:parseExpr(expr) -- Work on functions expr = expr:gsub("([_%w]+)(%b())",function(func,args) local v = gen("$") - local fnwr = {self.current_lineStats[1],0,FWNR,self.current_lineStats[2],v.." = "..func..args} + local fnwr = {self.current_line[1],self.current_line[2],FWNR,self.current_line[4],v.." = "..func..args} self:parseFNWR(fnwr) return v end) diff --git a/dump.dat b/dump.dat new file mode 100644 index 0000000..a2ea257 Binary files /dev/null and b/dump.dat differ diff --git a/loadtest.dms b/loadtest.dms new file mode 100644 index 0000000..01cf47d --- /dev/null +++ b/loadtest.dms @@ -0,0 +1,6 @@ +[Fancy] + "This was loaded!" + "Weeeeeee" +[maintest] + "Lets go" + "Oooooweee" \ No newline at end of file diff --git a/test.dms b/test.dms index 3149860..b84149f 100644 --- a/test.dms +++ b/test.dms @@ -2,7 +2,7 @@ entry main enable warnings //enable debugging define -loadfile test.dat +loadfile loadtest.dms define version 1.2 using extendedDefine as @@ -51,17 +51,25 @@ using extendedDefine as ... if (func(123)!=name[1] or true == "Bob") and foodCount >= 10.34 "test=true or test2=false!" - elseif cond - ... + "help me" + if cool == true + "We are here" + "Nested if" + elseif food >= 21 + "This is getting weird" + "Hi" + elseif (func2(321)!=name2[1] or true == "Bob2") and foodCount2 >= 100.78 + "This Block" else - ... + "That Block" + "ah this is why no pop" [Ryan:char] age = 24 money = 100 - [test:env] + "test" [newblock:function()] "Test #2"