Zuletzt aktiv 1736227479

Änderung 6fd396e86986f32430b88eba5ac30a736a247d44

parse_alta.lua Orginalformat Playground
1local alta = {}
2
3function 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 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 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
105end
106
107return alta