Simplify tokenizing, raise Unknown errors.
This brings the behaviour of Python Joy into congruence with Nim Joy.
This commit is contained in:
parent
b2c449dd66
commit
6fc77a9a4a
10
joy/joy.py
10
joy/joy.py
|
|
@ -29,6 +29,9 @@ from .parser import text_to_expression, ParseError, Symbol
|
||||||
from .utils.stack import stack_to_string
|
from .utils.stack import stack_to_string
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownSymbolError(KeyError): pass
|
||||||
|
|
||||||
|
|
||||||
def joy(stack, expression, dictionary, viewer=None):
|
def joy(stack, expression, dictionary, viewer=None):
|
||||||
'''Evaluate a Joy expression on a stack.
|
'''Evaluate a Joy expression on a stack.
|
||||||
|
|
||||||
|
|
@ -53,7 +56,10 @@ def joy(stack, expression, dictionary, viewer=None):
|
||||||
|
|
||||||
term, expression = expression
|
term, expression = expression
|
||||||
if isinstance(term, Symbol):
|
if isinstance(term, Symbol):
|
||||||
term = dictionary[term]
|
try:
|
||||||
|
term = dictionary[term]
|
||||||
|
except KeyError:
|
||||||
|
raise UnknownSymbolError(term)
|
||||||
stack, expression, dictionary = term(stack, expression, dictionary)
|
stack, expression, dictionary = term(stack, expression, dictionary)
|
||||||
else:
|
else:
|
||||||
stack = term, stack
|
stack = term, stack
|
||||||
|
|
@ -123,6 +129,8 @@ def interp(stack=(), dictionary=None):
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
stack, _, dictionary = run(text, stack, dictionary)
|
stack, _, dictionary = run(text, stack, dictionary)
|
||||||
|
except UnknownSymbolError as sym:
|
||||||
|
print('Unknown:', sym)
|
||||||
except:
|
except:
|
||||||
print_exc()
|
print_exc()
|
||||||
print(stack_to_string(stack))
|
print(stack_to_string(stack))
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,16 @@ from re import Scanner
|
||||||
from .utils.stack import list_to_stack
|
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'\[|\]'
|
BRACKETS = r'\[|\]'
|
||||||
STRING_DOUBLE_QUOTED = r'"(?:[^"\\]|\\.)*"'
|
|
||||||
STRING_SINGLE_QUOTED = r"'(?:[^'\\]|\\.)*'"
|
|
||||||
BLANKS = r'\s+'
|
BLANKS = r'\s+'
|
||||||
|
WORDS = r'[^[\]\s]+'
|
||||||
|
|
||||||
|
|
||||||
|
token_scanner = Scanner([
|
||||||
|
(BRACKETS, lambda _, token: token),
|
||||||
|
(BLANKS, None),
|
||||||
|
(WORDS, lambda _, token: token),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class Symbol(str):
|
class Symbol(str):
|
||||||
|
|
@ -81,7 +82,7 @@ def _tokenize(text):
|
||||||
|
|
||||||
Raise ParseError (with some of the failing text) if the scan fails.
|
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:
|
if rest:
|
||||||
raise ParseError(
|
raise ParseError(
|
||||||
'Scan failed at position %i, %r'
|
'Scan failed at position %i, %r'
|
||||||
|
|
@ -107,20 +108,16 @@ def _parse(tokens):
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise ParseError('Extra closing bracket.')
|
raise ParseError('Extra closing bracket.')
|
||||||
frame[-1] = list_to_stack(frame[-1])
|
frame[-1] = list_to_stack(frame[-1])
|
||||||
|
elif tok == 'true':
|
||||||
|
frame.append(True)
|
||||||
|
elif tok == 'false':
|
||||||
|
frame.append(False)
|
||||||
else:
|
else:
|
||||||
frame.append(tok)
|
try:
|
||||||
|
thing = int(tok)
|
||||||
|
except ValueError:
|
||||||
|
thing = Symbol(tok)
|
||||||
|
frame.append(thing)
|
||||||
if stack:
|
if stack:
|
||||||
raise ParseError('Unclosed bracket.')
|
raise ParseError('Unclosed bracket.')
|
||||||
return list_to_stack(frame)
|
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),
|
|
||||||
])
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue