Knock together a quick REPL
This commit is contained in:
parent
8e72dcd64f
commit
2943bd02e1
3 changed files with 78 additions and 10 deletions
6
setup.py
6
setup.py
|
@ -24,9 +24,13 @@ setup(
|
||||||
packages=[
|
packages=[
|
||||||
"flowmetal",
|
"flowmetal",
|
||||||
],
|
],
|
||||||
scripts=[
|
entry_points = {
|
||||||
|
'console_scripts': [
|
||||||
|
'iflow=flowmetal.repl:main'
|
||||||
],
|
],
|
||||||
|
},
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
'prompt-toolkit~=3.0.0',
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,16 +216,21 @@ class Parser(SexpParser):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, f: PosTrackingBufferedReader):
|
def parse(cls, f: PosTrackingBufferedReader):
|
||||||
|
if not f.peek():
|
||||||
|
raise SyntaxError(f"Got end of file ({f.pos()}) while parsing")
|
||||||
|
elif cls.ispunct(f.peek()):
|
||||||
if f.peek() == "(":
|
if f.peek() == "(":
|
||||||
return cls.parse_list(f)
|
return cls.parse_list(f)
|
||||||
elif f.peek() == "[":
|
elif f.peek() == "[":
|
||||||
return cls.parse_sqlist(f)
|
return cls.parse_sqlist(f)
|
||||||
elif f.peek() == '"':
|
elif f.peek() == '"':
|
||||||
return cls.parse_str(f)
|
return cls.parse_str(f)
|
||||||
elif cls.isspace(f.peek()):
|
|
||||||
return cls.parse_whitespace(f)
|
|
||||||
elif f.peek() == ";":
|
elif f.peek() == ";":
|
||||||
return cls.parse_comment(f)
|
return cls.parse_comment(f)
|
||||||
|
else:
|
||||||
|
raise SyntaxError(f"Got unexpected punctuation {f.read()!r} at {f.pos()} while parsing")
|
||||||
|
elif cls.isspace(f.peek()):
|
||||||
|
return cls.parse_whitespace(f)
|
||||||
else:
|
else:
|
||||||
return cls.parse_symbol(f)
|
return cls.parse_symbol(f)
|
||||||
|
|
||||||
|
@ -258,6 +263,8 @@ class Parser(SexpParser):
|
||||||
pos = rtb.pos()
|
pos = rtb.pos()
|
||||||
acc = []
|
acc = []
|
||||||
while f.peek() != closec:
|
while f.peek() != closec:
|
||||||
|
if not f.peek():
|
||||||
|
raise SyntaxError(f"Got end of file ({f.pos()}) while parsing {openc!r}...{closec!r} starting at {pos}")
|
||||||
acc.append(cls.parse(rtb))
|
acc.append(cls.parse(rtb))
|
||||||
assert rtb.read() == closec # Discard the trailing delimeter
|
assert rtb.read() == closec # Discard the trailing delimeter
|
||||||
return ctor(acc, str(rtb), pos)
|
return ctor(acc, str(rtb), pos)
|
||||||
|
|
57
src/python/flowmetal/repl.py
Normal file
57
src/python/flowmetal/repl.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
from flowmetal.syntax_analyzer import analyzes
|
||||||
|
|
||||||
|
from prompt_toolkit import print_formatted_text, prompt, PromptSession
|
||||||
|
from prompt_toolkit.formatted_text import FormattedText
|
||||||
|
from prompt_toolkit.history import FileHistory
|
||||||
|
from prompt_toolkit.styles import Style
|
||||||
|
|
||||||
|
|
||||||
|
STYLE = Style.from_dict({
|
||||||
|
# User input (default text).
|
||||||
|
"": "",
|
||||||
|
"prompt": "ansigreen",
|
||||||
|
"time": "ansiyellow"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class InterpreterInterrupt(Exception):
|
||||||
|
"""An exception used to break the prompt or evaluation."""
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""REPL entry point."""
|
||||||
|
|
||||||
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
logger = logging.getLogger("arrdem.datalog")
|
||||||
|
ch = logging.StreamHandler()
|
||||||
|
ch.setLevel(logging.INFO)
|
||||||
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||||
|
ch.setFormatter(formatter)
|
||||||
|
logger.addHandler(ch)
|
||||||
|
|
||||||
|
session = PromptSession(history=FileHistory(".datalog.history"))
|
||||||
|
line_no = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
line = session.prompt([("class:prompt", ">>> ")], style=STYLE)
|
||||||
|
except (InterpreterInterrupt, KeyboardInterrupt):
|
||||||
|
continue
|
||||||
|
except EOFError:
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
pprint.pprint(analyzes(line, source_name=f"repl@{line_no}"))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
finally:
|
||||||
|
line_no += 1
|
Loading…
Reference in a new issue