about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-06-09 11:10:57 -0400
committerelioat <elioat@tilde.institute>2024-06-09 11:10:57 -0400
commitb72b5e6ab57173afd5daa555396f8d0c7aa9c1f6 (patch)
tree6722e5f6d97a7c54d707ce0f5ff77226bef6a108
parent0d5a8c704d517e7f880c5b704867e3d491e9ec8f (diff)
downloadtour-b72b5e6ab57173afd5daa555396f8d0c7aa9c1f6.tar.gz
*
-rw-r--r--lua/chupacabra/chupacabra.lua79
-rw-r--r--lua/chupacabra/scratch.lua1
-rw-r--r--lua/chupacabra/test_chupacabra.lua22
3 files changed, 102 insertions, 0 deletions
diff --git a/lua/chupacabra/chupacabra.lua b/lua/chupacabra/chupacabra.lua
new file mode 100644
index 0000000..645d327
--- /dev/null
+++ b/lua/chupacabra/chupacabra.lua
@@ -0,0 +1,79 @@
+local chupacabra = {}
+
+-- TODO: add the ability to push and pop arrays from the stack
+
+-- Parse a string into a list of tokens
+function chupacabra.tokenize(str)
+    local tokens = {}
+    for token in string.gmatch(str, "%S+") do
+        table.insert(tokens, token)
+    end
+    return tokens
+end
+
+function chupacabra.evaluate(tokens, context)
+    local stack = {}
+
+    for _, token in ipairs(tokens) do
+        if tonumber(token) then
+            table.insert(stack, tonumber(token))
+        elseif token == "pop" then
+            table.remove(stack) -- testing is fun
+        elseif token == "+" then
+            local b = table.remove(stack)
+            local a = table.remove(stack)
+            table.insert(stack, a + b)
+        elseif token == "-" then
+            local b = table.remove(stack)
+            local a = table.remove(stack)
+            table.insert(stack, a - b)
+        elseif token == "*" then
+            local b = table.remove(stack)
+            local a = table.remove(stack)
+            table.insert(stack, a * b)
+        elseif token == "/" then
+            local b = table.remove(stack)
+            local a = table.remove(stack)
+            table.insert(stack, a / b)
+        elseif token == "map+" then
+            -- If the token is "map+", pop an array from the stack, add 1 to each element, and push the result
+            local a = table.remove(stack)
+            for i, v in ipairs(a) do
+                a[i] = v + 1
+            end
+            table.insert(stack, a)
+        elseif token == "map*" then
+            -- If the token is "map*", pop an array from the stack, multiply each element by 2, and push the result
+            local a = table.remove(stack)
+            for i, v in ipairs(a) do
+                a[i] = v * 2
+            end
+            table.insert(stack, a)
+        elseif token == "map-" then
+            -- If the token is "map-", pop an array from the stack, subtract 1 from each element, and push the result
+            local a = table.remove(stack)
+            for i, v in ipairs(a) do
+                a[i] = v - 1
+            end
+            table.insert(stack, a)
+        elseif token == "map/" then
+            -- If the token is "map/", pop an array from the stack, divide each element by 2, and push the result
+            local a = table.remove(stack)
+            for i, v in ipairs(a) do
+                a[i] = v / 2
+            end
+            table.insert(stack, a)
+        else
+            error("invalid token: " .. token)
+        end
+    end
+
+    return table.remove(stack)
+end
+
+function chupacabra.run(str, context)
+    local tokens = chupacabra.tokenize(str)
+    return chupacabra.evaluate(tokens, context)
+end
+
+return chupacabra
\ No newline at end of file
diff --git a/lua/chupacabra/scratch.lua b/lua/chupacabra/scratch.lua
new file mode 100644
index 0000000..e0bab8c
--- /dev/null
+++ b/lua/chupacabra/scratch.lua
@@ -0,0 +1 @@
+local chupacabra = require("chupacabra")
\ No newline at end of file
diff --git a/lua/chupacabra/test_chupacabra.lua b/lua/chupacabra/test_chupacabra.lua
new file mode 100644
index 0000000..4d75f70
--- /dev/null
+++ b/lua/chupacabra/test_chupacabra.lua
@@ -0,0 +1,22 @@
+local chupacabra = require("chupacabra") 
+
+-- Define a function to run a test case
+local function test_case(input, expected_output)
+    local output = chupacabra.run(input, {})
+    assert(output == expected_output, "Test failed: " .. input .. " => " .. output .. ", expected: " .. expected_output)
+    print("Test passed: " .. input .. " => " .. output)
+end
+
+
+-- Run some test cases
+test_case("1", 1)  -- 1
+test_case("2 1 pop", 2) -- 2
+test_case("3 4 +", 7)  -- 3 + 4 = 7
+test_case("5 2 -", 3)  -- 5 - 2 = 3
+test_case("2 3 *", 6)  -- 2 * 3 = 6
+test_case("8 2 /", 4)  -- 8 / 2 = 4
+test_case("2 3 4 + *", 14)  -- 2 * (3 + 4) = 14
+test_case("5 2 3 + 4 + +", 14)  -- 5 + 2 + 3 + 4 = 14
+test_case("7 2 + 3 4 + +", 16)  -- 7 + 2 + 3 + 4 = 16
+test_case("5 2 - 3 4 * +", 15)  -- (5 - 2) + (3 * 4) = 15
+test_case("8 2 / 3 4 * +", 16)  -- (8 / 2) + (3 * 4) = 16
\ No newline at end of file