Help with tables

I’m trying to make a calculator, and this is how it works:

  1. The player clicks any buttons on the calculator gui and it adds whatever they clicked to a table that is in a module.
  2. When they click ‘=’ it calculates whatever they put in, and shows the result.

What I need help with is, in the table there’s everything they put in, and I need to somehow calculate that.

If you don’t know what I mean, this is the script:

local equals = script.Parent
local frame = equals.Parent
local main = frame.Parent
local result = main.Result
local inputModule = game.ReplicatedStorage.Input
local inputTable = require(inputModule)

equals.MouseButton1Click:Connect(function()
    local calculation = ""
    for _,input in pairs(inputTable) do
        calculation ..= input
    end
    if calculation ~= nil then
        result.Text = calculation
    else
        result.Text = "Error"
    end
end)

^ ‘calculation’ is a string, instead I basically want it to literally DO it. (Calculate it)

Example, you put 3+6*7, the table would literally be {3,+,6,*,7}, then the loop makes a string: 3+6*7 (‘calculation’ variable), which I want to solve instead of making a string, and make (‘result’)'s text, that.

Is there a way I can do this?

There are multiple solutions in this thread check it out.

1 Like

Sounds like someone is making a lexer. Which is interesting.

To make a lexer, you need to break down each “token”.
Something like this.

INPUT: 1 + 3 + 3 + 4
OUTPUT: {1, +, 3, +, 3, 4}

INPUT:(3+4+6)/15 * 16 ^ 18
OUTPUT: {(3, +, 4, +, 6, ), /, 15, *, 16, ^, 18}

So after you are able to turn strings into that, you will have to compute everything “inside” a parenthesis.
After all operations inside parentheses are computed, compute all the exponentiation, division, and multiplication, and finally, run it from the first index to the last, adding and subtracting all those numbers.

Adding functions (e.g. sine) is just as simple as they can be treated like a special token.

You will have to use a parser.

The easiest option is probably to use dthecoolest’s answer for parsing. It seems that all you have to do is load a string expression and do something with the output.

Another option would be to write a parser yourself. This is not the most practical thing to do, but it can be quite educational. Normally, you would be able to use Lua’s ‘load’ global, but I believe that it is not available in ROBLOX. Also, things can get quite complicated, cause you cannot just iterate through an equation from start to finish. For example, the equation ‘3 * 4 ^ 2’ cannot be solved like this:

  1. 3 * 4 ^ 2
  2. != 12 ^ 2
  3. = 144

To do this you can use what’s called the “shunting yard algorithm”, explained for instance in Comp Sci in 5: Shunting Yard Algorithm - YouTube.

Here’s a calculate function I wrote based on that video. I’m only supporting * and +, and also not doing any checking to see if what is entered is valid, so if you actually used this you might want to add that or wrap it in a pcall.

	function tokenize(expression)
	-- turn an expression to a table of tokens
	-- for example "42+3141*271" -> {42, "+", 3141, "*", 271}

	local result = {}

	local part = ""
	for i = 1, #expression do
	    local character = expression:sub(i,i)
	    if character == "+" or character == "*" then
	    	if part ~= "" then
	    		table.insert(result, tonumber(part))
	    		part = ""
	    	end
	    	table.insert(result, character)
	    else
	    	part = part .. character
	    end
	end
	if part ~= "" then
		table.insert(result, tonumber(part))
	end

	return result
end

function to_postfix(tokens)
	-- shunting yard algorithm learned from 
	-- https://www.youtube.com/watch?v=Wz85Hiwi5MY
	stack = {}
	queue = {}

	for _, token in pairs(tokens) do
		if token == "*" then
			-- Push on top of stack
			table.insert(stack, 1, "*")
		elseif token == "+" then
			-- First move any multiplications from stack to the queue
			while #stack > 0 and stack[1] == "*" do
				table.remove(stack, 1)
				table.insert(queue, "*")
			end

			-- Push + on top of stack
			table.insert(stack, 1, "+")
		else
			-- Numbers go in the queue
			table.insert(queue, token)
		end
	end

	-- Finally move anything left in the stack onto the queue
	while #stack > 0 do
		table.insert(queue, table.remove(stack, 1))
	end

	return queue
end

function calculate_postfix(postfix)
	local stack = {}
	for _, token in pairs(postfix) do
		local isNumber = token ~= "+" and token ~= "*"
		if isNumber then
			-- Push operand on stack
			table.insert(stack, 1, token)
		else
			-- Pop operands from stack, compute result and push it on stack
			if #stack < 2 then
				print("Tried to compute", token, "but operands were missing")
				return
			end
			local a = table.remove(stack, 1)
			local b = table.remove(stack, 1)
			if token == "+" then
				table.insert(stack, 1, a + b)
			end
			if token == "*" then
				table.insert(stack, 1, a * b)
			end
		end
	end
	return table.remove(stack, 1)
end

function calculate(expression)
	-- Convert to tokens, then to postfix and calculate
	local tokens = tokenize(expression)
	local postfix = to_postfix(tokens)
	local result = calculate_postfix(postfix)
	return result
end

print(calculate("42+3141*271"))
1 Like

You can use loadstring to do it. First, you have to tick LoadstringEnabled in ServerScriptService. Then, you can use loadstring(calculation). I haven’t tested this so please tell me if it doesn’t work.

One of the posts in that thread helped me, thank you.


What I exactly did:
I used remote events and loadstring to calculate it.

Example if anyone else needs help with a similar issue idk

When = is clicked, use remote events/functions to send the input to the server, calculate it, send it back and enter the result.