diff options
Diffstat (limited to 'fsm.py')
-rw-r--r-- | fsm.py | 117 |
1 files changed, 0 insertions, 117 deletions
@@ -1,117 +0,0 @@ -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('<pre>\n') - self._offset += 1 - elif line.startswith('* '): - self._fsm.push_state(self.list_state) - self._output.write('<ul>\n') - elif line.startswith('=>'): - self._fsm.push_state(self.link_state) - self._output.write('<ul>\n') - else: - if line.startswith('# '): - self._output.write('<h1>{}</h1>\n'.format(html.escape(line[2:]))) - elif line.startswith('## '): - self._output.write('<h2>{}</h2>\n'.format(html.escape(line[3:]))) - elif line.startswith('### '): - self._output.write('<h3>{}</h3>\n'.format(html.escape(line[4:]))) - elif line.startswith('> '): - self._output.write('<blockquote>{}</blockquote>\n'.format(html.escape(line[2:]))) - elif line.strip() == '': - if self._blanks > 1: - self._output.write('<br/>\n') - else: - self._output.write('<p>{}</p>\n'.format(html.escape(line))) - self._offset += 1 - - def pre_state(self): - line = self._document[self._offset] - if line.startswith('```'): - self._fsm.pop_state() - self._output.write('</pre>\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('<li>{}</li>\n'.format(html.escape(line[2:]))) - self._offset += 1 - else: - self._fsm.pop_state() - self._output.write('</ul>\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('<li class="link"><a href="{}">{}</a>{}</li>\n'.format(url, text, external)) - self._offset += 1 - else: - self._fsm.pop_state() - self._output.write('</ul>\n') |