From b94acce656db4f0b129cd939765c0ca451f6a538 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 28 Feb 2015 14:14:18 +0100 Subject: Nim: step1 --- nim/reader.nim | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 nim/reader.nim (limited to 'nim/reader.nim') diff --git a/nim/reader.nim b/nim/reader.nim new file mode 100644 index 0000000..c8f9096 --- /dev/null +++ b/nim/reader.nim @@ -0,0 +1,97 @@ +import nre, optional_t, strutils, types + +var + tokenRE = re"""[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)""" + intRE = re"-?[0-9]+$" + +type Reader = object + tokens: seq[string] + position: int + +proc next(r: var Reader): string = + if r.position >= r.tokens.len: + result = nil + else: + result = r.tokens[r.position] + inc r.position + +proc peek(r: Reader): string = + if r.position >= r.tokens.len: nil + else: r.tokens[r.position] + +proc tokenize(str: string): seq[string] = + result = @[] + for match in str.findIter(tokenRE): + result.add match.captures[0] + +proc read_form(r: var Reader): MalType + +proc read_seq(r: var Reader, fr, to: string): seq[MalType] = + result = @[] + var t = r.next + if t != fr: raise newException(ValueError, "expected '" & fr & "'") + + t = r.peek + while t != to: + if t == nil: raise newException(ValueError, "expected '" & to & "', got EOF") + result.add r.read_form + t = r.peek + discard r.next + +proc read_list(r: var Reader): MalType = + result = list r.read_seq("(", ")") + +proc read_vector(r: var Reader): MalType = + result = vector r.read_seq("[", "]") + +proc read_hash_map(r: var Reader): MalType = + result = hash_map r.read_seq("{", "}") + +proc read_atom(r: var Reader): MalType = + let t = r.next + if t.match(intRE): number t.parseInt + else: symbol t + +proc read_form(r: var Reader): MalType = + if r.peek[0] == ';': + discard r.next + return nilObj + case r.peek + of "'": + discard r.next + result = list(symbol "quote", r.read_form) + of "`": + discard r.next + result = list(symbol "quasiquote", r.read_form) + of "~": + discard r.next + result = list(symbol "unquote", r.read_form) + of "~@": + discard r.next + result = list(symbol "splice-unquote", r.read_form) + of "^": + discard r.next + let meta = r.read_form + result = list(symbol "with-meta", r.read_form, meta) + of "@": + discard r.next + result = list(symbol "deref", r.read_form) + + # list + of "(": result = r.read_list + of ")": raise newException(ValueError, "unexpected ')'") + + # vector + of "[": result = r.read_vector + of "]": raise newException(ValueError, "unexpected ']'") + + # hash-map + of "{": result = r.read_hash_map + of "}": raise newException(ValueError, "unexpected '}'") + + # atom + else: result = r.read_atom + +proc read_str*(str: string): MalType = + var r = Reader(tokens: str.tokenize) + r.read_form -- cgit v1.2.3