#! /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