feat(parse_transition): first version of parse_transition, with tests

This commit is contained in:
swaits committed 2025-02-02 20:11:01 -08:00
commit bdc28c4e83
9 files changed
+342

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
---
-- Recursively prints the contents of a table in a human-readable format.
--
-- This function traverses the provided table `tbl` and prints each key-value
-- pair to the standard output. For nested tables, it calls itself recursively,
-- increasing the indentation level to visually represent the table hierarchy.
--
-- @param tbl table: The table whose contents are to be printed.
-- @param indent number: (Optional) The current indentation level. Defaults to 0.
-- @return nil
export print_table = (tbl, indent) ->
-- Use the “?=” operator to give a default value.
unless indent
indent = 0
-- Omit the extra “do” after the loop header.
for k, v in pairs tbl
formatting = string.rep(" ", indent) .. k .. ": "
if type(v) == "table"
print formatting
print_table v, indent + 1
elseif type(v) == "boolean"
print formatting .. tostring(v)
else
print formatting .. v
+41
View File
@@ -0,0 +1,41 @@
require "src.util.string"
require "src.util.validators"
---
-- parse_transition
-- Parses a transition string into a table with:
-- • target: the target state name,
-- • type: "after" | "every" | "on",
-- • time: number (if timer-based),
-- • event: string (if event-based).
export parse_transition = (trans) ->
unless type(trans) == "string"
error "Transition must be a string"
words = split trans
unless #words == 3
error "Transition must consist of three words"
unless is_valid_symbol words[1]
error "Invalid state name"
switch words[2]
when "on"
unless is_valid_symbol words[3]
error "Invalid event name"
{target: words[1], event: words[3]}
when "after"
num = tonumber words[3]
unless is_valid_timer num
error "Invalid time value in 'after' transition type"
{target: words[1], after: num}
when "every"
num = tonumber words[3]
unless is_valid_timer num
error "Invalid time value in 'every' transition type"
{target: words[1], every: num}
else
error "Unknown transition type"
+18
View File
@@ -0,0 +1,18 @@
---
-- Splits the input string into an array of non-whitespace substrings.
--
-- This function uses Lua's pattern matching to iterate over the provided
-- string `s` and collects each contiguous sequence of non-whitespace
-- characters into a new table. If the input is not a string, the function
-- raises an error.
--
-- @param s string: The string to be split. Must be a valid string.
-- @return table: An array of substrings obtained by splitting `s` on whitespace.
-- @raise error if the input parameter `s` is not a string.
export split = (s) ->
unless type(s) == "string"
error "split() requires a string parameter"
chunks = {}
for substr in string.gmatch s, '%S+'
table.insert chunks, substr
chunks
+28
View File
@@ -0,0 +1,28 @@
---
-- Determines if the provided timer value is valid.
--
-- A valid timer is defined as a number greater than zero.
--
-- @param x number: The timer value to validate.
-- @return boolean: Returns `true` if `x` is a positive number; otherwise, returns `false` or `nil`.
export is_valid_timer = (x) ->
x and x > 0
---
-- Checks whether the given string is a valid symbol.
--
-- A valid symbol is defined as a non-empty string that contains only
-- alphabetic characters (A-Z and a-z). If the input is not a string,
-- the function returns `false`.
--
-- @param s string: The string to be validated as a symbol.
-- @return boolean: Returns `true` if `s` contains only letters; otherwise, returns `false`.
export is_valid_symbol = (s) ->
-- Return false immediately if s is not a string.
unless type(s) == "string"
return false
-- Use Lua's pattern matching to ensure the string only contains letters.
if string.match s, "^[A-Za-z]+$"
true
else
false