commit - 2be87f778a56964007d4c5ccf7171fa000149f79
commit + 9828682d540b975b38136ea29d9e2d4821f3442b
blob - 771e0898b66bd3ce7b85cd60ab72614d746765e4
blob + cf4055f93e6f1181a01b395d5b0428d13ee87d33
--- tools/6c
+++ tools/6c
-----------------------------------------------------------------------
-- TOKEN MATCHING
-----------------------------------------------------------------------
-local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" }
-- This is kinda a double definition but fix later :^)
local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" }
for i = 1, len do
local s = intstr:sub(len - i + 1, len - i + 1)
+ if s:match("[0-9]") == false then
+ return nil
+ end
s = s * (10 ^ (i - 1))
res = res + s
end
return result
end
+
+
-----------------------------------------------------------------------
+-- EXPRESSION SOLVING
+-----------------------------------------------------------------------
+
+local function subarray(array, start, last)
+ if last == nil then
+ last = #array
+ end
+
+ local sub = { }
+
+ for i, v in ipairs(array) do
+ if i >= start and i <= last then
+ table.insert(sub, array[i])
+ end
+ end
+
+ return sub
+end
+
+local function finddepth(array, spos)
+ local epos = nil
+ local depth = 1
+
+ for j = spos, #array do
+ if array[j] == "(" then depth = depth + 1 end
+ if array[j] == ")" then depth = depth - 1 end
+
+ if depth == 0 then
+ epos = j
+ break
+ end
+ end
+
+ if depth ~= 0 then
+ perror("invalid nesting")
+ end
+
+ if epos == nil then perror("Mismatched paranthesis") end
+
+ return epos
+end
+
+-- Use this once the syntax validation is completed
+local function evaluate_expression(array)
+ local i = 1
+ local eval = { }
+ while i <= #array do
+ if array[i] == "(" then
+ local spos = i
+ local epos = finddepth(array, spos + 1)
+
+ local sub = { }
+ for k = spos + 1, epos - 1 do
+ table.insert(sub, array[k])
+ end
+
+ local result = evaluate_expression(sub)
+
+ for _, val in ipairs(result) do
+ table.insert(eval, val)
+ end
+
+ i = epos + 1
+ elseif array[i] == "*" then
+ local left = table.remove(eval)
+ local right = array[i + 1]
+ local epos = i + 2
+
+ if right == "(" then
+ local sub = subarray(array, i + 1)
+ right = evaluate_expression(sub)[1]
+ epos = finddepth(array, i + 2) + 1
+ end
+
+ if type(left) == "string" and type(right) == "string" then
+ if tonumber(left) ~= nil and tonumber(right) ~= nil then
+ table.insert(eval, tostring(tonumber(left) * tonumber(right)))
+
+ elseif tonumber(left) == nil and tonumber(right) ~= nil then
+ table.insert(eval, { left, tonumber(right) })
+
+ elseif tonumber(left) ~= nil and tonumber(right) == nil then
+ table.insert(eval, { right, tonumber(left) })
+
+ end
+ elseif type(left) == "table" and type(right) == "string" then
+ if tonumber(right) ~= nil then
+ table.insert(eval, { left[1], left[2] * tonumber(right) })
+ end
+ end
+
+ i = epos
+ else
+ table.insert(eval, array[i])
+ i = i + 1
+ end
+ end
+
+ local k = 1
+ local total = 0
+ local final = {}
+
+ while k < #eval do
+ local cur = eval[k]
+ local opr = eval[k + 1]
+ local nxt = eval[k + 2]
+
+ local n1 = tonumber(cur)
+ local n2 = tonumber(nxt)
+
+ if n1 ~= nil then
+ total = n1 + total
+ k = k + 1
+ elseif cur == "+" or cur == "-" then
+ if tonumber(opr) ~= nil then
+ if cur == "+" then
+ total = tonumber(opr) + total
+ elseif cur == "-" then
+ total = total - tonumber(opr)
+ end
+
+ k = k + 2
+ else
+ if type(opr) == "string" then
+ table.insert(final, {opr, 1})
+ else
+ table.insert(final, opr)
+ end
+ k = k + 2
+ end
+
+ elseif type(cur) == "string" and n2 ~= nil then
+ table.insert(final, { cur, 1 })
+ total = total + n2
+ k = k + 3
+
+ elseif type(cur) == "table" and n2 ~= nil then
+ table.insert(final, cur)
+ if opr == "-" then
+ total = total - n2
+ else
+ total = total + n2
+ end
+ k = k + 3
+
+ elseif type(cur) == "table" and type(nxt) == "string" then
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "string" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, { nxt, 1 })
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "table" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, nxt)
+ k = k + 3
+
+ else
+ k = k + 3
+ end
+ end
+
+ if total ~= 0 then
+ table.insert(final, tostring(total))
+ end
+
+ return final
+end
+-----------------------------------------------------------------------
-- Checking arguments and setting read and write file
-----------------------------------------------------------------------
-- Tokenizing
-----------------------------------------------------------------------
-local nline = 0
+local nline = 1
while true do
local line = src:read("*l")
if line == nil then
blob - c40eacaa915eea26d8db27517a070e966ab2c204
blob + 037ae3288d68a6b0a53ce2301d8fade58d65088c
--- tools/6l
+++ tools/6l
-----------------------------------------------------------------------
-- TOKEN MATCHING
-----------------------------------------------------------------------
-local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" }
-- This is kinda a double definition but fix later :^)
local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" }
for i = 1, len do
local s = intstr:sub(len - i + 1, len - i + 1)
+ if s:match("[0-9]") == false then
+ return nil
+ end
s = s * (10 ^ (i - 1))
res = res + s
end
return result
end
+
+
-----------------------------------------------------------------------
+-- EXPRESSION SOLVING
+-----------------------------------------------------------------------
+
+local function subarray(array, start, last)
+ if last == nil then
+ last = #array
+ end
+
+ local sub = { }
+
+ for i, v in ipairs(array) do
+ if i >= start and i <= last then
+ table.insert(sub, array[i])
+ end
+ end
+
+ return sub
+end
+
+local function finddepth(array, spos)
+ local epos = nil
+ local depth = 1
+
+ for j = spos, #array do
+ if array[j] == "(" then depth = depth + 1 end
+ if array[j] == ")" then depth = depth - 1 end
+
+ if depth == 0 then
+ epos = j
+ break
+ end
+ end
+
+ if depth ~= 0 then
+ perror("invalid nesting")
+ end
+
+ if epos == nil then perror("Mismatched paranthesis") end
+
+ return epos
+end
+
+-- Use this once the syntax validation is completed
+local function evaluate_expression(array)
+ local i = 1
+ local eval = { }
+ while i <= #array do
+ if array[i] == "(" then
+ local spos = i
+ local epos = finddepth(array, spos + 1)
+
+ local sub = { }
+ for k = spos + 1, epos - 1 do
+ table.insert(sub, array[k])
+ end
+
+ local result = evaluate_expression(sub)
+
+ for _, val in ipairs(result) do
+ table.insert(eval, val)
+ end
+
+ i = epos + 1
+ elseif array[i] == "*" then
+ local left = table.remove(eval)
+ local right = array[i + 1]
+ local epos = i + 2
+
+ if right == "(" then
+ local sub = subarray(array, i + 1)
+ right = evaluate_expression(sub)[1]
+ epos = finddepth(array, i + 2) + 1
+ end
+
+ if type(left) == "string" and type(right) == "string" then
+ if tonumber(left) ~= nil and tonumber(right) ~= nil then
+ table.insert(eval, tostring(tonumber(left) * tonumber(right)))
+
+ elseif tonumber(left) == nil and tonumber(right) ~= nil then
+ table.insert(eval, { left, tonumber(right) })
+
+ elseif tonumber(left) ~= nil and tonumber(right) == nil then
+ table.insert(eval, { right, tonumber(left) })
+
+ end
+ elseif type(left) == "table" and type(right) == "string" then
+ if tonumber(right) ~= nil then
+ table.insert(eval, { left[1], left[2] * tonumber(right) })
+ end
+ end
+
+ i = epos
+ else
+ table.insert(eval, array[i])
+ i = i + 1
+ end
+ end
+
+ local k = 1
+ local total = 0
+ local final = {}
+
+ while k < #eval do
+ local cur = eval[k]
+ local opr = eval[k + 1]
+ local nxt = eval[k + 2]
+
+ local n1 = tonumber(cur)
+ local n2 = tonumber(nxt)
+
+ if n1 ~= nil then
+ total = n1 + total
+ k = k + 1
+ elseif cur == "+" or cur == "-" then
+ if tonumber(opr) ~= nil then
+ if cur == "+" then
+ total = tonumber(opr) + total
+ elseif cur == "-" then
+ total = total - tonumber(opr)
+ end
+
+ k = k + 2
+ else
+ if type(opr) == "string" then
+ table.insert(final, {opr, 1})
+ else
+ table.insert(final, opr)
+ end
+ k = k + 2
+ end
+
+ elseif type(cur) == "string" and n2 ~= nil then
+ table.insert(final, { cur, 1 })
+ total = total + n2
+ k = k + 3
+
+ elseif type(cur) == "table" and n2 ~= nil then
+ table.insert(final, cur)
+ if opr == "-" then
+ total = total - n2
+ else
+ total = total + n2
+ end
+ k = k + 3
+
+ elseif type(cur) == "table" and type(nxt) == "string" then
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "string" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, { nxt, 1 })
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "table" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, nxt)
+ k = k + 3
+
+ else
+ k = k + 3
+ end
+ end
+
+ if total ~= 0 then
+ table.insert(final, tostring(total))
+ end
+
+ return final
+end
+-----------------------------------------------------------------------
-- Checking arguments
-----------------------------------------------------------------------
progname = "6l"
-- You cannot multiply the base reg (not allowed according to manual)
-- You can only multiply index reg by a factor of 2 up to max value 8 (1, 2, 4, 8)
elseif op.type == tk_type["["] then
- local brackets = { opened = 0, closed = 0 }
+ local expr = { }
+ local depth = 0
while true do
local pre = op
" line " .. op.line)
end
- if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" }) == false then
+ if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" , "[", "(" }) == false then
perror("Base register `" .. gettokenkey(op) ..
"` can only be applied + or - on it line " .. op.line)
- elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*" }) == false then
+ elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*", "(", "[" }) == false then
perror("Index register `" .. gettokenkey(op) ..
"` can only be applied +, - or * on it line " .. op.line)
end
table.insert(ret.memblock.regs, gettokenkey(op))
+ table.insert(expr, gettokenkey(op))
elseif typematch(op, { "hexadecimal", "integer" }) then
if typematch(pre, { "[", arithmetics }) == false then
perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw ..
" line " .. op.line)
end
+
+ if op.type == tk_type["hexadecimal"] then
+ table.insert(expr, tostring(hexval(op.raw)))
+ elseif op.type == tk_type["integer"] then
+ table.insert(expr, tostring(intval(op.raw)))
+ end
+
-- Other arithmetic symbols
elseif isarithmetic(op) == true then
- if typematch(pre, { regs8, "hexadecimal", "integer" }) == false then
+ if typematch(pre, { regs8, "hexadecimal", "integer", ")" }) == false then
perror("illegal token before " .. gettokenkey(op) .. " at line " .. op.line)
end
+
+ if #ret.memblock.regs == 1 and typematch(pre, { regs8 }) == true and typematch(op, { "+", "-" } ) == false then
+ perror("Base register `" .. gettokenkey(pre) ..
+ "` can only be applied + or - on it line " .. op.line)
+ end
+ table.insert(expr, gettokenkey(op))
+
+ elseif op.type == tk_type["("] then
+ if typematch(pre, { regs8, arithmetics, "(", "[" , "hexadecimal", "integer" }) == false then
+ perror("illegal token befor `(` at line " .. op.line)
+ end
+
+ table.insert(expr, "(")
+ depth = depth + 1
+ elseif op.type == tk_type[")"] then
+ if typematch(pre, { regs8, "hexadecimal", ")", "integer" }) == false then
+ perror("illegal token before `)` at line " .. op.line)
+ end
+
+ table.insert(expr, ")")
+ depth = depth - 1
else
perror("illegal token " .. gettokenkey(op) .. " at line " .. op.line)
end
end
end
+ if depth ~= 0 then
+ perror("Mismatching paranthesis at line " .. op.line)
+ end
+
if op.type ~= tk_type["]"] then
perror("Missing closing `]` at line " .. op.line)
end
+ local e = evaluate_expression(expr)
+ --[[
+ for _,v in ipairs(e) do
+ if type(v) == "string" then
+ io.write(v, " ")
+ else
+ io.write("{")
+ io.write(v[1], ", ")
+ io.write(v[2], "")
+ io.write("} ")
+ end
+ end
+ io.write("\n")
+ io.write("\n")
+ ]]--
+
+ ret.memblock.expression = e
table.insert(ret.details, ASM_MEM8)
ret.opcount = 1
+
elseif op.type == tk_type["\n"] then
ret.opcount = 0
else
regs = { },
dispsize = 0,
blevel = 0,
+ expression = nil
}
}
return ret
elseif opcount == 1 then
-- amslyze caps it at 2
+ return ret
else
if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
local dstmap = regmap[gettokenkey(inst.operands[1])]
-- 10 memory 32 bit displacement
-- 11 register to register
elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then
+ local mod = "00"
+
return ret
end
end
elseif hdr.type == tk_type["cli"] then
writeu8(dst, hexval("0hFA"))
+
+ elseif hdr.type == tk_type["int"] then
+ local opcount = #inst.details
+
+ if opcount ~= 1 then
+ perror("int takes 1 operand at line " .. hdr.line)
+ end
+
+ if inst.details[1] ~= ASM_IMM8 then
+ perror("int requires an immediate 8 byte value")
+ end
+
+ writeu8(dst, hexval("0hCD"))
+
+ if inst.operands[1].type == tk_type["hexadecimal"] then
+ writeu8(dst, hexval(inst.operands[1].raw))
+ elseif inst.operands[1].type == tk_type["integer"] then
+ writeu8(dst, intval(inst.operands[1].raw))
+ end
end
end
end
blob - 6d39970a0aa2f1314e3971c97ecf869d5bff94ec
blob + 5ab188ebc6559ddc93627d47140bf87ce8a562de
--- tools/boot.sc
+++ tools/boot.sc
asm {
_start:
+ mov ah, 0h0e
+ mov al, 0h61
+ int 0h10
+ mov [ al + 0h100 ], bl
hlt
}
blob - 73c6a396f089b292270ae57e9209b940ccaa8b91
blob + 4f1f15f1abbc7a87e724565092403922576b4833
--- tools/compiler.lua
+++ tools/compiler.lua
-- Tokenizing
-----------------------------------------------------------------------
-local nline = 0
+local nline = 1
while true do
local line = src:read("*l")
if line == nil then
blob - 88127113ea6e94d8819871d58c5f49c92ed74cda
blob + aff9c78043627789dc3802f77df40ac91a3b049b
--- tools/linker.lua
+++ tools/linker.lua
-- You cannot multiply the base reg (not allowed according to manual)
-- You can only multiply index reg by a factor of 2 up to max value 8 (1, 2, 4, 8)
elseif op.type == tk_type["["] then
- local brackets = { opened = 0, closed = 0 }
+ local expr = { }
+ local depth = 0
while true do
local pre = op
" line " .. op.line)
end
- if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" }) == false then
+ if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" , "[", "(" }) == false then
perror("Base register `" .. gettokenkey(op) ..
"` can only be applied + or - on it line " .. op.line)
- elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*" }) == false then
+ elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*", "(", "[" }) == false then
perror("Index register `" .. gettokenkey(op) ..
"` can only be applied +, - or * on it line " .. op.line)
end
table.insert(ret.memblock.regs, gettokenkey(op))
+ table.insert(expr, gettokenkey(op))
elseif typematch(op, { "hexadecimal", "integer" }) then
if typematch(pre, { "[", arithmetics }) == false then
perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw ..
" line " .. op.line)
end
+
+ if op.type == tk_type["hexadecimal"] then
+ table.insert(expr, tostring(hexval(op.raw)))
+ elseif op.type == tk_type["integer"] then
+ table.insert(expr, tostring(intval(op.raw)))
+ end
+
-- Other arithmetic symbols
elseif isarithmetic(op) == true then
- if typematch(pre, { regs8, "hexadecimal", "integer" }) == false then
+ if typematch(pre, { regs8, "hexadecimal", "integer", ")" }) == false then
perror("illegal token before " .. gettokenkey(op) .. " at line " .. op.line)
end
+
+ if #ret.memblock.regs == 1 and typematch(pre, { regs8 }) == true and typematch(op, { "+", "-" } ) == false then
+ perror("Base register `" .. gettokenkey(pre) ..
+ "` can only be applied + or - on it line " .. op.line)
+ end
+ table.insert(expr, gettokenkey(op))
+
+ elseif op.type == tk_type["("] then
+ if typematch(pre, { regs8, arithmetics, "(", "[" , "hexadecimal", "integer" }) == false then
+ perror("illegal token befor `(` at line " .. op.line)
+ end
+
+ table.insert(expr, "(")
+ depth = depth + 1
+ elseif op.type == tk_type[")"] then
+ if typematch(pre, { regs8, "hexadecimal", ")", "integer" }) == false then
+ perror("illegal token before `)` at line " .. op.line)
+ end
+
+ table.insert(expr, ")")
+ depth = depth - 1
else
perror("illegal token " .. gettokenkey(op) .. " at line " .. op.line)
end
end
end
+ if depth ~= 0 then
+ perror("Mismatching paranthesis at line " .. op.line)
+ end
+
if op.type ~= tk_type["]"] then
perror("Missing closing `]` at line " .. op.line)
end
+ local e = evaluate_expression(expr)
+ --[[
+ for _,v in ipairs(e) do
+ if type(v) == "string" then
+ io.write(v, " ")
+ else
+ io.write("{")
+ io.write(v[1], ", ")
+ io.write(v[2], "")
+ io.write("} ")
+ end
+ end
+ io.write("\n")
+ io.write("\n")
+ ]]--
+
+ ret.memblock.expression = e
table.insert(ret.details, ASM_MEM8)
ret.opcount = 1
+
elseif op.type == tk_type["\n"] then
ret.opcount = 0
else
regs = { },
dispsize = 0,
blevel = 0,
+ expression = nil
}
}
return ret
elseif opcount == 1 then
-- amslyze caps it at 2
+ return ret
else
if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
local dstmap = regmap[gettokenkey(inst.operands[1])]
-- 10 memory 32 bit displacement
-- 11 register to register
elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then
+ local mod = "00"
+
return ret
end
end
elseif hdr.type == tk_type["cli"] then
writeu8(dst, hexval("0hFA"))
+
+ elseif hdr.type == tk_type["int"] then
+ local opcount = #inst.details
+
+ if opcount ~= 1 then
+ perror("int takes 1 operand at line " .. hdr.line)
+ end
+
+ if inst.details[1] ~= ASM_IMM8 then
+ perror("int requires an immediate 8 byte value")
+ end
+
+ writeu8(dst, hexval("0hCD"))
+
+ if inst.operands[1].type == tk_type["hexadecimal"] then
+ writeu8(dst, hexval(inst.operands[1].raw))
+ elseif inst.operands[1].type == tk_type["integer"] then
+ writeu8(dst, intval(inst.operands[1].raw))
+ end
end
end
end
blob - ae98f98922a5a8d6611cabb8da4d82c4cefa68c7
blob + fb968cda91cacb539c610a579f1f4f914ebc3164
--- tools/util.lua
+++ tools/util.lua
-----------------------------------------------------------------------
-- TOKEN MATCHING
-----------------------------------------------------------------------
-local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" }
-- This is kinda a double definition but fix later :^)
local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" }
for i = 1, len do
local s = intstr:sub(len - i + 1, len - i + 1)
+ if s:match("[0-9]") == false then
+ return nil
+ end
s = s * (10 ^ (i - 1))
res = res + s
end
return result
end
+
+
+-----------------------------------------------------------------------
+-- EXPRESSION SOLVING
+-----------------------------------------------------------------------
+
+local function subarray(array, start, last)
+ if last == nil then
+ last = #array
+ end
+
+ local sub = { }
+
+ for i, v in ipairs(array) do
+ if i >= start and i <= last then
+ table.insert(sub, array[i])
+ end
+ end
+
+ return sub
+end
+
+local function finddepth(array, spos)
+ local epos = nil
+ local depth = 1
+
+ for j = spos, #array do
+ if array[j] == "(" then depth = depth + 1 end
+ if array[j] == ")" then depth = depth - 1 end
+
+ if depth == 0 then
+ epos = j
+ break
+ end
+ end
+
+ if depth ~= 0 then
+ perror("invalid nesting")
+ end
+
+ if epos == nil then perror("Mismatched paranthesis") end
+
+ return epos
+end
+
+-- Use this once the syntax validation is completed
+local function evaluate_expression(array)
+ local i = 1
+ local eval = { }
+ while i <= #array do
+ if array[i] == "(" then
+ local spos = i
+ local epos = finddepth(array, spos + 1)
+
+ local sub = { }
+ for k = spos + 1, epos - 1 do
+ table.insert(sub, array[k])
+ end
+
+ local result = evaluate_expression(sub)
+
+ for _, val in ipairs(result) do
+ table.insert(eval, val)
+ end
+
+ i = epos + 1
+ elseif array[i] == "*" then
+ local left = table.remove(eval)
+ local right = array[i + 1]
+ local epos = i + 2
+
+ if right == "(" then
+ local sub = subarray(array, i + 1)
+ right = evaluate_expression(sub)[1]
+ epos = finddepth(array, i + 2) + 1
+ end
+
+ if type(left) == "string" and type(right) == "string" then
+ if tonumber(left) ~= nil and tonumber(right) ~= nil then
+ table.insert(eval, tostring(tonumber(left) * tonumber(right)))
+
+ elseif tonumber(left) == nil and tonumber(right) ~= nil then
+ table.insert(eval, { left, tonumber(right) })
+
+ elseif tonumber(left) ~= nil and tonumber(right) == nil then
+ table.insert(eval, { right, tonumber(left) })
+
+ end
+ elseif type(left) == "table" and type(right) == "string" then
+ if tonumber(right) ~= nil then
+ table.insert(eval, { left[1], left[2] * tonumber(right) })
+ end
+ end
+
+ i = epos
+ else
+ table.insert(eval, array[i])
+ i = i + 1
+ end
+ end
+
+ local k = 1
+ local total = 0
+ local final = {}
+
+ while k < #eval do
+ local cur = eval[k]
+ local opr = eval[k + 1]
+ local nxt = eval[k + 2]
+
+ local n1 = tonumber(cur)
+ local n2 = tonumber(nxt)
+
+ if n1 ~= nil then
+ total = n1 + total
+ k = k + 1
+ elseif cur == "+" or cur == "-" then
+ if tonumber(opr) ~= nil then
+ if cur == "+" then
+ total = tonumber(opr) + total
+ elseif cur == "-" then
+ total = total - tonumber(opr)
+ end
+
+ k = k + 2
+ else
+ if type(opr) == "string" then
+ table.insert(final, {opr, 1})
+ else
+ table.insert(final, opr)
+ end
+ k = k + 2
+ end
+
+ elseif type(cur) == "string" and n2 ~= nil then
+ table.insert(final, { cur, 1 })
+ total = total + n2
+ k = k + 3
+
+ elseif type(cur) == "table" and n2 ~= nil then
+ table.insert(final, cur)
+ if opr == "-" then
+ total = total - n2
+ else
+ total = total + n2
+ end
+ k = k + 3
+
+ elseif type(cur) == "table" and type(nxt) == "string" then
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "string" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, { nxt, 1 })
+ k = k + 3
+
+ elseif type(cur) == "string" and type(nxt) == "table" then
+ table.insert(final, { cur, 1 })
+ table.insert(final, nxt)
+ k = k + 3
+
+ else
+ k = k + 3
+ end
+ end
+
+ if total ~= 0 then
+ table.insert(final, tostring(total))
+ end
+
+ return final
+end