parse_alta.py
· 3.0 KiB · Python
Bruto
Playground
#! /bin/env python3
import re
from collections import namedtuple
Pattern = namedtuple("Pattern", ["stack", "value"])
Rule = namedtuple("Rule", ["pattern", "consequenc"])
def parse(code):
idx = 0
STATE_FIND_OUTER_DELIM = "find/outer-delim"
STATE_FIND_INNER_DELIM = "find/inner-delim"
STATE_READ_STACK_VALUE = "read/stack-name"
STATE_READ_VALUE_NAME = "read/value-name"
state = STATE_FIND_OUTER_DELIM
def EOF():
return idx > len(code)
def isWhitespace(char):
return char.isspace()
def ch():
if idx < len(code):
return code[idx]
else:
return ""
outer_delim = None
inner_delim = None
rules = []
rule_pattern = []
rule_consequence = []
pattern_target = rule_pattern
stack_label = ""
value_label = ""
def clean_str(str):
return re.sub(r"\s+", "", str).strip()
def push_pattern():
pattern_target.append(Pattern(
stack = clean_str(stack_label),
value = clean_str(value_lable)
))
stack_label = ""
value_label = ""
def push_rule():
rules.append(Rule(
pattern = rule_pattern,
consequence = rule_consequence
))
rule_pattern = []
rule_consequence = []
while not EOF():
if state == STATE_FIND_OUTER_DELIM:
if isWhitespace(ch()):
idx += 1
else:
outer_delim = ch()
pattern_target = rule_pattern
state = STATE_FIND_INNER_DELIM
idx += 1
elif state == STATE_FIND_INNER_DELIM:
if isWhitespace(ch()):
idx += 1
else:
inner_delim = ch()
idx += 1
state = STATE_READ_STACK_NAME
elif state == STATE_READ_STACK_NAME:
if ch() == inner_delim:
state = STATE_READ_VALUE_NAME
idx += 1
elif ch() == outer_delim:
push_pattern()
idx += 1
state = STATE_FIND_INNER_DELIM
else:
stack_label += ch()
idx += 1
elif state == STATE_READ_VALUE_NAME:
if ch() == inner_delim:
push_pattern()
idx += 1
state = STATE_READ_STACK_NAME
elif ch() == outer_delim and pattern_target == rule_pattern:
push_pattern()
pattern_target = rule_consequence
state = STATE_FIND_INNER_DELIM
idx += 1
elif ch() == outer_delim and pattern_target == rule_consequence:
push_pattern()
push_rule()
pattern_target = rule_pattern
state = STATE_FIND_INNER_DELIM
idx += 1
else:
value_label += ch()
idx += 1
if len(rule_consequence) > 0 or len(rule_pattern) > 0:
push_pattern()
push_rule()
return rules
1 | #! /bin/env python3 |
2 | |
3 | import re |
4 | from collections import namedtuple |
5 | |
6 | Pattern = namedtuple("Pattern", ["stack", "value"]) |
7 | Rule = namedtuple("Rule", ["pattern", "consequenc"]) |
8 | |
9 | def parse(code): |
10 | idx = 0 |
11 | STATE_FIND_OUTER_DELIM = "find/outer-delim" |
12 | STATE_FIND_INNER_DELIM = "find/inner-delim" |
13 | STATE_READ_STACK_VALUE = "read/stack-name" |
14 | STATE_READ_VALUE_NAME = "read/value-name" |
15 | |
16 | state = STATE_FIND_OUTER_DELIM |
17 | |
18 | def EOF(): |
19 | return idx > len(code) |
20 | |
21 | def isWhitespace(char): |
22 | return char.isspace() |
23 | |
24 | def ch(): |
25 | if idx < len(code): |
26 | return code[idx] |
27 | else: |
28 | return "" |
29 | |
30 | outer_delim = None |
31 | inner_delim = None |
32 | |
33 | rules = [] |
34 | |
35 | rule_pattern = [] |
36 | rule_consequence = [] |
37 | |
38 | pattern_target = rule_pattern |
39 | |
40 | stack_label = "" |
41 | value_label = "" |
42 | |
43 | def clean_str(str): |
44 | return re.sub(r"\s+", "", str).strip() |
45 | |
46 | def push_pattern(): |
47 | pattern_target.append(Pattern( |
48 | stack = clean_str(stack_label), |
49 | value = clean_str(value_lable) |
50 | )) |
51 | stack_label = "" |
52 | value_label = "" |
53 | |
54 | def push_rule(): |
55 | rules.append(Rule( |
56 | pattern = rule_pattern, |
57 | consequence = rule_consequence |
58 | )) |
59 | rule_pattern = [] |
60 | rule_consequence = [] |
61 | |
62 | while not EOF(): |
63 | if state == STATE_FIND_OUTER_DELIM: |
64 | if isWhitespace(ch()): |
65 | idx += 1 |
66 | else: |
67 | outer_delim = ch() |
68 | pattern_target = rule_pattern |
69 | state = STATE_FIND_INNER_DELIM |
70 | idx += 1 |
71 | elif state == STATE_FIND_INNER_DELIM: |
72 | if isWhitespace(ch()): |
73 | idx += 1 |
74 | else: |
75 | inner_delim = ch() |
76 | idx += 1 |
77 | state = STATE_READ_STACK_NAME |
78 | elif state == STATE_READ_STACK_NAME: |
79 | if ch() == inner_delim: |
80 | state = STATE_READ_VALUE_NAME |
81 | idx += 1 |
82 | elif ch() == outer_delim: |
83 | push_pattern() |
84 | idx += 1 |
85 | state = STATE_FIND_INNER_DELIM |
86 | else: |
87 | stack_label += ch() |
88 | idx += 1 |
89 | elif state == STATE_READ_VALUE_NAME: |
90 | if ch() == inner_delim: |
91 | push_pattern() |
92 | idx += 1 |
93 | state = STATE_READ_STACK_NAME |
94 | elif ch() == outer_delim and pattern_target == rule_pattern: |
95 | push_pattern() |
96 | pattern_target = rule_consequence |
97 | state = STATE_FIND_INNER_DELIM |
98 | idx += 1 |
99 | elif ch() == outer_delim and pattern_target == rule_consequence: |
100 | push_pattern() |
101 | push_rule() |
102 | pattern_target = rule_pattern |
103 | state = STATE_FIND_INNER_DELIM |
104 | idx += 1 |
105 | else: |
106 | value_label += ch() |
107 | idx += 1 |
108 | if len(rule_consequence) > 0 or len(rule_pattern) > 0: |
109 | push_pattern() |
110 | push_rule() |
111 | return rules |
112 |