Added logic and restructured labels
This commit is contained in:
parent
a6a16e614a
commit
4669f33760
44
compiler.lua
44
compiler.lua
@ -421,7 +421,9 @@ function Interpreter:new(parser)
|
|||||||
end
|
end
|
||||||
function c:visit_BinOp(node)
|
function c:visit_BinOp(node)
|
||||||
if node.op.type == PLUS then
|
if node.op.type == PLUS then
|
||||||
return self:visit(node.left) + self:visit(node.right)
|
local a,b = self:visit(node.left),self:visit(node.right)
|
||||||
|
print("ADD ",a,b)
|
||||||
|
return a + b
|
||||||
elseif node.op.type == MINUS then
|
elseif node.op.type == MINUS then
|
||||||
return self:visit(node.left) - self:visit(node.right)
|
return self:visit(node.left) - self:visit(node.right)
|
||||||
elseif node.op.type == MUL then
|
elseif node.op.type == MUL then
|
||||||
@ -450,31 +452,25 @@ end
|
|||||||
|
|
||||||
text = [[
|
text = [[
|
||||||
BEGIN
|
BEGIN
|
||||||
BEGIN
|
ret := 11+a;
|
||||||
number := 2;
|
|
||||||
a := number;
|
|
||||||
b := 10 * a + 10 * number / 4;
|
|
||||||
c := a - - b
|
|
||||||
END;
|
|
||||||
x := 11;
|
|
||||||
END.
|
END.
|
||||||
]]
|
]]
|
||||||
lexer = Lexer:new(text)
|
lexer = Lexer:new(text)
|
||||||
parser = Parser:new(lexer)
|
parser = Parser:new(lexer)
|
||||||
interpreter = Interpreter:new(parser)
|
interpreter = Interpreter:new(parser)
|
||||||
tprint(parser)
|
interpreter.GLOBAL_SCOPE = {a=100}
|
||||||
-- interpreter:interpret()
|
interpreter:interpret()
|
||||||
-- for i,v in pairs(interpreter.GLOBAL_SCOPE) do
|
for i,v in pairs(interpreter.GLOBAL_SCOPE) do
|
||||||
-- print(i,v)
|
print(i,v)
|
||||||
-- end
|
end
|
||||||
-- while true do
|
while true do
|
||||||
-- io.write("calc> ")
|
io.write("calc> ")
|
||||||
-- local text = io.read()
|
local text = io.read()
|
||||||
-- if text then
|
if text then
|
||||||
-- lexer = Lexer:new(text)
|
lexer = Lexer:new(text)
|
||||||
-- parser = Parser:new(lexer)
|
parser = Parser:new(lexer)
|
||||||
-- interpreter = Interpreter:new(parser)
|
interpreter = Interpreter:new(parser)
|
||||||
-- result = interpreter:interpret()
|
result = interpreter:interpret()
|
||||||
-- print(result)
|
print(result)
|
||||||
-- end
|
end
|
||||||
-- end
|
end
|
||||||
|
|||||||
@ -15,13 +15,13 @@ function Chunk:new(cname,ctype,filename)
|
|||||||
c.chunkname = cname
|
c.chunkname = cname
|
||||||
c.chunktype = ctype
|
c.chunktype = ctype
|
||||||
c.filename = filename
|
c.filename = filename
|
||||||
|
c.variables = {}
|
||||||
c.pos = 0
|
c.pos = 0
|
||||||
c.cmds = {}
|
c.cmds = {}
|
||||||
c.labels = {} -- ["label"] = pos
|
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
function Chunk:addLabel(label)
|
function Chunk:addVariable(value)
|
||||||
self.labels[label] = self:count()
|
self.varaiables[value.name] = value.value
|
||||||
end
|
end
|
||||||
function Chunk:addCmd(cmd)
|
function Chunk:addCmd(cmd)
|
||||||
cmd.chunk = self
|
cmd.chunk = self
|
||||||
|
|||||||
8
dms/expr.lua
Normal file
8
dms/expr.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
local Expr = {}
|
||||||
|
Expr.__index = Expr
|
||||||
|
function Expr:new(expr)
|
||||||
|
local c = {}
|
||||||
|
setmetatable(c,self)
|
||||||
|
|
||||||
|
return c
|
||||||
|
end
|
||||||
546
dms/parser.lua
546
dms/parser.lua
@ -1,8 +1,10 @@
|
|||||||
require("dms.utils")
|
require("dms.utils")
|
||||||
|
local char = string.char
|
||||||
local Stack = require("dms.stack")
|
local Stack = require("dms.stack")
|
||||||
local Chunk = require("dms.chunk")
|
local Chunk = require("dms.chunk")
|
||||||
local Cmd = require("dms.cmd")
|
local Cmd = require("dms.cmd")
|
||||||
local ENTR,ENAB,DISA,LOAD,VERN,USIN,STAT,DISP,ASGN,LABL,CHOI,OPTN,FORE,UNWN,WHLE,FNWR,FNNR,IFFF,ELIF,ELSE,DEFN = "ENTR","ENAB","DISA","LOAD","VERN","USIN","STAT","DISP","ASGN","LABL","CHOI","OPTN","FORE","????","WHLE","FNWR","FNNR","IFFF","ELIF","ELSE","DEFN"
|
local Value = require("dms.value")
|
||||||
|
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 controls = {STAT,CHOI,FORE,WHLE,IFFF,ELIF,ELSE}
|
local controls = {STAT,CHOI,FORE,WHLE,IFFF,ELIF,ELSE}
|
||||||
local flags = {ENTR,ENAB,DISA,LOAD,VERN,USIN,DEFN}
|
local flags = {ENTR,ENAB,DISA,LOAD,VERN,USIN,DEFN}
|
||||||
local recognizedFlags = {
|
local recognizedFlags = {
|
||||||
@ -103,6 +105,137 @@ function parser:isRecognizedFlag(flag)
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
function parser:split(s,pat,l)
|
||||||
|
local pat=pat or ","
|
||||||
|
local res = {}
|
||||||
|
local start = 1
|
||||||
|
local state = 0
|
||||||
|
local c = '.'
|
||||||
|
local elem = ''
|
||||||
|
local function helper()
|
||||||
|
if tonumber(elem) then
|
||||||
|
elem = tonumber(elem)
|
||||||
|
elseif elem:sub(1,1) == "\"" and elem:sub(-1,-1) == "\"" then
|
||||||
|
elem = elem:sub(2,-2)
|
||||||
|
elseif elem == "true" then
|
||||||
|
elem = true
|
||||||
|
elseif elem == "false" then
|
||||||
|
elem = false
|
||||||
|
elseif elem:sub(1,1)=="{" and elem:sub(-1,-1)=="}" then
|
||||||
|
elem = self:split(elem:sub(2,-2),nil,true)
|
||||||
|
elseif elem:match("[%-%+/%%%(%)%*%^]") then
|
||||||
|
gen("$",true) -- Flush the temp variables
|
||||||
|
elem = "\1"..self:parseExpr(elem)
|
||||||
|
else
|
||||||
|
-- \1 Tells the interperter that we need to do a lookup
|
||||||
|
elem = "\1"..elem
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local counter = 0
|
||||||
|
local function next()
|
||||||
|
counter = counter + 1
|
||||||
|
return s:sub(counter,counter)
|
||||||
|
end
|
||||||
|
local function peek()
|
||||||
|
return s:sub(counter + 1,counter + 1)
|
||||||
|
end
|
||||||
|
local function getarr()
|
||||||
|
local a = peek()
|
||||||
|
local str = ""
|
||||||
|
local open = 1
|
||||||
|
while open~=0 and a~="" do
|
||||||
|
a = next()
|
||||||
|
if a == "{" then
|
||||||
|
open = open+1
|
||||||
|
end
|
||||||
|
if a == "}" then
|
||||||
|
open = open-1
|
||||||
|
if open == 0 then
|
||||||
|
next()
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
str = str .. a
|
||||||
|
a = peek()
|
||||||
|
end
|
||||||
|
next()
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
c = true
|
||||||
|
while c~="" do
|
||||||
|
c = next()
|
||||||
|
if state == 0 or state == 3 then -- start state or space after comma
|
||||||
|
if state == 3 and c == ' ' then
|
||||||
|
state = 0 -- skipped the space after the comma
|
||||||
|
else
|
||||||
|
state = 0
|
||||||
|
if c == '"' or c=="'" then
|
||||||
|
state = 1
|
||||||
|
elem = elem .. '"'
|
||||||
|
elseif c=="{" then
|
||||||
|
local t = self:split(getarr(),nil,true)
|
||||||
|
res[#res + 1] = t
|
||||||
|
elem = ''
|
||||||
|
state = 3
|
||||||
|
elseif c == pat then
|
||||||
|
helper()
|
||||||
|
res[#res + 1] = elem
|
||||||
|
elem = ''
|
||||||
|
state = 3 -- skip over the next space if present
|
||||||
|
elseif c == "(" then
|
||||||
|
state = 1
|
||||||
|
elem = elem .. '('
|
||||||
|
else
|
||||||
|
elem = elem .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif state == 1 then -- inside quotes
|
||||||
|
if c == '"' or c=="'" then --quote detection could be done here
|
||||||
|
state = 0
|
||||||
|
elem = elem .. '"'
|
||||||
|
elseif c=="}" then
|
||||||
|
state = 0
|
||||||
|
elem = elem .. '}'
|
||||||
|
elseif c==")" then
|
||||||
|
state = 0
|
||||||
|
elem = elem .. ')'
|
||||||
|
elseif c == '\\' then
|
||||||
|
state = 2
|
||||||
|
else
|
||||||
|
elem = elem .. c
|
||||||
|
end
|
||||||
|
elseif state == 2 then -- after \ in string
|
||||||
|
elem = elem .. c
|
||||||
|
state = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
helper()
|
||||||
|
if elem ~= "" then
|
||||||
|
res[#res + 1] = elem
|
||||||
|
end
|
||||||
|
if l then
|
||||||
|
setmetatable(res,{
|
||||||
|
__tostring = function(self)
|
||||||
|
local str = "{"
|
||||||
|
for i,v in ipairs(self) do
|
||||||
|
str = str .. tostring(v) .. ", "
|
||||||
|
end
|
||||||
|
return str:sub(1,-3).."}"
|
||||||
|
end
|
||||||
|
})
|
||||||
|
else
|
||||||
|
setmetatable(res,{
|
||||||
|
__tostring = function(self)
|
||||||
|
local str = "("
|
||||||
|
for i,v in ipairs(self) do
|
||||||
|
str = str .. tostring(v) .. ", "
|
||||||
|
end
|
||||||
|
return str:sub(1,-3)..")"
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
function parser:parse()
|
function parser:parse()
|
||||||
local link = self
|
local link = self
|
||||||
local line_num = 0
|
local line_num = 0
|
||||||
@ -158,6 +291,7 @@ function parser:parse()
|
|||||||
end
|
end
|
||||||
if line=="" then goto continue end
|
if line=="" then goto continue end
|
||||||
::back::
|
::back::
|
||||||
|
self.current_lineStats = {line_num,self.filename}
|
||||||
if line:match("^%[[_:,%w%(%)]+%]") then
|
if line:match("^%[[_:,%w%(%)]+%]") then
|
||||||
groupStack:append{line_num,group,STAT,self.filename,line:trim()}
|
groupStack:append{line_num,group,STAT,self.filename,line:trim()}
|
||||||
noblock = false
|
noblock = false
|
||||||
@ -191,20 +325,20 @@ function parser:parse()
|
|||||||
else
|
else
|
||||||
goto back
|
goto back
|
||||||
end
|
end
|
||||||
elseif line:match("[%s,_%w]*=.-%(.+%)") then
|
elseif line:match("[%s,%$_%w]*=%s*[%l_][%w_]-%(.+%)") then
|
||||||
groupStack:append{line_num,group,FNWR,self.filename,line:trim()}
|
groupStack:append{line_num,group,FNWR,self.filename,line:trim()}
|
||||||
elseif line:match(".-%(.+%)") then
|
|
||||||
groupStack:append{line_num,group,FNNR,self.filename,line:trim()}
|
|
||||||
elseif line:match("[%s,_%w]*=(.+)") then
|
|
||||||
groupStack:append{line_num,group,ASGN,self.filename,line:trim()}
|
|
||||||
elseif line:match("\"(.+)\"") then
|
|
||||||
groupStack:append{line_num,group,DISP,self.filename,line:trim()}
|
|
||||||
elseif line:match("elseif%s*(.+)") then
|
elseif line:match("elseif%s*(.+)") then
|
||||||
groupStack:append{line_num,group,ELIF,self.filename,line:trim()}
|
groupStack:append{line_num,group,ELIF,self.filename,line:trim()}
|
||||||
elseif line:match("if%s*(.+)") then
|
elseif line:match("if%s*(.+)") then
|
||||||
groupStack:append{line_num,group,IFFF,self.filename,line:trim()}
|
groupStack:append{line_num,group,IFFF,self.filename,line:trim()}
|
||||||
elseif line:match("else%s*(.+)") then
|
elseif line:match("else%s*(.+)") then
|
||||||
groupStack:append{line_num,group,ELSE,self.filename,line:trim()}
|
groupStack:append{line_num,group,ELSE,self.filename,line:trim()}
|
||||||
|
elseif line:match("[%s,%$_%w]*=(.+)") then
|
||||||
|
groupStack:append{line_num,group,ASGN,self.filename,line:trim()}
|
||||||
|
elseif line:match("[%l_][%w_]-%(.+%)") then
|
||||||
|
groupStack:append{line_num,group,FNNR,self.filename,line:trim()}
|
||||||
|
elseif line:match("\"(.+)\"") then
|
||||||
|
groupStack:append{line_num,group,DISP,self.filename,line:trim()}
|
||||||
else
|
else
|
||||||
groupStack:append{line_num,group,UNWN,self.filename,line:trim()}
|
groupStack:append{line_num,group,UNWN,self.filename,line:trim()}
|
||||||
end
|
end
|
||||||
@ -240,8 +374,10 @@ function parser:parse()
|
|||||||
if chunks[cname] then self:error("Chunk \""..cname.."\" has already been defined!",v) end
|
if chunks[cname] then self:error("Chunk \""..cname.."\" has already been defined!",v) end
|
||||||
elseif v[3] == CHOI then
|
elseif v[3] == CHOI then
|
||||||
self:parseChoice(v)
|
self:parseChoice(v)
|
||||||
|
elseif v[3] == IFFF then
|
||||||
|
self:parseIFFF(v)
|
||||||
else
|
else
|
||||||
--print("CTRL",table.concat(v,"\t"))
|
print("CTRL",table.concat(v,"\t"))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if v[3] == DISP then
|
if v[3] == DISP then
|
||||||
@ -253,9 +389,9 @@ function parser:parse()
|
|||||||
elseif v[3] == ASGN then
|
elseif v[3] == ASGN then
|
||||||
self:parseASGN(v)
|
self:parseASGN(v)
|
||||||
elseif v[3] == LABL then
|
elseif v[3] == LABL then
|
||||||
self.current_chunk:addLabel(v[5]:match("::(.+)::"))
|
self:parseLABL(v)
|
||||||
end
|
end
|
||||||
--print("FUNC",table.concat(v,"\t"))
|
print("FUNC",table.concat(v,"\t"))
|
||||||
end
|
end
|
||||||
v = self:next()
|
v = self:next()
|
||||||
end
|
end
|
||||||
@ -266,19 +402,356 @@ function parser:parse()
|
|||||||
print(i,v)
|
print(i,v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local EQ,GTE,LTE,NEQ,GT,LT = "=",char(242),char(243),char(247),">","<"
|
||||||
|
function parser:parseIFFF(line)
|
||||||
|
print(line[5])
|
||||||
|
print(self:logicChop(line[5]))
|
||||||
|
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})
|
||||||
|
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})
|
||||||
|
function cmd:tostring()
|
||||||
|
return table.concat({tostring(self.args.name),tostring(self.args.index)},", ").." -> "..self.args.var
|
||||||
|
end
|
||||||
|
self.current_chunk:addCmd(cmd)
|
||||||
|
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}
|
||||||
|
self:parseFNWR(fnwr)
|
||||||
|
return v
|
||||||
|
end)
|
||||||
|
local counter = 0
|
||||||
|
local v
|
||||||
|
local function next()
|
||||||
|
counter = counter + 1
|
||||||
|
return expr:sub(counter,counter)
|
||||||
|
end
|
||||||
|
local function prev()
|
||||||
|
counter = counter - 1
|
||||||
|
end
|
||||||
|
local function peek()
|
||||||
|
return expr:sub(counter + 1,counter + 1)
|
||||||
|
end
|
||||||
|
local c = "."
|
||||||
|
local l,o,r = '','',''
|
||||||
|
local state = 0
|
||||||
|
local start = 1
|
||||||
|
local elem = ""
|
||||||
|
local function setOp(op)
|
||||||
|
if l~='' then
|
||||||
|
o = op
|
||||||
|
else
|
||||||
|
self:error("Invalid Syntax 2")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function index(right)
|
||||||
|
local ind = ""
|
||||||
|
c = peek()
|
||||||
|
while c ~= "]" do
|
||||||
|
next()
|
||||||
|
ind = ind..c
|
||||||
|
c = peek()
|
||||||
|
end
|
||||||
|
c = next()
|
||||||
|
if right then
|
||||||
|
local vv = gen("$")
|
||||||
|
v = gen("$")
|
||||||
|
r = right
|
||||||
|
self:buildIndex(r,ind,vv)
|
||||||
|
self:buildLogic(l,o,vv,v)
|
||||||
|
l,o,r = '','',''
|
||||||
|
elem = elem .. v
|
||||||
|
elseif l~= "" and r=="" then
|
||||||
|
v = gen("$")
|
||||||
|
print(l.."["..ind.."] -> "..v)
|
||||||
|
l = v
|
||||||
|
end
|
||||||
|
if not(c=="]") then
|
||||||
|
self:error("']' expected to close '['")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function default()
|
||||||
|
if c == "=" and peek()=="=" then
|
||||||
|
next() -- eat second =
|
||||||
|
setOp(EQ)
|
||||||
|
elseif c == ">" and peek()=="=" then
|
||||||
|
next()
|
||||||
|
setOp(GTE)
|
||||||
|
elseif c == "<" and peek()=="=" then
|
||||||
|
next()
|
||||||
|
setOp(LTE)
|
||||||
|
elseif c == "!" or c == "~" and peek()== "=" then
|
||||||
|
next()
|
||||||
|
setOp(NEQ)
|
||||||
|
elseif c == "<" then
|
||||||
|
setOp(LT)
|
||||||
|
elseif c == ">" then
|
||||||
|
setOp(GT)
|
||||||
|
elseif c == "[" then -- handle index stuff
|
||||||
|
index()
|
||||||
|
elseif c == "o" and peek()=="r" then
|
||||||
|
next()
|
||||||
|
elem = elem .. "+"
|
||||||
|
elseif c == "a" and peek()=="n" then
|
||||||
|
if next() == "n" and peek()=="d" then
|
||||||
|
next()
|
||||||
|
elem = elem .. "*"
|
||||||
|
else
|
||||||
|
--self:error("Invalid syntax!"..c) -- Grab the current line
|
||||||
|
end
|
||||||
|
elseif c == "i" and peek()=="f" then
|
||||||
|
next()
|
||||||
|
elseif c == ' ' then
|
||||||
|
-- Ignore white space if not part of a string
|
||||||
|
elseif isDigit(c) then
|
||||||
|
local dot = false
|
||||||
|
prev()
|
||||||
|
c = peek()
|
||||||
|
local digit = ""
|
||||||
|
while isDigit(c) or (dot==false and c==".") do
|
||||||
|
next()
|
||||||
|
if c=="." then
|
||||||
|
dot = true
|
||||||
|
digit = digit .. "."
|
||||||
|
elseif isDigit(c) then
|
||||||
|
digit = digit .. c
|
||||||
|
end
|
||||||
|
c = peek()
|
||||||
|
end
|
||||||
|
digit = tonumber(digit)
|
||||||
|
if l=="" then
|
||||||
|
l = digit
|
||||||
|
elseif r=="" then
|
||||||
|
r = digit
|
||||||
|
v = gen("$")
|
||||||
|
self:buildLogic(l,o,r,v)
|
||||||
|
l,o,r = '','',''
|
||||||
|
elem = elem .. v
|
||||||
|
end
|
||||||
|
elseif isLetter(c) then
|
||||||
|
if l=='' then
|
||||||
|
l=c
|
||||||
|
local k = peek()
|
||||||
|
while isLetter(k) or isDigit(k) do
|
||||||
|
next()
|
||||||
|
l=l..k
|
||||||
|
k = peek()
|
||||||
|
end
|
||||||
|
if l == "true" then
|
||||||
|
l = true
|
||||||
|
elseif l == "false" then
|
||||||
|
l = false
|
||||||
|
else
|
||||||
|
l = "\1" .. l
|
||||||
|
end
|
||||||
|
elseif o~= '' then
|
||||||
|
r=c
|
||||||
|
local k = peek()
|
||||||
|
while isLetter(k) or isDigit(k) do
|
||||||
|
next()
|
||||||
|
r=r..k
|
||||||
|
k = peek()
|
||||||
|
end
|
||||||
|
if k == "[" then
|
||||||
|
next()
|
||||||
|
index(r)
|
||||||
|
else
|
||||||
|
if r == "true" then
|
||||||
|
r = true
|
||||||
|
elseif r == "false" then
|
||||||
|
r = false
|
||||||
|
else
|
||||||
|
r = "\1" .. r
|
||||||
|
end
|
||||||
|
v = gen("$")
|
||||||
|
self:buildLogic(l,o,r,v)
|
||||||
|
l,o,r = '','',''
|
||||||
|
elem = elem .. v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(l,o,r)
|
||||||
|
self:error("Invalid syntax!")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
elem = elem .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local str = ""
|
||||||
|
while c~="" do
|
||||||
|
c = next()
|
||||||
|
if c == '"' then
|
||||||
|
c = peek()
|
||||||
|
str = ""
|
||||||
|
while c~="\"" do
|
||||||
|
next()
|
||||||
|
if c=="\\" and peek()=="\"" then
|
||||||
|
next()
|
||||||
|
str = str .. "\""
|
||||||
|
else
|
||||||
|
str = str .. c
|
||||||
|
end
|
||||||
|
c = peek()
|
||||||
|
end
|
||||||
|
if l=="" then
|
||||||
|
l = str
|
||||||
|
elseif r=="" then
|
||||||
|
r = str
|
||||||
|
v = gen("$")
|
||||||
|
self:buildLogic(l,o,r,v)
|
||||||
|
l,o,r = '','',''
|
||||||
|
elem = elem .. v
|
||||||
|
end
|
||||||
|
next()
|
||||||
|
elseif c == "'" then
|
||||||
|
elem = elem .. '"'
|
||||||
|
c = peek()
|
||||||
|
while c~="\"" do
|
||||||
|
next()
|
||||||
|
if c=="\\" and peek()=="\"" then
|
||||||
|
next()
|
||||||
|
elem = elem + "\""
|
||||||
|
else
|
||||||
|
elem = elem .. c
|
||||||
|
end
|
||||||
|
c = peek()
|
||||||
|
end
|
||||||
|
if l=="" then
|
||||||
|
l = str
|
||||||
|
elseif r=="" then
|
||||||
|
r = str
|
||||||
|
v = gen("$")
|
||||||
|
self:buildLogic(l,o,r,v)
|
||||||
|
l,o,r = '','',''
|
||||||
|
elem = elem .. v
|
||||||
|
end
|
||||||
|
next()
|
||||||
|
else
|
||||||
|
default()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return elem
|
||||||
|
end
|
||||||
|
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 line
|
||||||
|
if o == "+" then
|
||||||
|
line = v.." = ADD("..table.concat({l,r},",")..")"
|
||||||
|
elseif o == "-" then
|
||||||
|
line = v.." = SUB("..table.concat({l,r},",")..")"
|
||||||
|
elseif o == "*" then
|
||||||
|
line = v.." = MUL("..table.concat({l,r},",")..")"
|
||||||
|
elseif o == "/" then
|
||||||
|
line = v.." = DIV("..table.concat({l,r},",")..")"
|
||||||
|
elseif o == "%" then
|
||||||
|
line = v.." = MOD("..table.concat({l,r},",")..")"
|
||||||
|
elseif o == "^" then
|
||||||
|
line = v.." = POW("..table.concat({l,r},",")..")"
|
||||||
|
else
|
||||||
|
-- Soon we will allow for custom symbols for now error
|
||||||
|
end
|
||||||
|
table.insert(fnwr,line)
|
||||||
|
self:parseFNWR(fnwr)
|
||||||
|
end
|
||||||
|
function parser:parseExpr(expr)
|
||||||
|
-- handle pharanses
|
||||||
|
expr=expr:gsub("([%W])(%-%d)",function(b,a)
|
||||||
|
return b.."(0-"..a:match("%d+")..")"
|
||||||
|
end)
|
||||||
|
-- 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}
|
||||||
|
self:parseFNWR(fnwr)
|
||||||
|
return v
|
||||||
|
end)
|
||||||
|
expr = expr:gsub("(%b())",function(a)
|
||||||
|
return self:parseExpr(a:sub(2,-2))
|
||||||
|
end)
|
||||||
|
return self:chop(expr)
|
||||||
|
end
|
||||||
|
function parser:parseChoice(line)
|
||||||
|
local text = line[5]:match("\"(.+)\"")
|
||||||
|
local copt = self:peek()
|
||||||
|
local choice = {text = text,options = {}}
|
||||||
|
local cmd = Cmd:new(line,CHOI,choice)
|
||||||
|
function cmd:tostring()
|
||||||
|
return "\""..self.args.text.."\" {"..table.concat(self.args.options,", ").."}"-- disp choices
|
||||||
|
end
|
||||||
|
self.current_chunk:addCmd(cmd)
|
||||||
|
if copt[3]~=OPTN then
|
||||||
|
self:error("Choices must have at least one option to choose!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local opts = {}
|
||||||
|
while copt do
|
||||||
|
copt = self:next()
|
||||||
|
local a,b = copt[5]:match("(.+) %s*(.+)")
|
||||||
|
table.insert(choice.options,a)
|
||||||
|
table.insert(opts,b)
|
||||||
|
copt = self:peek()
|
||||||
|
if copt[3]~=OPTN then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local s = ((#opts-1)*2-1)
|
||||||
|
local c = s
|
||||||
|
for i=1,#opts do
|
||||||
|
self:parseFNNR({copt[1],copt[2],FNNR,copt[4],opts[i]})
|
||||||
|
if i~=#opts then
|
||||||
|
self:parseFNNR({copt[1],copt[2],FNNR,copt[4],"SKIP(".. c ..")"})
|
||||||
|
end
|
||||||
|
c=c-2
|
||||||
|
end
|
||||||
|
end
|
||||||
function parser:parseFNNR(line)
|
function parser:parseFNNR(line)
|
||||||
local fname, args = line[5]:match("(.-)%((.+)%)")
|
local fname, args = line[5]:match("(.-)%((.*)%)")
|
||||||
args = args:split()
|
if #args==0 then
|
||||||
|
args = {}
|
||||||
|
else
|
||||||
|
args = self:split(args)
|
||||||
|
end
|
||||||
local cmd = Cmd:new(line,FNNR,{func=fname,args=args})
|
local cmd = Cmd:new(line,FNNR,{func=fname,args=args})
|
||||||
function cmd:tostring()
|
function cmd:tostring()
|
||||||
return table.concat({fname,table.concat(args,", ")},", ")
|
if #args==0 then
|
||||||
|
return fname
|
||||||
|
else
|
||||||
|
return table.concat({fname,table.concat(args,", ")},", ")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
self.current_chunk:addCmd(cmd)
|
self.current_chunk:addCmd(cmd)
|
||||||
end
|
end
|
||||||
function parser:parseFNWR(line)
|
function parser:parseFNWR(line)
|
||||||
local vars, fname, args = line[5]:match("(.-)%s*=%s*(.-)%((.+)%)")
|
local vars, fname, args = line[5]:match("(.-)%s*=%s*(.-)%((.+)%)")
|
||||||
vars = vars:split()
|
vars = self:split(vars)
|
||||||
args = args:split()
|
if #args==0 then
|
||||||
|
args = {}
|
||||||
|
else
|
||||||
|
args = self:split(args)
|
||||||
|
end
|
||||||
local cmd = Cmd:new(line,FNWR,{func=fname,args=args,vars=vars})
|
local cmd = Cmd:new(line,FNWR,{func=fname,args=args,vars=vars})
|
||||||
function cmd:tostring()
|
function cmd:tostring()
|
||||||
return table.concat({fname,table.concat(args,", ")},", ").." -> ".. table.concat(vars,", ")
|
return table.concat({fname,table.concat(args,", ")},", ").." -> ".. table.concat(vars,", ")
|
||||||
@ -287,34 +760,33 @@ function parser:parseFNWR(line)
|
|||||||
end
|
end
|
||||||
function parser:parseASGN(line)
|
function parser:parseASGN(line)
|
||||||
local vars,assigns = line[5]:match("(.-)%s*=%s*(.+)")
|
local vars,assigns = line[5]:match("(.-)%s*=%s*(.+)")
|
||||||
vars = vars:split()
|
vars = self:split(vars)
|
||||||
assigns = assigns:split()
|
assigns = self:split(assigns)
|
||||||
local cmd = Cmd:new(line,ASGN,{vars = vars, assigns = assigns})
|
local list = {}
|
||||||
|
for i,v in ipairs(vars) do
|
||||||
|
table.insert(list,Value:new(v,assigns[i]))
|
||||||
|
end
|
||||||
|
local cmd = Cmd:new(line,ASGN,list)
|
||||||
function cmd:tostring()
|
function cmd:tostring()
|
||||||
return "DATA -> "..table.concat(vars,", ")
|
local str = ""
|
||||||
|
for i,v in ipairs(self.args) do
|
||||||
|
str = str .. "(" .. tostring(v) .. " -> ".. v.name ..")" .. ", "
|
||||||
|
end
|
||||||
|
return str:sub(1,-3)
|
||||||
end
|
end
|
||||||
self.current_chunk:addCmd(cmd)
|
self.current_chunk:addCmd(cmd)
|
||||||
-- TODO: make dict lookups builtin
|
-- TODO: make dict lookups builtin
|
||||||
end
|
end
|
||||||
function parser:parseChoice(line)
|
function parser:parseLABL(line)
|
||||||
local text = line[5]:match("\"(.+)\"")
|
local label = line[5]:match("::(.+)::")
|
||||||
local copt = self:peek()
|
if not label then
|
||||||
local choice = {text = text}
|
self:error("Invalid Label Definition",line)
|
||||||
local cmd = Cmd:new(line,CHOI,choice)
|
|
||||||
if copt[3]~=OPTN then
|
|
||||||
self:error("Choices must have at least one option to choose!")
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
while copt do
|
local cmd = Cmd:new(line,LABL,{label = label})
|
||||||
copt = self:next()
|
function cmd:tostring()
|
||||||
local a,b = copt[5]:match("(.+) %s*(.+)")
|
return self.args.label
|
||||||
print(a,"|",b)
|
|
||||||
copt = self:peek()
|
|
||||||
if copt[3]~=OPTN then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- We need to get functions working first
|
self.current_chunk:addCmd(cmd)
|
||||||
end
|
end
|
||||||
function parser:parseDialogue(line)
|
function parser:parseDialogue(line)
|
||||||
local targ,text = line[5]:match("(%w*)%s*(.*)")
|
local targ,text = line[5]:match("(%w*)%s*(.*)")
|
||||||
|
|||||||
108
dms/utils.lua
108
dms/utils.lua
@ -1,4 +1,37 @@
|
|||||||
-- Utils modify the global enviroment
|
-- Utils modify the global enviroment
|
||||||
|
local symcount = {}
|
||||||
|
local syms = {}
|
||||||
|
for i=65,90 do
|
||||||
|
syms[#syms+1] = string.char(i)
|
||||||
|
end
|
||||||
|
for i=97,122 do
|
||||||
|
syms[#syms+1] = string.char(i)
|
||||||
|
end
|
||||||
|
local count = #syms+1
|
||||||
|
function gen(symbol,flush)
|
||||||
|
if flush == true then
|
||||||
|
symcount[symbol] = {1, 0}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
symbol = symbol or "__"
|
||||||
|
if symcount[symbol] then
|
||||||
|
symcount[symbol][2] = symcount[symbol][2] + 1
|
||||||
|
if symcount[symbol][2]%count==0 then
|
||||||
|
symcount[symbol][2] = 1
|
||||||
|
symcount[symbol][1] = symcount[symbol][1] + 1
|
||||||
|
end
|
||||||
|
return symbol .. syms[symcount[symbol][1]%count]..syms[symcount[symbol][2]%count]
|
||||||
|
else
|
||||||
|
symcount[symbol] = {1, 0}
|
||||||
|
return gen(symbol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function isLetter(c)
|
||||||
|
return c:lower():match("[%$_%l]")
|
||||||
|
end
|
||||||
|
function isDigit(c)
|
||||||
|
return c:lower():match("%d")
|
||||||
|
end
|
||||||
function string.tabs(str)
|
function string.tabs(str)
|
||||||
local c = 0
|
local c = 0
|
||||||
for i in str:gmatch(".") do
|
for i in str:gmatch(".") do
|
||||||
@ -21,80 +54,9 @@ function tprint (tbl, indent)
|
|||||||
print(formatting)
|
print(formatting)
|
||||||
tprint(v, indent+1)
|
tprint(v, indent+1)
|
||||||
elseif type(v) == 'boolean' then
|
elseif type(v) == 'boolean' then
|
||||||
print(formatting .. tostring(v))
|
print(formatting .. "<" .. type(v).. ">" .. tostring(v))
|
||||||
else
|
else
|
||||||
print(formatting .. v)
|
print(formatting .. "<" .. type(v).. ">" .. tostring(v))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
function string.split(s,pat)
|
|
||||||
local pat=pat or ","
|
|
||||||
local res = {}
|
|
||||||
local start = 1
|
|
||||||
local state = 0
|
|
||||||
local c = '.'
|
|
||||||
local elem = ''
|
|
||||||
local function helper()
|
|
||||||
if tonumber(elem) then
|
|
||||||
elem = tonumber(elem)
|
|
||||||
elseif elem:sub(1,1) == "\"" and elem:sub(-1,-1) == "\"" then
|
|
||||||
elem = elem:sub(2,-2)
|
|
||||||
elseif elem == "true" then
|
|
||||||
elem = true
|
|
||||||
elseif elem == "false" then
|
|
||||||
elem = false
|
|
||||||
elseif elem:sub(1,1) == "{" and elem:sub(-1,-1)=="}" then
|
|
||||||
elem = elem:sub(2,-2):split()
|
|
||||||
else
|
|
||||||
elem = "\1"..elem
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i = 1, #s do
|
|
||||||
c = s:sub(i, i)
|
|
||||||
if state == 0 or state == 3 then -- start state or space after comma
|
|
||||||
if state == 3 and c == ' ' then
|
|
||||||
state = 0 -- skipped the space after the comma
|
|
||||||
else
|
|
||||||
state = 0
|
|
||||||
if c == '"' or c=="'" then
|
|
||||||
state = 1
|
|
||||||
elem = elem .. '"'
|
|
||||||
elseif c=="{" then
|
|
||||||
state = 1
|
|
||||||
elem = elem .. '{'
|
|
||||||
elseif c == pat then
|
|
||||||
helper()
|
|
||||||
res[#res + 1] = elem
|
|
||||||
elem = ''
|
|
||||||
state = 3 -- skip over the next space if present
|
|
||||||
elseif c == "(" then
|
|
||||||
state = 1
|
|
||||||
elem = elem .. '('
|
|
||||||
else
|
|
||||||
elem = elem .. c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif state == 1 then -- inside quotes
|
|
||||||
if c == '"' or c=="'" then --quote detection could be done here
|
|
||||||
state = 0
|
|
||||||
elem = elem .. '"'
|
|
||||||
elseif c=="}" then
|
|
||||||
state = 0
|
|
||||||
elem = elem .. '}'
|
|
||||||
elseif c==")" then
|
|
||||||
state = 0
|
|
||||||
elem = elem .. ')'
|
|
||||||
elseif c == '\\' then
|
|
||||||
state = 2
|
|
||||||
else
|
|
||||||
elem = elem .. c
|
|
||||||
end
|
|
||||||
elseif state == 2 then -- after \ in string
|
|
||||||
elem = elem .. c
|
|
||||||
state = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
helper()
|
|
||||||
res[#res + 1] = elem
|
|
||||||
return res
|
|
||||||
end
|
end
|
||||||
33
dms/value.lua
Normal file
33
dms/value.lua
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
local Value = {}
|
||||||
|
Value.__index = Value
|
||||||
|
local c = string.char
|
||||||
|
local types = {
|
||||||
|
string = c(0x0),
|
||||||
|
lookup = "",
|
||||||
|
boolean = c(0x2),
|
||||||
|
table = c(0x3),
|
||||||
|
number = c(0x4)
|
||||||
|
}
|
||||||
|
function Value:__tostring()
|
||||||
|
local t = self.type
|
||||||
|
return types[t]..tostring(self.value)
|
||||||
|
end
|
||||||
|
function Value:new(name,value)
|
||||||
|
local c = {}
|
||||||
|
setmetatable(c,self)
|
||||||
|
c.type = type(value)
|
||||||
|
c.value = value
|
||||||
|
if c.type=="string" and c.value:sub(1,1)=="\1" then
|
||||||
|
c.type = "lookup"
|
||||||
|
end
|
||||||
|
c.name = name
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function Value:set(value)
|
||||||
|
self.type = type(value)
|
||||||
|
self.value = value
|
||||||
|
end
|
||||||
|
function Value:get()
|
||||||
|
return self.value
|
||||||
|
end
|
||||||
|
return Value
|
||||||
14
test.dms
14
test.dms
@ -13,8 +13,10 @@ using extendedDefine as
|
|||||||
|
|
||||||
Ryan "Hello how are you doing?" // this is a comment
|
Ryan "Hello how are you doing?" // this is a comment
|
||||||
Bob "I'm good you?"
|
Bob "I'm good you?"
|
||||||
|
|
||||||
|
tester = "Hello"
|
||||||
|
|
||||||
list = {1,2,3},true,"This is a string!",false, {3,2,1}
|
list,test = {{1,2+food,3},true,tester,123,"This is a string!",false, {3,2,1}},5
|
||||||
a = list[1]
|
a = list[1]
|
||||||
/*
|
/*
|
||||||
heheheh
|
heheheh
|
||||||
@ -22,15 +24,19 @@ using extendedDefine as
|
|||||||
ghgfh
|
ghgfh
|
||||||
kjuty
|
kjuty
|
||||||
*/
|
*/
|
||||||
|
hungry = (-2+4-((5*5)/sqrt(144+5)))^2*2+2
|
||||||
list[1] = "Hello"
|
list[1] = "Hello"
|
||||||
var1,var2 = func(1,"string", 2+5)
|
var1,var2 = func(1,"string", 2+5)
|
||||||
func(1,"string", 2+5)
|
a = 100 + func(1,"string", 2+5) + 100
|
||||||
|
func(1,"string", 2+5)
|
||||||
::label::
|
::label::
|
||||||
//Hello im testing stuff
|
//Hello im testing stuff
|
||||||
|
|
||||||
choice "Pick one:"
|
choice "Pick one:"
|
||||||
"first" func()
|
"first" func()
|
||||||
"second" func()
|
"second" func()
|
||||||
"third" func()
|
"third" func()
|
||||||
|
"forth" func()
|
||||||
|
|
||||||
for x = 1,10
|
for x = 1,10
|
||||||
for y = 1,10
|
for y = 1,10
|
||||||
@ -43,8 +49,8 @@ using extendedDefine as
|
|||||||
|
|
||||||
while cond
|
while cond
|
||||||
...
|
...
|
||||||
if cond
|
if (func(123)!=name[1] or true == "Bob") and foodCount >= 10.34
|
||||||
...
|
"test=true or test2=false!"
|
||||||
elseif cond
|
elseif cond
|
||||||
...
|
...
|
||||||
else
|
else
|
||||||
|
|||||||
11
test.lua
Normal file
11
test.lua
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
||||||
|
require("dms.utils")
|
||||||
|
--require("dms.parser")
|
||||||
|
parser = {}
|
||||||
|
|
||||||
|
|
||||||
|
print(parser:logicChop([[if (func(123)!=name[1] or true == "Bob") and foodCount >= 10.34]]))
|
||||||
|
-- function parser:parseLogic(expr)
|
||||||
|
-- expr = expr:gsub("")
|
||||||
|
-- end
|
||||||
|
-- print(parser:parseLogic([[if (name=="Ryan" or name == "Bob") and foodCount >= 10]]))
|
||||||
Loading…
x
Reference in New Issue
Block a user