Skip to content

Instantly share code, notes, and snippets.

@RealNeGate
Last active May 18, 2023 21:21
Show Gist options
  • Save RealNeGate/be130523b1294d2f857387157d3775ea to your computer and use it in GitHub Desktop.
Save RealNeGate/be130523b1294d2f857387157d3775ea to your computer and use it in GitHub Desktop.
inspect = require "inspect"
function sm_parse(source)
local states = {}
for line in source:gmatch("[^\r\n]+") do
local tokens = {}
for w in line:gmatch("[^%s]+") do tokens[#tokens + 1] = w end
-- yell at the user about missing arrows
if tokens[2] ~= "->" then
print("error: missing ->")
return nil
end
if tokens[4] == "->" then
local curr = states[tokens[1]]
if curr == nil then
-- make new state node
curr = {}
states[tokens[1]] = curr
end
if states[tokens[5]] == nil then
-- make new state node
states[tokens[5]] = {}
end
curr[tokens[3]] = tokens[5]
end
end
return states
end
-- example line: state -> input -> next
function sm_compile(source)
local states = sm_parse(source)
local str = {}
local function s(a) str[#str + 1] = a end
s('function FINAL() end')
for k, v in pairs(states) do
-- edges
s('function '..k..'(input)')
for input, edge in pairs(v) do
s([[ if input == "]] .. input .. [[" then return ]] .. edge .. [[(coroutine.yield("]]..edge..[[")) end]])
end
s(' return FINAL(coroutine.yield("FINAL"))')
s("end")
end
s('return a')
local source = table.concat(str, "\n")
local code, errors = load(source)
if code ~= nil then
local sm = coroutine.create(code())
return function(input)
return coroutine.resume(sm, input)
end
else
print(errors)
return nil
end
end
function sm_interpret(source)
local code = sm_parse(source)
local state = "a"
return function(input)
state = code[state][input]
if state == "FINAL" then
return nil
end
return state
end
end
--[[
Here's some example code (you can replace with sm_compile if you
wish to compile the state machine into a lua function)
sm = sm_interpret[[
a -> a-down -> b
a -> b-down -> c
c -> a-down -> d
]]
--]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment