parse_alta.lua
· 2.9 KiB · Lua
原始檔案
Playground
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
1 | local alta = {} |
2 | |
3 | function alta.parse(code) |
4 | local idx = 1 |
5 | local STATE_FIND_OUTER_DELIM = "find/outer-delim" |
6 | local STATE_FIND_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 | return 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 | 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_FIND_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_FIND_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_FIND_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 |