import sys class StackFSM(object): """ Implement a finite state machine that uses a stack to manage state. """ def __init__(self): self._state_stack = [] def _current_state(self): if len(self._state_stack) > 0: return self._state_stack[-1] return None def update(self): fn = self._current_state() if fn is not None: fn() def push_state(self, state): self._state_stack.append(state) def pop_state(self): return self._state_stack.pop() class Parser(object): def __init__(self, document, output=None): self._document = document if output is None: output = sys.stdout self._output = output self._offset = 0 self._blanks = 0 self._fsm = StackFSM() def parse(self): self._fsm.push_state(self.text_state) while self._fsm._current_state() is not None: self._fsm.update() def text_state(self): if len(self._document) <= self._offset: self._fsm.pop_state() return line = self._document[self._offset] if line.strip() == '': self._blanks += 1 else: self._blanks = 0 if line.strip() == '```': self._fsm.pop_state() self._fsm.push_state(self.pre_state) self._output.write('
\n')
            self._offset += 1
        elif line.startswith('* '):
            self._fsm.pop_state()
            self._fsm.push_state(self.list_state)
            self._output.write('
\n') self._offset += 1 elif line.startswith('* '): self._fsm.pop_state() self._fsm.push_state(self.list_state) self._output.write('\n') document = """ # h1 hello hello ## h2 ``` code code ``` ### h3 hello hello ### lists * hello * two * three text * one * two * three ### links =>https://example.com hello => https://example.com two => https://example.com three text =>https://example.com => https://example.com => https://example.com """ p = Parser(document.split('\n')) p.parse()