Commit | Line | Data |
---|---|---|
58ff8110 | 1 | (import [hy.models [HyInteger :as Int HyKeyword :as Keyword |
081c3223 | 2 | HyString :as Str HySymbol :as Sym]] |
58ff8110 JM |
3 | [re]) |
4 | ||
5 | (defclass Blank [Exception]) | |
6 | ||
7 | (defclass Reader [] | |
8 | (defn --init-- [self tokens &optional [position 0]] | |
9 | (setv self.tokens tokens self.position position)) | |
10 | (defn next [self] | |
11 | (setv self.position (+ 1 self.position)) | |
12 | (get self.tokens (- self.position 1))) | |
13 | (defn peek [self] | |
14 | (if (> (len self.tokens) self.position) | |
15 | (get self.tokens self.position) | |
16 | None))) | |
17 | ||
18 | (def tok-re (.compile re "[\\s,]*(~@|[\\[\\]{}()'`~^@]|\"(?:[\\\\].|[^\\\\\"])*\"?|;.*|[^\\s\\[\\]{}()'\"`@,;]+)")) | |
19 | (def int-re (.compile re "-?[0-9]+$")) | |
9a4896ef | 20 | (def str-re (.compile re "^\"(?:[\\\\].|[^\\\\\"])*\"$")) |
4aa0ebdf | 21 | (def str-bad-re (.compile re "^\".*$")) |
58ff8110 JM |
22 | |
23 | (defn tokenize [str] | |
24 | (list-comp | |
25 | t | |
26 | (t (.findall re tok-re str)) | |
27 | (!= (get t 0) ";"))) | |
28 | ||
29 | (defn unescape [s] | |
42aecee6 JM |
30 | (-> s (.replace "\\\\" "\u029e") |
31 | (.replace "\\\"" "\"") | |
32 | (.replace "\\n" "\n") | |
33 | (.replace "\u029e" "\\"))) | |
58ff8110 JM |
34 | |
35 | (defn read-atom [rdr] | |
36 | (setv token (.next rdr)) | |
37 | (if | |
38 | (.match re int-re token) (int token) | |
4aa0ebdf | 39 | (.match re str-re token) (Str (unescape (cut token 1 -1))) |
6c4cc8ad | 40 | (.match re str-bad-re token) (raise (Exception "expected '\"', got EOF")) |
58ff8110 JM |
41 | (= ":" (get token 0)) (Keyword token) |
42 | (= "nil" token) None | |
43 | (= "true" token) True | |
44 | (= "false" token) False | |
45 | True (Sym token))) | |
46 | ||
47 | (defn read-seq [rdr &optional [start "("] [end ")"]] | |
48 | (setv ast (list) | |
49 | token (.next rdr)) | |
50 | (if (!= token start) | |
51 | (raise (Exception (+ "expected '" start "'"))) | |
52 | (do | |
53 | (setv token (.peek rdr)) | |
54 | (while (!= token end) | |
55 | (if (not token) (raise (Exception (+ "expected '" end | |
56 | ", got EOF")))) | |
57 | (.append ast (read-form rdr)) | |
58 | (setv token (.peek rdr))) | |
59 | (.next rdr) | |
60 | ast))) | |
61 | ||
62 | (defn read-form [rdr] | |
63 | (setv token (.peek rdr)) | |
64 | (if | |
65 | (= ";" (get token 0)) (.next rdr) | |
66 | ||
67 | (= "'" token) (do (.next rdr) | |
68 | (tuple [(Sym "quote") (read-form rdr)])) | |
69 | (= "`" token) (do (.next rdr) | |
70 | (tuple [(Sym "quasiquote") (read-form rdr)])) | |
71 | (= "~" token) (do (.next rdr) | |
72 | (tuple [(Sym "unquote") (read-form rdr)])) | |
73 | (= "~@" token) (do (.next rdr) | |
74 | (tuple [(Sym "splice-unquote") | |
75 | (read-form rdr)])) | |
76 | (= "^" token) (do (.next rdr) | |
77 | (setv meta (read-form rdr)) | |
78 | (tuple [(Sym "with-meta") (read-form rdr) meta])) | |
79 | (= "@" token) (do (.next rdr) | |
80 | (tuple [(Sym "deref") (read-form rdr)])) | |
81 | ||
82 | (= ")" token) (raise (Exception "unexpected ')'")) | |
83 | (= "(" token) (tuple (read-seq rdr "(" ")")) | |
84 | ||
85 | (= "]" token) (raise (Exception "unexpected ')'")) | |
86 | (= "[" token) (read-seq rdr "[" "]") | |
87 | ||
88 | (= "}" token) (raise (Exception "unexpected '}'")) | |
081c3223 | 89 | (= "{" token) (dict (partition (read-seq rdr "{" "}") 2)) |
58ff8110 JM |
90 | |
91 | True (read-atom rdr))) | |
92 | ||
93 | (defn read-str [str] | |
94 | (setv tokens (tokenize str)) | |
95 | (if (= 0 (len tokens)) (raise (Blank "blank line"))) | |
96 | (read-form (Reader tokens))) |