def read_atom(reader): token = reader.peek() try: val = int(token) return mal_types.MalNumber(val) except ValueError: pass if token in _quote_mapping: reader.next() return mal_types.MalList( [mal_types.MalSymbol(_quote_mapping[token]), read_form(reader)]) elif token == '^': reader.next() meta_data = read_form(reader) reader.next() lst = read_form(reader) return mal_types.MalList( [mal_types.MalSymbol("with-meta"), lst, meta_data]) elif token.startswith('"') and token.endswith('"'): return mal_types.MalString( bytes(token[1:-1], "utf-8").decode("unicode_escape")) elif token.startswith(":"): return mal_types.MalKeyword(token) elif token in ('true', 'false'): if token == 'true': return mal_types.MalBool(True) return mal_types.MalBool(False) elif token == 'nil': return mal_types.MalNil() return mal_types.MalSymbol(token) # symbol?
def quasiquote(ast): if not is_pair(ast): return mal_types.MalList([mal_types.MalSymbol('quote'), ast]) elif ast[0].data == 'unquote': return ast[1] elif isinstance(ast[0], mal_types.list_types) and \ isinstance(ast[0][0], mal_types.MalSymbol) and \ ast[0][0].data == 'splice-unquote': return mal_types.MalList([mal_types.MalSymbol('concat'), ast[0][1], quasiquote(ast[1:])]) else: return mal_types.MalList([mal_types.MalSymbol('cons'), quasiquote(ast[0]), quasiquote(ast[1:])])
def symbol(x): return mal_types.MalSymbol(x.data)