Commit Diff


commit - 9828682d540b975b38136ea29d9e2d4821f3442b
commit + cc1b538ae080ea83a96421aa59d0fa35078f44a2
blob - cf4055f93e6f1181a01b395d5b0428d13ee87d33
blob + c115f66915a6581fd4af49849b22d0dcb8fdc0ea
--- tools/6c
+++ tools/6c
@@ -264,23 +264,7 @@ 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 function findcb(array, spos)
 	local epos = nil
 	local depth = 1
 
@@ -294,141 +278,168 @@ local function finddepth(array, spos)
 		end
 	end
 
-	if depth ~= 0 then
-		perror("invalid nesting")
+	if depth ~= 0 or epos == nil then
+		print("Missing closing bracket")
+		os.exit(1)
 	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 ast = { }
+
+ast.gennode = function(data)
+	local node = { }
+	if tonumber(data) ~= nil then
+		node = {	
+			left = nil,
+			right = nil,
+			data = { "number", data }
+		}
+	elseif data == "+" or data == "-" or data == "*" or data == "/" then
+		node = {
+			left = nil,
+			right = nil,
+			data = { "custom", data }
+		}
+	else
+		node = {
+			left = nil,
+			right = nil,
+			data = { "variable", data }
+		}
+	end
+
+	return node
+end
+
+ast.genast = function(expr)
+	-- PASS 1 for paranthesis
 	local i = 1
-	local eval = { }
-	while i <= #array do
-		if array[i] == "(" then
-			local spos = i
-			local epos = finddepth(array, spos + 1)
+	while i <= #expr do
+		if expr[i] == "(" then
+			local epos = findcb(expr, i + 1)
+			local sub = {}
 
-			local sub = { }
-			for k = spos + 1, epos - 1 do
-				table.insert(sub, array[k])
-			end
+			for j = i + 1, epos - 1 do
+				table.insert(sub, expr[j])
+			end	
 
-			local result = evaluate_expression(sub)
+			local subtree = ast.genast(sub)
+			table.remove(expr, i)
 
-			for _, val in ipairs(result) do
-				table.insert(eval, val)
+			for j = i, epos - 1 do
+				table.remove(expr, i)
 			end
 
-			i = epos + 1
-		elseif array[i] == "*" then
-			local left = table.remove(eval)
-			local right = array[i + 1]
-			local epos = i + 2
+			table.insert(expr, i, subtree)
+		else
+			i = i + 1
+		end
+	end
 
-			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)))
+	-- PASS 2 for multiplication / divisions
+	i = 1
+	while i <= #expr do
+		if expr[i] == "*" or expr[i] == "/" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-				elseif tonumber(left) == nil and tonumber(right) ~= nil then
-					table.insert(eval, { left, tonumber(right) })
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
 
-				elseif tonumber(left) ~= nil and tonumber(right) == nil then
-					table.insert(eval, { right, tonumber(left) })
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
+		else
+			i = i + 1
+		end
+	end
 
-				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
+	-- PASS 3 for additions / substractions
+	i = 1
+	local node = nil
+	while i <= #expr do
+		if expr[i] == "+" or expr[i] == "-" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-			i = epos
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
+
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
 		else
-			table.insert(eval, array[i])
 			i = i + 1
 		end
 	end
+	return expr[1]
+end
 
-	local k = 1
-	local total = 0
-	local final = {}
+ast.eval = function(node)
+	if node.data[1] == "number" then
+		return { tonumber(node.data[2]) or 0 }
+	end
 
-	while k < #eval do
-		local cur = eval[k]
-		local opr = eval[k + 1]
-		local nxt = eval[k + 2]
+	if node.data[1] == "variable" then
+		return { { node.data[2], 1 } }
+	end
 
-		local n1 = tonumber(cur)
-		local n2 = tonumber(nxt)
+	local leftval = ast.eval(node.left)
+	local rightval = ast.eval(node.right)
 
-		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
+	local op = node.data[2]
+	local result = {}
 
-				k = k + 2
-			else
-				if type(opr) == "string" then
-					table.insert(final, {opr, 1})
-				else
-					table.insert(final, opr)
-				end
-				k = k + 2
-			end
+	if op == "+" or op == "-" then
+		local con = 0
 
-		elseif type(cur) == "string" and n2 ~= nil then
-			table.insert(final, { cur, 1 })
-			total = total + n2
-			k = k + 3
+		for _, term in ipairs(leftval) do
+			table.insert(result, term)
+		end
 
-		elseif type(cur) == "table" and n2 ~= nil then
-			table.insert(final, cur)
-			if opr == "-" then
-				total = total - n2
+		for _, term in ipairs(rightval) do
+			if type(term) == "table" then
+				local var = term[1]
+				local mul = term[2]
+
+				local res = (op == "+") and mul or -mul
+
+				table.insert(result, {var, res})
 			else
-				total = total + n2
+				local res = (op == "+") and term or -term
+				con = con + res
 			end
-			k = k + 3
+		end
 
-		elseif type(cur) == "table" and type(nxt) == "string" then
-			k = k + 3
+		if con ~= 0 then
+			table.insert(result, con)
+		end
 
-		elseif type(cur) == "string" and type(nxt) == "string" then
-			table.insert(final, { cur, 1 })
-			table.insert(final, { nxt, 1 })
-			k = k + 3
+		return result
+	elseif op == "*" then
+		for _, l in ipairs(leftval) do
+			for _, r in ipairs(rightval) do
+				if type(l) == "number" and type(r) == "number" then
+					table.insert(result, l * r)
 
-		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
+				elseif type(l) == "number" and type(r) == "table" then
+					table.insert(result, { r[1], r[2] * l })
+	
+				elseif type(l) == "table" and type(r) == "number" then
+					table.insert(result, { l[1], l[2] * r })
+				end
+			end
 		end
-	end
 
-	if total ~= 0 then
-		table.insert(final, tostring(total))
+		return result
 	end
-
-	return final
 end
 -----------------------------------------------------------------------
 -- Checking arguments and setting read and write file
blob - 037ae3288d68a6b0a53ce2301d8fade58d65088c
blob + 3ea7054e411f2f3630fcdc2c110483cf51399ce4
--- tools/6l
+++ tools/6l
@@ -264,23 +264,7 @@ 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 function findcb(array, spos)
 	local epos = nil
 	local depth = 1
 
@@ -294,141 +278,168 @@ local function finddepth(array, spos)
 		end
 	end
 
-	if depth ~= 0 then
-		perror("invalid nesting")
+	if depth ~= 0 or epos == nil then
+		print("Missing closing bracket")
+		os.exit(1)
 	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 ast = { }
+
+ast.gennode = function(data)
+	local node = { }
+	if tonumber(data) ~= nil then
+		node = {	
+			left = nil,
+			right = nil,
+			data = { "number", data }
+		}
+	elseif data == "+" or data == "-" or data == "*" or data == "/" then
+		node = {
+			left = nil,
+			right = nil,
+			data = { "custom", data }
+		}
+	else
+		node = {
+			left = nil,
+			right = nil,
+			data = { "variable", data }
+		}
+	end
+
+	return node
+end
+
+ast.genast = function(expr)
+	-- PASS 1 for paranthesis
 	local i = 1
-	local eval = { }
-	while i <= #array do
-		if array[i] == "(" then
-			local spos = i
-			local epos = finddepth(array, spos + 1)
+	while i <= #expr do
+		if expr[i] == "(" then
+			local epos = findcb(expr, i + 1)
+			local sub = {}
 
-			local sub = { }
-			for k = spos + 1, epos - 1 do
-				table.insert(sub, array[k])
-			end
+			for j = i + 1, epos - 1 do
+				table.insert(sub, expr[j])
+			end	
 
-			local result = evaluate_expression(sub)
+			local subtree = ast.genast(sub)
+			table.remove(expr, i)
 
-			for _, val in ipairs(result) do
-				table.insert(eval, val)
+			for j = i, epos - 1 do
+				table.remove(expr, i)
 			end
 
-			i = epos + 1
-		elseif array[i] == "*" then
-			local left = table.remove(eval)
-			local right = array[i + 1]
-			local epos = i + 2
+			table.insert(expr, i, subtree)
+		else
+			i = i + 1
+		end
+	end
 
-			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)))
+	-- PASS 2 for multiplication / divisions
+	i = 1
+	while i <= #expr do
+		if expr[i] == "*" or expr[i] == "/" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-				elseif tonumber(left) == nil and tonumber(right) ~= nil then
-					table.insert(eval, { left, tonumber(right) })
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
 
-				elseif tonumber(left) ~= nil and tonumber(right) == nil then
-					table.insert(eval, { right, tonumber(left) })
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
+		else
+			i = i + 1
+		end
+	end
 
-				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
+	-- PASS 3 for additions / substractions
+	i = 1
+	local node = nil
+	while i <= #expr do
+		if expr[i] == "+" or expr[i] == "-" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-			i = epos
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
+
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
 		else
-			table.insert(eval, array[i])
 			i = i + 1
 		end
 	end
+	return expr[1]
+end
 
-	local k = 1
-	local total = 0
-	local final = {}
+ast.eval = function(node)
+	if node.data[1] == "number" then
+		return { tonumber(node.data[2]) or 0 }
+	end
 
-	while k < #eval do
-		local cur = eval[k]
-		local opr = eval[k + 1]
-		local nxt = eval[k + 2]
+	if node.data[1] == "variable" then
+		return { { node.data[2], 1 } }
+	end
 
-		local n1 = tonumber(cur)
-		local n2 = tonumber(nxt)
+	local leftval = ast.eval(node.left)
+	local rightval = ast.eval(node.right)
 
-		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
+	local op = node.data[2]
+	local result = {}
 
-				k = k + 2
-			else
-				if type(opr) == "string" then
-					table.insert(final, {opr, 1})
-				else
-					table.insert(final, opr)
-				end
-				k = k + 2
-			end
+	if op == "+" or op == "-" then
+		local con = 0
 
-		elseif type(cur) == "string" and n2 ~= nil then
-			table.insert(final, { cur, 1 })
-			total = total + n2
-			k = k + 3
+		for _, term in ipairs(leftval) do
+			table.insert(result, term)
+		end
 
-		elseif type(cur) == "table" and n2 ~= nil then
-			table.insert(final, cur)
-			if opr == "-" then
-				total = total - n2
+		for _, term in ipairs(rightval) do
+			if type(term) == "table" then
+				local var = term[1]
+				local mul = term[2]
+
+				local res = (op == "+") and mul or -mul
+
+				table.insert(result, {var, res})
 			else
-				total = total + n2
+				local res = (op == "+") and term or -term
+				con = con + res
 			end
-			k = k + 3
+		end
 
-		elseif type(cur) == "table" and type(nxt) == "string" then
-			k = k + 3
+		if con ~= 0 then
+			table.insert(result, con)
+		end
 
-		elseif type(cur) == "string" and type(nxt) == "string" then
-			table.insert(final, { cur, 1 })
-			table.insert(final, { nxt, 1 })
-			k = k + 3
+		return result
+	elseif op == "*" then
+		for _, l in ipairs(leftval) do
+			for _, r in ipairs(rightval) do
+				if type(l) == "number" and type(r) == "number" then
+					table.insert(result, l * r)
 
-		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
+				elseif type(l) == "number" and type(r) == "table" then
+					table.insert(result, { r[1], r[2] * l })
+	
+				elseif type(l) == "table" and type(r) == "number" then
+					table.insert(result, { l[1], l[2] * r })
+				end
+			end
 		end
-	end
 
-	if total ~= 0 then
-		table.insert(final, tostring(total))
+		return result
 	end
-
-	return final
 end
 -----------------------------------------------------------------------
 -- Checking arguments
@@ -566,7 +577,7 @@ local function operlyze(op, ret)
 			end
 
 			if isregs8(op) == true then
-				if typematch(pre, { "[", arithmetics }) == false then
+				if typematch(pre, { "[", "(", arithmetics }) == false then
 					perror("missing arithmetic prefix for register " .. gettokenkey(op) ..
 						" line " .. op.line)
 				end
@@ -582,7 +593,7 @@ local function operlyze(op, ret)
 				table.insert(expr, gettokenkey(op))
 
 			elseif typematch(op, { "hexadecimal", "integer" }) then
-				if typematch(pre, { "[", arithmetics }) == false then
+				if typematch(pre, { "[", "(", arithmetics }) == false then
 					perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw ..
 						" line " .. op.line)
 				end
@@ -636,21 +647,23 @@ local function operlyze(op, ret)
 			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
+		local gen = ast.genast(expr)
+		local exp = ast.eval(gen)
+
+		for _, v in ipairs(exp) do
+			if type(v) == "table" then
 				io.write("{")
-				io.write(v[1], ", ")
-				io.write(v[2], "")
+				io.write(v[1])
+				io.write(", ")
+				io.write(v[2])
 				io.write("} ")
+			else
+				io.write(tonumber(v))
 			end
 		end
+
 		io.write("\n")
 		io.write("\n")
-		]]--
 
 		ret.memblock.expression = e
 		table.insert(ret.details, ASM_MEM8)
@@ -765,6 +778,19 @@ local function instvaluate(inst)
 		elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then
 			local mod = "00"
 
+			local reg1 = nil
+			local reg2 = nil
+			local dstmap = "000"
+			local srcmap = "000"
+
+			for i = 1, #inst.memblock.regs do
+				if reg1 == nil then
+					reg1 = inst.memblock.regs[i]
+				elseif reg2 == nil then
+					reg2 = inst.memblock.regs[i]
+				end
+			end
+
 			return ret
 		end
 	end
blob - 5ab188ebc6559ddc93627d47140bf87ce8a562de
blob + fb5ebec9b76df12de540c6dba0bef4bca2d5dc53
--- tools/boot.sc
+++ tools/boot.sc
@@ -3,6 +3,6 @@ _start:
 	mov ah, 0h0e
 	mov al, 0h61
 	int 0h10
-	mov [ al + 0h100 ], bl
+	mov [ ((al)) + (bl * 100) * 4 + 0h100 ], bl
 	hlt
 }
blob - aff9c78043627789dc3802f77df40ac91a3b049b
blob + 8d86957439a3fd2605f9b14d39de96c8bc135663
--- tools/linker.lua
+++ tools/linker.lua
@@ -134,7 +134,7 @@ local function operlyze(op, ret)
 			end
 
 			if isregs8(op) == true then
-				if typematch(pre, { "[", arithmetics }) == false then
+				if typematch(pre, { "[", "(", arithmetics }) == false then
 					perror("missing arithmetic prefix for register " .. gettokenkey(op) ..
 						" line " .. op.line)
 				end
@@ -150,7 +150,7 @@ local function operlyze(op, ret)
 				table.insert(expr, gettokenkey(op))
 
 			elseif typematch(op, { "hexadecimal", "integer" }) then
-				if typematch(pre, { "[", arithmetics }) == false then
+				if typematch(pre, { "[", "(", arithmetics }) == false then
 					perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw ..
 						" line " .. op.line)
 				end
@@ -204,21 +204,23 @@ local function operlyze(op, ret)
 			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
+		local gen = ast.genast(expr)
+		local exp = ast.eval(gen)
+
+		for _, v in ipairs(exp) do
+			if type(v) == "table" then
 				io.write("{")
-				io.write(v[1], ", ")
-				io.write(v[2], "")
+				io.write(v[1])
+				io.write(", ")
+				io.write(v[2])
 				io.write("} ")
+			else
+				io.write(tonumber(v))
 			end
 		end
+
 		io.write("\n")
 		io.write("\n")
-		]]--
 
 		ret.memblock.expression = e
 		table.insert(ret.details, ASM_MEM8)
@@ -333,6 +335,19 @@ local function instvaluate(inst)
 		elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then
 			local mod = "00"
 
+			local reg1 = nil
+			local reg2 = nil
+			local dstmap = "000"
+			local srcmap = "000"
+
+			for i = 1, #inst.memblock.regs do
+				if reg1 == nil then
+					reg1 = inst.memblock.regs[i]
+				elseif reg2 == nil then
+					reg2 = inst.memblock.regs[i]
+				end
+			end
+
 			return ret
 		end
 	end
blob - fb968cda91cacb539c610a579f1f4f914ebc3164
blob + 118b7570602f441e01aed443d89312149213e293
--- tools/util.lua
+++ tools/util.lua
@@ -262,23 +262,7 @@ 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 function findcb(array, spos)
 	local epos = nil
 	local depth = 1
 
@@ -292,139 +276,166 @@ local function finddepth(array, spos)
 		end
 	end
 
-	if depth ~= 0 then
-		perror("invalid nesting")
+	if depth ~= 0 or epos == nil then
+		print("Missing closing bracket")
+		os.exit(1)
 	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 ast = { }
+
+ast.gennode = function(data)
+	local node = { }
+	if tonumber(data) ~= nil then
+		node = {	
+			left = nil,
+			right = nil,
+			data = { "number", data }
+		}
+	elseif data == "+" or data == "-" or data == "*" or data == "/" then
+		node = {
+			left = nil,
+			right = nil,
+			data = { "custom", data }
+		}
+	else
+		node = {
+			left = nil,
+			right = nil,
+			data = { "variable", data }
+		}
+	end
+
+	return node
+end
+
+ast.genast = function(expr)
+	-- PASS 1 for paranthesis
 	local i = 1
-	local eval = { }
-	while i <= #array do
-		if array[i] == "(" then
-			local spos = i
-			local epos = finddepth(array, spos + 1)
+	while i <= #expr do
+		if expr[i] == "(" then
+			local epos = findcb(expr, i + 1)
+			local sub = {}
 
-			local sub = { }
-			for k = spos + 1, epos - 1 do
-				table.insert(sub, array[k])
-			end
+			for j = i + 1, epos - 1 do
+				table.insert(sub, expr[j])
+			end	
 
-			local result = evaluate_expression(sub)
+			local subtree = ast.genast(sub)
+			table.remove(expr, i)
 
-			for _, val in ipairs(result) do
-				table.insert(eval, val)
+			for j = i, epos - 1 do
+				table.remove(expr, i)
 			end
 
-			i = epos + 1
-		elseif array[i] == "*" then
-			local left = table.remove(eval)
-			local right = array[i + 1]
-			local epos = i + 2
+			table.insert(expr, i, subtree)
+		else
+			i = i + 1
+		end
+	end
 
-			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)))
+	-- PASS 2 for multiplication / divisions
+	i = 1
+	while i <= #expr do
+		if expr[i] == "*" or expr[i] == "/" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-				elseif tonumber(left) == nil and tonumber(right) ~= nil then
-					table.insert(eval, { left, tonumber(right) })
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
 
-				elseif tonumber(left) ~= nil and tonumber(right) == nil then
-					table.insert(eval, { right, tonumber(left) })
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
+		else
+			i = i + 1
+		end
+	end
 
-				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
+	-- PASS 3 for additions / substractions
+	i = 1
+	local node = nil
+	while i <= #expr do
+		if expr[i] == "+" or expr[i] == "-" then
+			local left = expr[i - 1]
+			local right = expr[i + 1]
+			local opnode = ast.gennode(expr[i])
 
-			i = epos
+			opnode.left = (type(left) == "table") and left or ast.gennode(left)
+			opnode.right = (type(right) == "table") and right or ast.gennode(right)
+
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.remove(expr, i - 1)
+			table.insert(expr, i - 1, opnode)
 		else
-			table.insert(eval, array[i])
 			i = i + 1
 		end
 	end
+	return expr[1]
+end
 
-	local k = 1
-	local total = 0
-	local final = {}
+ast.eval = function(node)
+	if node.data[1] == "number" then
+		return { tonumber(node.data[2]) or 0 }
+	end
 
-	while k < #eval do
-		local cur = eval[k]
-		local opr = eval[k + 1]
-		local nxt = eval[k + 2]
+	if node.data[1] == "variable" then
+		return { { node.data[2], 1 } }
+	end
 
-		local n1 = tonumber(cur)
-		local n2 = tonumber(nxt)
+	local leftval = ast.eval(node.left)
+	local rightval = ast.eval(node.right)
 
-		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
+	local op = node.data[2]
+	local result = {}
 
-				k = k + 2
-			else
-				if type(opr) == "string" then
-					table.insert(final, {opr, 1})
-				else
-					table.insert(final, opr)
-				end
-				k = k + 2
-			end
+	if op == "+" or op == "-" then
+		local con = 0
 
-		elseif type(cur) == "string" and n2 ~= nil then
-			table.insert(final, { cur, 1 })
-			total = total + n2
-			k = k + 3
+		for _, term in ipairs(leftval) do
+			table.insert(result, term)
+		end
 
-		elseif type(cur) == "table" and n2 ~= nil then
-			table.insert(final, cur)
-			if opr == "-" then
-				total = total - n2
+		for _, term in ipairs(rightval) do
+			if type(term) == "table" then
+				local var = term[1]
+				local mul = term[2]
+
+				local res = (op == "+") and mul or -mul
+
+				table.insert(result, {var, res})
 			else
-				total = total + n2
+				local res = (op == "+") and term or -term
+				con = con + res
 			end
-			k = k + 3
+		end
 
-		elseif type(cur) == "table" and type(nxt) == "string" then
-			k = k + 3
+		if con ~= 0 then
+			table.insert(result, con)
+		end
 
-		elseif type(cur) == "string" and type(nxt) == "string" then
-			table.insert(final, { cur, 1 })
-			table.insert(final, { nxt, 1 })
-			k = k + 3
+		return result
+	elseif op == "*" then
+		for _, l in ipairs(leftval) do
+			for _, r in ipairs(rightval) do
+				if type(l) == "number" and type(r) == "number" then
+					table.insert(result, l * r)
 
-		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
+				elseif type(l) == "number" and type(r) == "table" then
+					table.insert(result, { r[1], r[2] * l })
+	
+				elseif type(l) == "table" and type(r) == "number" then
+					table.insert(result, { l[1], l[2] * r })
+				end
+			end
 		end
-	end
 
-	if total ~= 0 then
-		table.insert(final, tostring(total))
+		return result
 	end
-
-	return final
 end