From 0abf3511646446ee64f21d551dd0d2214fd624b7 Mon Sep 17 00:00:00 2001 From: Matt Singleton Date: Wed, 19 Jan 2022 18:58:02 -0600 Subject: organizing the repo a bit --- browser/fsm.py | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 browser/fsm.py (limited to 'browser/fsm.py') diff --git a/browser/fsm.py b/browser/fsm.py new file mode 100644 index 0000000..eccfc6e --- /dev/null +++ b/browser/fsm.py @@ -0,0 +1,117 @@ +import html +import sys +import urllib.parse + + +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 and len(self._document) > self._offset: + self._fsm.update() + + def text_state(self): + line = self._document[self._offset] + if line.strip() == '': + self._blanks += 1 + else: + self._blanks = 0 + if line.startswith('```'): + self._fsm.push_state(self.pre_state) + self._output.write('
\n')
+            self._offset += 1
+        elif line.startswith('* '):
+            self._fsm.push_state(self.list_state)
+            self._output.write('
\n') + self._offset += 1 + else: + self._output.write(line + '\n') + self._offset += 1 + + def list_state(self): + line = self._document[self._offset] + if line.startswith('* '): + self._output.write('
  • {}
  • \n'.format(html.escape(line[2:]))) + self._offset += 1 + else: + self._fsm.pop_state() + self._output.write('\n') + + def link_state(self): + line = self._document[self._offset] + if line.startswith('=>'): + parts = line[2:].split(None, 1) + url = parts[0] + url_parts = urllib.parse.urlsplit(url) + if url_parts.scheme in ('gemini', ''): + external = '' + else: + external = open('external_link.svg').read() + if len(parts) == 1: + text = url + else: + text = html.escape(parts[1]) + self._output.write('\n'.format(url, text, external)) + self._offset += 1 + else: + self._fsm.pop_state() + self._output.write('\n') -- cgit v1.2.3