parse_alta.py
· 3.0 KiB · Python
Raw
Playground
#! /bin/env python3
import re
from collections import namedtuple
Pattern = namedtuple("Pattern", ["stack", "value"])
Rule = namedtuple("Rule", ["pattern", "consequence"])
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", "consequence"]) |
| 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 |