Reader's 'done'

This commit is contained in:
Reid D. 'arrdem' McKenzie 2022-01-09 16:32:11 -07:00
parent 0b7b67b797
commit df9aae1253
7 changed files with 60 additions and 23 deletions

View file

@ -15,22 +15,19 @@ mapping: "{" kv* "}"
kv: expr expr kv: expr expr
quote: "'" expr quote: "'" expr
atom: KEYWORD | PATTERN | INT | FLOAT | STRING | true | false | nil | SYMBOL atom: KEYWORD | PATTERN | INT | FLOAT | STRING | TRUE | FALSE | NIL | SYMBOL
KEYWORD: ":" SYMBOL KEYWORD: ":" SYMBOL
SYMBOL: /[^(){}#'"\s]+/ SYMBOL: /[^(){}#'"\s]+/
// FIXME: These two don't deal with escapes correctly at all
STRING: /".*?"/ STRING: /".*?"/
PATTERN: /\/.*?\// PATTERN: /\/.*?\//
true: TRUE
TRUE: /true/ TRUE: /true/
false: FALSE
FALSE: /false/ FALSE: /false/
nil: NIL
NIL: /nil/ NIL: /nil/
INT: /[+-]?[0-9]+/ INT: /[+-]?[0-9]+/
%import common.WORD // imports from terminal library
%import common.FLOAT // float %import common.FLOAT // float
%ignore " " // Disregard spaces in text %ignore " " // Disregard spaces in text
%ignore "," // Treat commas as whitespace %ignore "," // Treat commas as whitespace
@ -39,6 +36,6 @@ INT: /[+-]?[0-9]+/
def parse(input: str) -> Any: def parse(input: str) -> Any:
"""Parse a string using the shogoth (lisp) gramar, returning an unmodified tree.""" '''Parse a string using the shogoth (lisp) gramar, returning an unmodified tree.'''
return PARSER.parse(input) return PARSER.parse(input)

View file

@ -2,4 +2,5 @@
from .impl import Reader from .impl import Reader
__all__ = ["Reader"] __all__ = ["Reader"]

View file

@ -1,11 +1,19 @@
"""The shogoth reader.""" """The shogoth reader."""
import re
from typing import Any from typing import Any
from shogoth.parser import parse
from lark import Tree, Token from lark import (
from lark import Lark, Transformer, v_args Lark,
Token,
Transformer,
Tree,
v_args,
)
from shogoth.parser import parse
from shogoth.types import Keyword, Symbol
# Monkeypatching for py3.10 matching # Monkeypatching for py3.10 matching
Tree.__match_args__ = ("data", "children") Tree.__match_args__ = ("data", "children")
@ -22,41 +30,57 @@ class Reader(object):
return parse(buffer) return parse(buffer)
def symbol(self, x): def symbol(self, x):
return ["read-eval", ["symbol", x]] return Symbol(x)
def keyword(self, x): def keyword(self, x):
return ["read-eval", ["keyword", x]] return Keyword(x)
def pattern(self, x):
return re.compile(x[1:-1].replace("\\/", "/"))
def _read(self, tree: Tree) -> Any: def _read(self, tree: Tree) -> Any:
match tree: match tree:
case Tree(Token('RULE', 'expr'), children): case Tree(Token("RULE", "expr"), children):
return self._read(children[0]) return self._read(children[0])
case Tree(Token('RULE', 'plist'), children): case Tree(Token("RULE", "plist"), children):
return [self._read(c) for c in children] return [self._read(c) for c in children]
case Tree(Token('RULE', 'blist'), children): case Tree(Token("RULE", "blist"), children):
return [self._read(c) for c in children] return [self._read(c) for c in children]
case Tree(Token('RULE', 'mapping'), children): case Tree(Token("RULE", "mapping"), children):
return dict(self._read(c) for c in children) return dict(self._read(c) for c in children)
case Tree(Token('RULE', 'kv'), [k, v]): case Tree(Token("RULE", "kv"), [k, v]):
return (self._read(k), self._read(v)) return (self._read(k), self._read(v))
case Tree(Token('RULE', 'atom'), [a]): case Tree(Token("RULE", "atom"), [a]):
return self._read(a) return self._read(a)
case Token('INT', x): case Token("INT", x):
return int(x) return int(x)
case Token('FLOAT', x): case Token("FLOAT", x):
return float(x) return float(x)
case Token('KEYWORD', x): case Token("KEYWORD", x):
return self.keyword(x) return self.keyword(x)
case Token('SYMBOL', x): case Token("PATTERN", x):
return self.pattern(x)
case Token("TRUE", _):
return True
case Token("FALSE", _):
return False
case Token("NIL", _):
return None
# Symbol is very much the catch-all of the grammar
case Token("SYMBOL", x):
return self.symbol(x) return self.symbol(x)
case _: case _:

View file

@ -1,8 +1,6 @@
"""A testing REPL.""" """A testing REPL."""
import sys
from shogoth.parser import parse
from shogoth.reader import Reader from shogoth.reader import Reader

View file

@ -0,0 +1,7 @@
"""The public interface for shogoth's baked-in types."""
from .keyword import Keyword
from .symbol import Symbol
__all__ = ["Keyword", "Symbol"]

View file

@ -0,0 +1,5 @@
from .symbol import Symbol
class Keyword(Symbol):
pass

View file

@ -0,0 +1,5 @@
from typing import NamedTuple
class Symbol(NamedTuple):
name: str