local alta = {} function alta.parse(code) local idx = 1 local STATE_FIND_OUTER_DELIM = "find/outer-delim" local STATE_FIND_INNER_DELIM = "find/inner-delim" local STATE_READ_STACK_NAME = "read/stack-name" local STATE_READ_VALUE_NAME = "read/value-name" local state = STATE_FIND_OUTER_DELIM function EOF() return idx > #code end function isWhitespace(chr) return chr:find("^%s$") ~= nil end function ch() return code:sub(idx,idx) end local outer_delim = nil local inner_delim = nil local rules = {} local rule_pattern = {} local rule_consequence = {} local pattern_target = rule_pattern local stack_label = "" local value_label = "" function clean_str(str) return str :gsub("^%s+", "") :gsub("%s+$", "") :gsub("%s+", " ") end function push_pattern() table.insert(pattern_target, { stack = clean_str(stack_label), value = clean_str(value_label), }) stack_label = "" value_label = "" end function push_rule() table.insert(rules, { pattern = rule_pattern, consequence = rule_consequence, }) rule_pattern = {} rule_consequence = {} end while not EOF() do if state == STATE_FIND_OUTER_DELIM then if isWhitespace(ch()) then idx = idx + 1 else inner_delim = ch() idx = idx + 1 state = STATE_READ_STACK_NAME end elseif state == STATE_READ_STACK_NAME then if ch() == inner_delim then state = STATE_READ_VALUE_NAME idx = idx + 1 elseif ch() == outer_delim then push_pattern() idx = idx + 1 state = STATE_FIND_INNER_DELIM else stack_label = stack_label .. ch() idx =idx + 1 end elseif state == STATE_READ_VALUE_NAME then if ch() == inner_delim then push_pattern() idx = idx + 1 state = STATE_READ_STACK_NAME elseif ch == outer_delim and pattern_target == rule_pattern then push_pattern() pattern_target = rule_consequence state = STATE_FIND_INNER_DELIM idx = idx + 1 elseif ch == outer_delim and pattern_target == rule_consequence then push_pattern() push_rule() pattern_target = rule_pattern state = STATE_FIND_INNER_DELIM idx = idx + 1 else value_label = value_label .. ch() idx = idx + 1 end end end if #rule_consequence > 0 or #rule_pattern > 0 then push_pattern() push_rule() end return rules end return alta