Commit | Line | Data |
---|---|---|
ed3a12f5 PS |
1 | module Reader |
2 | open System | |
327bd967 | 3 | open Tokenizer |
ed3a12f5 PS |
4 | open Types |
5 | ||
3b82891f | 6 | type MutableList = System.Collections.Generic.List<Node> |
327bd967 PS |
7 | let inline addToMutableList (lst:MutableList) item = lst.Add(item); lst |
8 | ||
6c47cf67 PS |
9 | let errExpectedButEOF tok = ReaderError(sprintf "Expected %s, got EOF" tok) |
10 | let errInvalid () = ReaderError("Invalid token") | |
11 | ||
327bd967 PS |
12 | let quote = Symbol("quote") |
13 | let quasiquote = Symbol("quasiquote") | |
14 | let unquote = Symbol("unquote") | |
15 | let spliceUnquote = Symbol("splice-unquote") | |
16 | let deref = Symbol("deref") | |
17 | let withMeta = Symbol("with-meta") | |
18 | ||
19 | let rec readForm = function | |
20 | | OpenParen::rest -> readList [] rest | |
21 | | OpenBracket::rest -> readVector (MutableList()) rest | |
22 | | OpenBrace::rest -> readMap [] rest | |
23 | | SingleQuote::rest -> wrapForm quote rest | |
24 | | Backtick::rest -> wrapForm quasiquote rest | |
25 | | Tilde::rest -> wrapForm unquote rest | |
26 | | SpliceUnquote::rest -> wrapForm spliceUnquote rest | |
27 | | At::rest -> wrapForm deref rest | |
28 | | Caret::rest -> readMeta rest | |
29 | | tokens -> readAtom tokens | |
30 | ||
31 | and wrapForm node tokens = | |
32 | match readForm tokens with | |
33 | | Some(form), rest -> Some(List([node; form])), rest | |
6c47cf67 | 34 | | None, _ -> raise <| errExpectedButEOF "form" |
3b82891f | 35 | |
327bd967 PS |
36 | and readList acc = function |
37 | | CloseParen::rest -> Some(List(acc |> List.rev)), rest | |
6c47cf67 | 38 | | [] -> raise <| errExpectedButEOF "')'" |
327bd967 PS |
39 | | tokens -> |
40 | match readForm tokens with | |
41 | | Some(form), rest -> readList (form::acc) rest | |
6c47cf67 | 42 | | None, _ -> raise <| errExpectedButEOF "')'" |
327bd967 PS |
43 | |
44 | and readVector acc = function | |
45 | | CloseBracket::rest -> Some(Vector(acc.ToArray())), rest | |
6c47cf67 | 46 | | [] -> raise <| errExpectedButEOF "']'" |
327bd967 PS |
47 | | tokens -> |
48 | match readForm tokens with | |
49 | | Some(form), rest -> readVector (addToMutableList acc form) rest | |
6c47cf67 | 50 | | None, _ -> raise <| errExpectedButEOF "']'" |
327bd967 PS |
51 | |
52 | and readMap acc = function | |
53 | | CloseBrace::rest -> Some(Map(acc |> List.rev |> Map.ofList)), rest | |
6c47cf67 | 54 | | [] -> raise <| errExpectedButEOF "'}'" |
327bd967 PS |
55 | | tokens -> |
56 | match readForm tokens with | |
57 | | Some(key), rest -> | |
58 | match readForm rest with | |
59 | | Some(v), rest -> readMap ((key, v)::acc) rest | |
6c47cf67 PS |
60 | | None, _ -> raise <| errExpectedButEOF "'}'" |
61 | | None, _ -> raise <| errExpectedButEOF "'}'" | |
327bd967 PS |
62 | |
63 | and readMeta = function | |
64 | | OpenBrace::rest -> | |
65 | let meta, rest = readMap [] rest | |
66 | match readForm rest with | |
67 | | Some(form), rest -> Some(List([withMeta; form; meta.Value])), rest | |
6c47cf67 PS |
68 | | None, _ -> raise <| errExpectedButEOF "form" |
69 | | _ -> raise <| errExpectedButEOF "map" | |
b856be1e | 70 | |
327bd967 | 71 | and readAtom = function |
a836d8f3 PS |
72 | | Token("nil")::rest -> SomeNIL, rest |
73 | | Token("true")::rest -> SomeTRUE, rest | |
74 | | Token("false")::rest -> SomeFALSE, rest | |
327bd967 PS |
75 | | Tokenizer.String(str)::rest -> Some(String(str)), rest |
76 | | Tokenizer.Keyword(kw)::rest -> Some(Keyword(kw)), rest | |
77 | | Tokenizer.Number(num)::rest -> Some(Number(Int64.Parse(num))), rest | |
78 | | Token(sym)::rest -> Some(Symbol(sym)), rest | |
79 | | [] -> None, [] | |
6c47cf67 | 80 | | _ -> raise <| errInvalid () |
3b82891f | 81 | |
327bd967 PS |
82 | let rec readForms acc = function |
83 | | [] -> List.rev acc | |
84 | | tokens -> | |
85 | match readForm tokens with | |
86 | | Some(form), rest -> readForms (form::acc) rest | |
87 | | None, rest -> readForms acc rest | |
88 | ||
ed3a12f5 | 89 | let read_str str = |
327bd967 | 90 | tokenize str |> readForms [] |