Simplify tokenizing, raise Unknown errors.

This brings the behaviour of Python Joy into congruence with Nim Joy.
This commit is contained in:
Simon Forman 2021-04-06 12:40:04 -07:00
parent b2c449dd66
commit 6fc77a9a4a
2 changed files with 27 additions and 22 deletions

View File

@ -29,6 +29,9 @@ from .parser import text_to_expression, ParseError, Symbol
from .utils.stack import stack_to_string
class UnknownSymbolError(KeyError): pass
def joy(stack, expression, dictionary, viewer=None):
'''Evaluate a Joy expression on a stack.
@ -53,7 +56,10 @@ def joy(stack, expression, dictionary, viewer=None):
term, expression = expression
if isinstance(term, Symbol):
term = dictionary[term]
try:
term = dictionary[term]
except KeyError:
raise UnknownSymbolError(term)
stack, expression, dictionary = term(stack, expression, dictionary)
else:
stack = term, stack
@ -123,6 +129,8 @@ def interp(stack=(), dictionary=None):
break
try:
stack, _, dictionary = run(text, stack, dictionary)
except UnknownSymbolError as sym:
print('Unknown:', sym)
except:
print_exc()
print(stack_to_string(stack))

View File

@ -40,15 +40,16 @@ from re import Scanner
from .utils.stack import list_to_stack
#TODO: explain the details of float lits and strings.
BOOL = 'true|false'
FLOAT = r'-?\d+\.\d*(e(-|\+)\d+)?'
INT = r'-?\d+'
SYMBOL = r'[•\w!@$%^&*()_+<>?|\/;:`~,.=-]+'
BRACKETS = r'\[|\]'
STRING_DOUBLE_QUOTED = r'"(?:[^"\\]|\\.)*"'
STRING_SINGLE_QUOTED = r"'(?:[^'\\]|\\.)*'"
BLANKS = r'\s+'
WORDS = r'[^[\]\s]+'
token_scanner = Scanner([
(BRACKETS, lambda _, token: token),
(BLANKS, None),
(WORDS, lambda _, token: token),
])
class Symbol(str):
@ -81,7 +82,7 @@ def _tokenize(text):
Raise ParseError (with some of the failing text) if the scan fails.
'''
tokens, rest = _scanner.scan(text)
tokens, rest = token_scanner.scan(text)
if rest:
raise ParseError(
'Scan failed at position %i, %r'
@ -107,20 +108,16 @@ def _parse(tokens):
except IndexError:
raise ParseError('Extra closing bracket.')
frame[-1] = list_to_stack(frame[-1])
elif tok == 'true':
frame.append(True)
elif tok == 'false':
frame.append(False)
else:
frame.append(tok)
try:
thing = int(tok)
except ValueError:
thing = Symbol(tok)
frame.append(thing)
if stack:
raise ParseError('Unclosed bracket.')
return list_to_stack(frame)
_scanner = Scanner([
( BOOL, lambda _, token: token == 'true'),
( FLOAT, lambda _, token: float(token)),
( INT, lambda _, token: int(token)),
( SYMBOL, lambda _, token: Symbol(token)),
( BRACKETS, lambda _, token: token),
(STRING_DOUBLE_QUOTED, lambda _, token: token[1:-1].replace('\\"', '"')),
(STRING_SINGLE_QUOTED, lambda _, token: token[1:-1].replace("\\'", "'")),
( BLANKS, None),
])