parse_alta.lua
· 2.9 KiB · Lua
Raw
Playground
local alta = {}
local function alta.parse(code)
local idx = 1
local STATE_FIND_OUTER_DELIM = "find/outer-delim"
local STATE_FND_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)
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,
rule_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_FND_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_FND_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_FND_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
| 1 | local alta = {} |
| 2 | |
| 3 | local function alta.parse(code) |
| 4 | local idx = 1 |
| 5 | local STATE_FIND_OUTER_DELIM = "find/outer-delim" |
| 6 | local STATE_FND_INNER_DELIM = "find/inner-delim" |
| 7 | local STATE_READ_STACK_NAME = "read/stack-name" |
| 8 | local STATE_READ_VALUE_NAME = "read/value-name" |
| 9 | |
| 10 | local state = STATE_FIND_OUTER_DELIM |
| 11 | |
| 12 | function EOF() return idx > #code end |
| 13 | function isWhitespace(chr) |
| 14 | chr:find("^%s$") ~= nil |
| 15 | end |
| 16 | |
| 17 | function ch() return code:sub(idx,idx) end |
| 18 | |
| 19 | local outer_delim = nil |
| 20 | local inner_delim = nil |
| 21 | |
| 22 | local rules = {} |
| 23 | |
| 24 | local rule_pattern = {} |
| 25 | local rule_consequence = {} |
| 26 | |
| 27 | local pattern_target = rule_pattern |
| 28 | |
| 29 | local stack_label = "" |
| 30 | local value_label = "" |
| 31 | |
| 32 | function clean_str(str) |
| 33 | return str |
| 34 | :gsub("^%s+", "") |
| 35 | :gsub("%s+$", "") |
| 36 | :gsub("%s+", " ") |
| 37 | end |
| 38 | |
| 39 | function push_pattern() |
| 40 | table.insert(pattern_target, { |
| 41 | stack = clean_str(stack_label), |
| 42 | value = clean_str(value_label), |
| 43 | }) |
| 44 | stack_label = "" |
| 45 | value_label = "" |
| 46 | end |
| 47 | |
| 48 | function push_rule() |
| 49 | table.insert(rules, { |
| 50 | pattern = rule_pattern, |
| 51 | rule_consequence = rule_consequence, |
| 52 | }) |
| 53 | rule_pattern = {} |
| 54 | rule_consequence = {} |
| 55 | end |
| 56 | |
| 57 | while not EOF() do |
| 58 | if state == STATE_FIND_OUTER_DELIM then |
| 59 | if isWhitespace(ch()) then |
| 60 | idx = idx + 1 |
| 61 | else |
| 62 | inner_delim = ch() |
| 63 | idx = idx + 1 |
| 64 | state = STATE_READ_STACK_NAME |
| 65 | end |
| 66 | elseif state == STATE_READ_STACK_NAME then |
| 67 | if ch() == inner_delim then |
| 68 | state = STATE_READ_VALUE_NAME |
| 69 | idx = idx + 1 |
| 70 | elseif ch() == outer_delim then |
| 71 | push_pattern() |
| 72 | idx = idx + 1 |
| 73 | state = STATE_FND_INNER_DELIM |
| 74 | else |
| 75 | stack_label = stack_label .. ch() |
| 76 | idx =idx + 1 |
| 77 | end |
| 78 | elseif state == STATE_READ_VALUE_NAME then |
| 79 | if ch() == inner_delim then |
| 80 | push_pattern() |
| 81 | idx = idx + 1 |
| 82 | state = STATE_READ_STACK_NAME |
| 83 | elseif ch == outer_delim and pattern_target == rule_pattern then |
| 84 | push_pattern() |
| 85 | pattern_target = rule_consequence |
| 86 | state = STATE_FND_INNER_DELIM |
| 87 | idx = idx + 1 |
| 88 | elseif ch == outer_delim and pattern_target == rule_consequence then |
| 89 | push_pattern() |
| 90 | push_rule() |
| 91 | pattern_target = rule_pattern |
| 92 | state = STATE_FND_INNER_DELIM |
| 93 | idx = idx + 1 |
| 94 | else |
| 95 | value_label = value_label .. ch() |
| 96 | idx = idx + 1 |
| 97 | end |
| 98 | end |
| 99 | end |
| 100 | if #rule_consequence > 0 or #rule_pattern > 0 then |
| 101 | push_pattern() |
| 102 | push_rule() |
| 103 | end |
| 104 | return rules |
| 105 | end |
| 106 | |
| 107 | return alta |